From 406abd7c4df1ace2cd3e4e17159e8941a2e8c0c4 Mon Sep 17 00:00:00 2001
From: Tristan Zur <tzur@webserver.ccwn.org>
Date: Wed, 10 Jun 2015 20:55:53 +0200
Subject: Initial import

---
 .gitignore                                         |    1 +
 .htaccess                                          |   82 +
 LICENSE                                            |  340 +
 README                                             |   85 +
 application/Bootstrap.php                          |   67 +
 application/config/config.php                      |  156 +
 bin/.htaccess                                      |    8 +
 bin/README                                         |    5 +
 index.php                                          |  116 +
 installer/cli.php                                  |  121 +
 installer/database_config.php                      |   46 +
 installer/index.php                                |   40 +
 installer/init_var.php                             |   12 +
 installer/install.css                              |   92 +
 installer/install.sql                              |  433 ++
 installer/installer.php                            |  270 +
 installer/views/already_installed.html.php         |    5 +
 installer/views/db_not_empty.html.php              |    8 +
 installer/views/environment_errors.html.php        |   20 +
 installer/views/get_db_info.html.php               |   89 +
 installer/views/install.html.php                   |   24 +
 installer/views/invalid_db_info.html.php           |    6 +
 installer/views/invalid_db_version.html.php        |    5 +
 installer/views/missing_db.html.php                |   13 +
 installer/views/oops.html.php                      |   10 +
 installer/views/success.html.php                   |   23 +
 installer/web.php                                  |   94 +
 lib/flowplayer.controls.swf.php                    |   31 +
 lib/flowplayer.js                                  |  228 +
 lib/flowplayer.pseudostreaming-byterange.swf.php   |   31 +
 lib/flowplayer.pseudostreaming.swf.php             |   31 +
 lib/flowplayer.swf.php                             |   47 +
 lib/gallery.ajax.js                                |   15 +
 lib/gallery.common.js                              |  253 +
 lib/gallery.dialog.js                              |  221 +
 lib/gallery.in_place_edit.js                       |   75 +
 lib/gallery.panel.js                               |  100 +
 lib/gallery.show_full_size.js                      |   58 +
 lib/images/Galerie-Logo.png                        |  Bin 0 -> 4047 bytes
 lib/images/apple-touch-icon.png                    |  Bin 0 -> 4441 bytes
 lib/images/favicon.ico                             |  Bin 0 -> 1150 bytes
 lib/images/logo.png                                |  Bin 0 -> 10222 bytes
 lib/jquery-ui.js                                   |  328 +
 lib/jquery.MultiFile.js                            |   11 +
 lib/jquery.autocomplete.css                        |   49 +
 lib/jquery.autocomplete.js                         |   13 +
 lib/jquery.cookie.js                               |   96 +
 lib/jquery.form.js                                 |  645 ++
 lib/jquery.jeditable.js                            |   32 +
 lib/jquery.js                                      |   19 +
 lib/jquery.localscroll.js                          |    9 +
 lib/jquery.scrollTo.js                             |   11 +
 lib/json2-min.js                                   |   39 +
 lib/superfish/css/superfish.css                    |  136 +
 lib/superfish/images/arrows-ffffff-rtl.png         |  Bin 0 -> 378 bytes
 lib/superfish/images/arrows-ffffff.png             |  Bin 0 -> 244 bytes
 lib/superfish/images/shadow.png                    |  Bin 0 -> 1698 bytes
 lib/superfish/js/superfish.js                      |  121 +
 lib/swfobject.js                                   |    4 +
 lib/uploadify/cancel.png                           |  Bin 0 -> 603 bytes
 lib/uploadify/jquery.uploadify.min.js              |   37 +
 lib/uploadify/uploadify.allglyphs.swf.php          |   47 +
 lib/uploadify/uploadify.css                        |   58 +
 lib/uploadify/uploadify.fla                        |  Bin 0 -> 125952 bytes
 lib/uploadify/uploadify.swf.php                    |   47 +
 lib/yui/base-min.css                               |    7 +
 lib/yui/reset-fonts-grids.css                      |    7 +
 modules/akismet/controllers/admin_akismet.php      |   67 +
 modules/akismet/helpers/akismet.php                |  193 +
 modules/akismet/helpers/akismet_event.php          |   70 +
 modules/akismet/helpers/akismet_installer.php      |   28 +
 modules/akismet/module.info                        |    7 +
 modules/akismet/views/admin_akismet.html.php       |   18 +
 modules/akismet/views/admin_akismet_stats.html.php |   11 +
 modules/calendarview/controllers/calendarview.php  |  296 +
 modules/calendarview/css/calendarview_calendar.css |   59 +
 modules/calendarview/css/calendarview_menu.css     |    3 +
 modules/calendarview/helpers/calendarview.php      |   48 +
 .../calendarview/helpers/calendarview_block.php    |   72 +
 .../calendarview/helpers/calendarview_event.php    |   99 +
 .../helpers/calendarview_installer.php             |   40 +
 .../calendarview/helpers/calendarview_theme.php    |   25 +
 .../calendarview/images/ico-view-calendarview.png  |  Bin 0 -> 4191 bytes
 modules/calendarview/libraries/PHPCalendar.php     |   87 +
 modules/calendarview/module.info                   |    7 +
 .../views/calendarview_sidebar.html.php            |    9 +
 .../calendarview/views/calendarview_year.html.php  |   95 +
 .../views/user_profile_calendarview.html.php       |   86 +
 modules/comment/controllers/admin_comments.php     |   60 +
 .../comment/controllers/admin_manage_comments.php  |  144 +
 modules/comment/controllers/comments.php           |   81 +
 modules/comment/css/comment.css                    |   45 +
 modules/comment/helpers/comment.php                |   71 +
 modules/comment/helpers/comment_block.php          |   39 +
 modules/comment/helpers/comment_event.php          |   97 +
 modules/comment/helpers/comment_installer.php      |  118 +
 modules/comment/helpers/comment_rest.php           |   74 +
 modules/comment/helpers/comment_rss.php            |   92 +
 modules/comment/helpers/comment_theme.php          |   46 +
 modules/comment/helpers/comments_rest.php          |   62 +
 modules/comment/helpers/item_comments_rest.php     |   50 +
 modules/comment/js/comment.js                      |   45 +
 modules/comment/models/comment.php                 |  194 +
 modules/comment/module.info                        |    7 +
 .../views/admin_block_recent_comments.html.php     |   23 +
 modules/comment/views/admin_comments.html.php      |    7 +
 .../comment/views/admin_manage_comments.html.php   |   46 +
 .../views/admin_manage_comments_queue.html.php     |  157 +
 modules/comment/views/comment.html.php             |   25 +
 modules/comment/views/comment.mrss.php             |   43 +
 modules/comment/views/comments.html.php            |   56 +
 .../comment/views/user_profile_comments.html.php   |   20 +
 .../downloadalbum/controllers/downloadalbum.php    |  300 +
 modules/downloadalbum/css/downloadalbum_menu.css   |    3 +
 .../downloadalbum/helpers/downloadalbum_event.php  |   40 +
 .../downloadalbum/helpers/downloadalbum_theme.php  |   24 +
 .../images/ico-view-downloadalbum.png              |  Bin 0 -> 4125 bytes
 modules/downloadalbum/module.info                  |    7 +
 .../controllers/admin_downloadfullsize.php         |   93 +
 .../controllers/downloadfullsize.php               |   37 +
 .../downloadfullsize/css/downloadfullsize_menu.css |    3 +
 .../helpers/downloadfullsize_block.php             |   51 +
 .../helpers/downloadfullsize_event.php             |   57 +
 .../helpers/downloadfullsize_theme.php             |   26 +
 .../images/ico-view-downloadfullsize.png           |  Bin 0 -> 4125 bytes
 modules/downloadfullsize/module.info               |    7 +
 .../views/admin_downloadfullsize.html.php          |    5 +
 .../views/downloadfullsize_block.html.php          |   18 +
 modules/exif/controllers/exif.php                  |   33 +
 modules/exif/helpers/exif.php                      |  167 +
 modules/exif/helpers/exif_event.php                |   39 +
 modules/exif/helpers/exif_installer.php            |   45 +
 modules/exif/helpers/exif_task.php                 |   88 +
 modules/exif/helpers/exif_theme.php                |   38 +
 modules/exif/lib/exif.php                          | 1135 ++++
 modules/exif/lib/makers/canon.php                  |  426 ++
 modules/exif/lib/makers/fujifilm.php               |  247 +
 modules/exif/lib/makers/gps.php                    |  218 +
 modules/exif/lib/makers/nikon.php                  |  411 ++
 modules/exif/lib/makers/olympus.php                |  189 +
 modules/exif/lib/makers/panasonic.php              |  292 +
 modules/exif/lib/makers/sanyo.php                  |  158 +
 modules/exif/models/exif_key.php                   |   21 +
 modules/exif/models/exif_record.php                |   21 +
 modules/exif/module.info                           |    7 +
 modules/exif/views/exif_dialog.html.php            |   33 +
 modules/exif/views/exif_sidebar.html.php           |    6 +
 modules/familygallery/controllers/login.php.backup |   10 +
 .../familygallery/helpers/familygallery_event.php  |   20 +
 modules/familygallery/module.info                  |    7 +
 modules/forge/libraries/Forge.php                  |  323 +
 modules/forge/libraries/Form_Checkbox.php          |   83 +
 modules/forge/libraries/Form_Checklist.php         |   92 +
 modules/forge/libraries/Form_Dateselect.php        |  138 +
 modules/forge/libraries/Form_Dropdown.php          |   78 +
 modules/forge/libraries/Form_Group.php             |   89 +
 modules/forge/libraries/Form_Hidden.php            |   25 +
 modules/forge/libraries/Form_Input.php             |  555 ++
 modules/forge/libraries/Form_Password.php          |   23 +
 modules/forge/libraries/Form_Phonenumber.php       |   98 +
 modules/forge/libraries/Form_Radio.php             |   22 +
 modules/forge/libraries/Form_Submit.php            |   30 +
 modules/forge/libraries/Form_Textarea.php          |   31 +
 modules/forge/libraries/Form_Upload.php            |  191 +
 modules/g2_import/controllers/admin_g2_import.php  |  136 +
 modules/g2_import/controllers/g2.php               |  121 +
 modules/g2_import/data/broken-image.gif            |  Bin 0 -> 1589 bytes
 modules/g2_import/helpers/g2_import.php            | 1375 ++++
 modules/g2_import/helpers/g2_import_event.php      |   40 +
 modules/g2_import/helpers/g2_import_installer.php  |   50 +
 modules/g2_import/helpers/g2_import_task.php       |  225 +
 .../g2_import/libraries/G2_Import_Exception.php    |   39 +
 modules/g2_import/models/g2_map.php                |   21 +
 modules/g2_import/module.info                      |    7 +
 modules/g2_import/views/admin_g2_import.html.php   |  150 +
 modules/gallery/config/cache.php                   |   50 +
 modules/gallery/config/cookie.php                  |   48 +
 modules/gallery/config/database.php                |   23 +
 modules/gallery/config/locale.php                  |   51 +
 modules/gallery/config/log_file.php                |   29 +
 modules/gallery/config/routes.php                  |   32 +
 modules/gallery/config/session.php                 |   66 +
 modules/gallery/config/upload.php                  |   36 +
 modules/gallery/config/user_agents.php             |   25 +
 modules/gallery/controllers/admin.php              |   94 +
 .../controllers/admin_advanced_settings.php        |   57 +
 modules/gallery/controllers/admin_dashboard.php    |   97 +
 modules/gallery/controllers/admin_graphics.php     |   50 +
 modules/gallery/controllers/admin_languages.php    |  135 +
 modules/gallery/controllers/admin_maintenance.php  |  243 +
 modules/gallery/controllers/admin_modules.php      |  119 +
 modules/gallery/controllers/admin_movies.php       |   72 +
 modules/gallery/controllers/admin_sidebar.php      |   69 +
 .../gallery/controllers/admin_theme_options.php    |  120 +
 modules/gallery/controllers/admin_themes.php       |   80 +
 .../gallery/controllers/admin_upgrade_checker.php  |   57 +
 modules/gallery/controllers/albums.php             |  207 +
 modules/gallery/controllers/combined.php           |   96 +
 modules/gallery/controllers/file_proxy.php         |  174 +
 modules/gallery/controllers/items.php              |   43 +
 modules/gallery/controllers/l10n_client.php        |  179 +
 modules/gallery/controllers/login.php              |   90 +
 modules/gallery/controllers/logout.php             |   29 +
 modules/gallery/controllers/movies.php             |   91 +
 modules/gallery/controllers/packager.php           |  191 +
 modules/gallery/controllers/permissions.php        |   91 +
 modules/gallery/controllers/photos.php             |   91 +
 modules/gallery/controllers/quick.php              |  144 +
 modules/gallery/controllers/reauthenticate.php     |  105 +
 modules/gallery/controllers/upgrader.php           |  118 +
 modules/gallery/controllers/uploader.php           |  133 +
 modules/gallery/controllers/user_profile.php       |  108 +
 modules/gallery/controllers/welcome_message.php    |   30 +
 modules/gallery/css/debug.css                      |   28 +
 modules/gallery/css/gallery.css                    |  213 +
 modules/gallery/css/l10n_client.css                |  206 +
 modules/gallery/css/upgrader.css                   |  183 +
 modules/gallery/helpers/MY_html.php                |   91 +
 modules/gallery/helpers/MY_num.php                 |   54 +
 modules/gallery/helpers/MY_remote.php              |  167 +
 modules/gallery/helpers/MY_url.php                 |   92 +
 modules/gallery/helpers/MY_valid.php               |   26 +
 modules/gallery/helpers/access.php                 |  758 +++
 modules/gallery/helpers/ajax.php                   |   31 +
 modules/gallery/helpers/album.php                  |  126 +
 modules/gallery/helpers/auth.php                   |  134 +
 modules/gallery/helpers/batch.php                  |   40 +
 modules/gallery/helpers/block_manager.php          |  115 +
 modules/gallery/helpers/data_rest.php              |  115 +
 modules/gallery/helpers/dir.php                    |   40 +
 modules/gallery/helpers/encoding.php               |   35 +
 modules/gallery/helpers/gallery.php                |  233 +
 modules/gallery/helpers/gallery_block.php          |  145 +
 modules/gallery/helpers/gallery_error.php          |   30 +
 modules/gallery/helpers/gallery_event.php          |  621 ++
 modules/gallery/helpers/gallery_graphics.php       |  183 +
 modules/gallery/helpers/gallery_installer.php      |  844 +++
 modules/gallery/helpers/gallery_rss.php            |   76 +
 modules/gallery/helpers/gallery_task.php           |  826 +++
 modules/gallery/helpers/gallery_theme.php          |  151 +
 modules/gallery/helpers/graphics.php               |  546 ++
 modules/gallery/helpers/identity.php               |  247 +
 modules/gallery/helpers/item.php                   |  433 ++
 modules/gallery/helpers/item_rest.php              |  210 +
 modules/gallery/helpers/items_rest.php             |   96 +
 modules/gallery/helpers/json.php                   |   31 +
 modules/gallery/helpers/l10n_client.php            |  323 +
 modules/gallery/helpers/l10n_scanner.php           |  178 +
 modules/gallery/helpers/legal_file.php             |  310 +
 modules/gallery/helpers/locales.php                |  264 +
 modules/gallery/helpers/log.php                    |  108 +
 modules/gallery/helpers/message.php                |  109 +
 modules/gallery/helpers/model_cache.php            |   42 +
 modules/gallery/helpers/module.php                 |  594 ++
 modules/gallery/helpers/movie.php                  |  282 +
 modules/gallery/helpers/photo.php                  |  145 +
 modules/gallery/helpers/random.php                 |   48 +
 modules/gallery/helpers/site_status.php            |  132 +
 modules/gallery/helpers/system.php                 |  113 +
 modules/gallery/helpers/task.php                   |  113 +
 modules/gallery/helpers/theme.php                  |  113 +
 modules/gallery/helpers/tree_rest.php              |   92 +
 modules/gallery/helpers/upgrade_checker.php        |  105 +
 modules/gallery/helpers/user_profile.php           |   55 +
 modules/gallery/helpers/xml.php                    |   35 +
 modules/gallery/hooks/init_gallery.php             |   56 +
 modules/gallery/images/ffmpeg.png                  |  Bin 0 -> 2888 bytes
 modules/gallery/images/gallery.png                 |  Bin 0 -> 22178 bytes
 modules/gallery/images/gd.png                      |  Bin 0 -> 5531 bytes
 modules/gallery/images/graphicsmagick.png          |  Bin 0 -> 1486 bytes
 modules/gallery/images/imagemagick.jpg             |  Bin 0 -> 20337 bytes
 modules/gallery/images/missing_album_cover.jpg     |  Bin 0 -> 4453 bytes
 modules/gallery/images/missing_movie.jpg           |  Bin 0 -> 3428 bytes
 modules/gallery/images/missing_photo.jpg           |  Bin 0 -> 2034 bytes
 modules/gallery/js/albums_form_add.js              |   25 +
 modules/gallery/js/item_form_delete.js             |    5 +
 modules/gallery/js/l10n_client.js                  |  315 +
 modules/gallery/libraries/Admin_View.php           |  120 +
 modules/gallery/libraries/Block.php                |   30 +
 modules/gallery/libraries/Breadcrumb.php           |   70 +
 modules/gallery/libraries/Form_Script.php          |   66 +
 modules/gallery/libraries/Form_Uploadify.php       |   72 +
 .../gallery/libraries/Form_Uploadify_buttons.php   |   25 +
 modules/gallery/libraries/Gallery_I18n.php         |  472 ++
 modules/gallery/libraries/Gallery_View.php         |  243 +
 modules/gallery/libraries/IdentityProvider.php     |  283 +
 modules/gallery/libraries/InPlaceEdit.php          |   91 +
 modules/gallery/libraries/MY_Database.php          |  101 +
 modules/gallery/libraries/MY_Forge.php             |   45 +
 modules/gallery/libraries/MY_Input.php             |   31 +
 modules/gallery/libraries/MY_Kohana_Exception.php  |  101 +
 modules/gallery/libraries/MY_ORM.php               |   52 +
 modules/gallery/libraries/MY_View.php              |   85 +
 modules/gallery/libraries/Menu.php                 |  257 +
 modules/gallery/libraries/ORM_MPTT.php             |  341 +
 modules/gallery/libraries/SafeString.php           |  162 +
 modules/gallery/libraries/Sendmail.php             |   98 +
 modules/gallery/libraries/Task_Definition.php      |   50 +
 modules/gallery/libraries/Theme_View.php           |  271 +
 .../gallery/libraries/drivers/Cache/Database.php   |  166 +
 .../gallery/libraries/drivers/IdentityProvider.php |  134 +
 modules/gallery/models/access_cache.php            |   21 +
 modules/gallery/models/access_intent.php           |   21 +
 modules/gallery/models/cache.php                   |   20 +
 modules/gallery/models/failed_auth.php             |   20 +
 modules/gallery/models/graphics_rule.php           |   21 +
 modules/gallery/models/incoming_translation.php    |   21 +
 modules/gallery/models/item.php                    | 1191 ++++
 modules/gallery/models/log.php                     |   38 +
 modules/gallery/models/message.php                 |   21 +
 modules/gallery/models/module.php                  |   21 +
 modules/gallery/models/outgoing_translation.php    |   21 +
 modules/gallery/models/permission.php              |   21 +
 modules/gallery/models/task.php                    |   86 +
 modules/gallery/models/theme.php                   |   21 +
 modules/gallery/models/var.php                     |   21 +
 modules/gallery/module.info                        |    7 +
 modules/gallery/vendor/joomla/crypt.php            |  151 +
 .../gallery/views/admin_advanced_settings.html.php |   57 +
 .../gallery/views/admin_block_log_entries.html.php |   15 +
 modules/gallery/views/admin_block_news.html.php    |   11 +
 .../views/admin_block_photo_stream.html.php        |   14 +
 .../gallery/views/admin_block_platform.html.php    |   24 +
 modules/gallery/views/admin_block_stats.html.php   |   12 +
 modules/gallery/views/admin_block_welcome.html.php |   20 +
 modules/gallery/views/admin_dashboard.html.php     |   43 +
 modules/gallery/views/admin_graphics.html.php      |   40 +
 modules/gallery/views/admin_graphics_gd.html.php   |   30 +
 .../views/admin_graphics_graphicsmagick.html.php   |   21 +
 .../views/admin_graphics_imagemagick.html.php      |   21 +
 modules/gallery/views/admin_graphics_none.html.php |    8 +
 modules/gallery/views/admin_languages.html.php     |  118 +
 modules/gallery/views/admin_maintenance.html.php   |  212 +
 .../views/admin_maintenance_show_log.html.php      |   19 +
 .../gallery/views/admin_maintenance_task.html.php  |   84 +
 modules/gallery/views/admin_modules.html.php       |  129 +
 .../gallery/views/admin_modules_confirm.html.php   |   22 +
 modules/gallery/views/admin_movies.html.php        |   44 +
 modules/gallery/views/admin_sidebar.html.php       |   64 +
 .../gallery/views/admin_sidebar_blocks.html.php    |    5 +
 modules/gallery/views/admin_theme_options.html.php |    7 +
 modules/gallery/views/admin_themes.html.php        |   98 +
 .../gallery/views/admin_themes_buttonset.html.php  |   48 +
 .../gallery/views/admin_themes_preview.html.php    |    8 +
 modules/gallery/views/error.html.php               |   12 +
 modules/gallery/views/error_404.html.php           |   26 +
 modules/gallery/views/error_admin.html.php         |  307 +
 modules/gallery/views/error_cli.txt.php            |    3 +
 modules/gallery/views/error_user.html.php          |   60 +
 modules/gallery/views/form.html.php                |   77 +
 modules/gallery/views/form_uploadify.html.php      |  167 +
 .../gallery/views/form_uploadify_buttons.html.php  |   11 +
 modules/gallery/views/in_place_edit.html.php       |   21 +
 modules/gallery/views/kohana/error.php             |   46 +
 modules/gallery/views/kohana_profiler.php          |   35 +
 modules/gallery/views/l10n_client.html.php         |   82 +
 modules/gallery/views/login_ajax.html.php          |   52 +
 modules/gallery/views/login_current_user.html.php  |    7 +
 modules/gallery/views/menu.html.php                |   24 +
 modules/gallery/views/menu_ajax_link.html.php      |   10 +
 modules/gallery/views/menu_dialog.html.php         |    9 +
 modules/gallery/views/menu_link.html.php           |    9 +
 modules/gallery/views/movieplayer.html.php         |   50 +
 modules/gallery/views/permissions_browse.html.php  |   62 +
 modules/gallery/views/permissions_form.html.php    |   92 +
 .../gallery/views/quick_delete_confirm.html.php    |   12 +
 modules/gallery/views/reauthenticate.html.php      |   15 +
 .../gallery/views/upgrade_checker_block.html.php   |   55 +
 modules/gallery/views/upgrader.html.php            |  163 +
 .../gallery/views/user_languages_block.html.php    |   19 +
 modules/gallery/views/user_profile.html.php        |   47 +
 modules/gallery/views/user_profile_info.html.php   |    9 +
 modules/gallery/views/welcome_message.html.php     |   36 +
 .../gallery/views/welcome_message_loader.html.php  |    7 +
 modules/greydragon/changelog.txt                   |   11 +
 modules/greydragon/css/gd_common.css               |   59 +
 modules/greydragon/images/blue-grad.png            |  Bin 0 -> 337 bytes
 modules/greydragon/module.info                     |    9 +
 modules/greydragon/views/gd_admin_include.html.php |  180 +
 modules/html5_uploader/controllers/uploader.php    |  126 +
 modules/html5_uploader/module.info                 |    7 +
 modules/image_block/controllers/image_block.php    |   27 +
 modules/image_block/helpers/image_block_block.php  |   56 +
 .../image_block/helpers/image_block_installer.php  |   43 +
 modules/image_block/module.info                    |    7 +
 .../image_block/views/image_block_block.html.php   |    8 +
 modules/info/helpers/info_block.php                |   93 +
 modules/info/helpers/info_installer.php            |   45 +
 modules/info/helpers/info_theme.php                |   41 +
 modules/info/module.info                           |    7 +
 modules/info/views/info_block.html.php             |    8 +
 modules/kbd_nav/changelog.txt                      |   47 +
 modules/kbd_nav/helpers/kbd_nav_theme.php          |    7 +
 modules/kbd_nav/js/kbd_nav.js                      |  120 +
 modules/kbd_nav/module.info                        |    8 +
 modules/kohana23_compat/config/pagination.php      |   27 +
 .../libraries/MY_Database_Builder.php              |   50 +
 modules/kohana23_compat/libraries/Pagination.php   |  252 +
 .../localprint/controllers/admin_localprint.php    |   26 +
 modules/localprint/css/localprint_menu.css         |   16 +
 modules/localprint/helpers/localprint_event.php    |   39 +
 .../localprint/helpers/localprint_installer.php    |   35 +
 modules/localprint/helpers/localprint_theme.php    |   27 +
 modules/localprint/images/localprint_logo.png      |  Bin 0 -> 2449 bytes
 modules/localprint/js/localprint.js                |    8 +
 modules/localprint/module.info                     |    3 +
 modules/localprint/views/admin_localprint.html.php |    4 +
 modules/localprint/views/localprint_code.html.php  |    9 +
 modules/notification/controllers/notification.php  |   36 +
 modules/notification/helpers/notification.php      |  218 +
 .../notification/helpers/notification_event.php    |  149 +
 .../helpers/notification_installer.php             |   54 +
 .../notification/models/pending_notification.php   |   21 +
 modules/notification/models/subscription.php       |   21 +
 modules/notification/module.info                   |    7 +
 .../notification/views/comment_published.html.php  |   35 +
 modules/notification/views/item_added.html.php     |   29 +
 modules/notification/views/item_deleted.html.php   |   25 +
 modules/notification/views/item_updated.html.php   |   35 +
 .../views/user_profile_notification.html.php       |   12 +
 modules/organize/controllers/organize.php          |  228 +
 modules/organize/css/organize_dialog.css           |   17 +
 modules/organize/css/organize_frame.css            |  118 +
 modules/organize/helpers/organize_event.php        |   54 +
 modules/organize/helpers/organize_installer.php    |   28 +
 modules/organize/module.info                       |    7 +
 modules/organize/vendor/ext/css/ext-all.css        | 6969 ++++++++++++++++++++
 modules/organize/vendor/ext/css/ux-all.css         |  772 +++
 .../vendor/ext/images/default/box/tb-blue.gif      |  Bin 0 -> 851 bytes
 .../vendor/ext/images/default/button/btn.gif       |  Bin 0 -> 4298 bytes
 .../vendor/ext/images/default/dd/drop-no.gif       |  Bin 0 -> 949 bytes
 .../vendor/ext/images/default/dd/drop-yes.gif      |  Bin 0 -> 1016 bytes
 .../vendor/ext/images/default/form/text-bg.gif     |  Bin 0 -> 819 bytes
 .../vendor/ext/images/default/form/trigger.gif     |  Bin 0 -> 1816 bytes
 .../ext/images/default/grid/invalid_line.gif       |  Bin 0 -> 815 bytes
 .../vendor/ext/images/default/grid/loading.gif     |  Bin 0 -> 771 bytes
 .../ext/images/default/panel/tool-sprites.gif      |  Bin 0 -> 4392 bytes
 .../ext/images/default/panel/white-top-bottom.gif  |  Bin 0 -> 872 bytes
 .../ext/images/default/progress/progress-bg.gif    |  Bin 0 -> 834 bytes
 .../organize/vendor/ext/images/default/qtip/bg.gif |  Bin 0 -> 1091 bytes
 modules/organize/vendor/ext/images/default/s.gif   |  Bin 0 -> 43 bytes
 .../vendor/ext/images/default/shadow-c.png         |  Bin 0 -> 118 bytes
 .../vendor/ext/images/default/shadow-lr.png        |  Bin 0 -> 135 bytes
 .../organize/vendor/ext/images/default/shadow.png  |  Bin 0 -> 311 bytes
 .../vendor/ext/images/default/toolbar/bg.gif       |  Bin 0 -> 904 bytes
 .../vendor/ext/images/default/tree/arrows.gif      |  Bin 0 -> 617 bytes
 .../vendor/ext/images/default/tree/drop-add.gif    |  Bin 0 -> 1001 bytes
 .../ext/images/default/tree/drop-between.gif       |  Bin 0 -> 907 bytes
 .../vendor/ext/images/default/tree/drop-over.gif   |  Bin 0 -> 911 bytes
 .../vendor/ext/images/default/tree/folder-open.gif |  Bin 0 -> 956 bytes
 .../vendor/ext/images/default/tree/folder.gif      |  Bin 0 -> 952 bytes
 .../vendor/ext/images/default/tree/loading.gif     |  Bin 0 -> 771 bytes
 .../ext/images/default/window/left-corners.png     |  Bin 0 -> 200 bytes
 .../ext/images/default/window/left-right.png       |  Bin 0 -> 152 bytes
 .../ext/images/default/window/right-corners.png    |  Bin 0 -> 256 bytes
 .../ext/images/default/window/top-bottom.png       |  Bin 0 -> 180 bytes
 modules/organize/vendor/ext/images/fam/delete.gif  |  Bin 0 -> 989 bytes
 .../organize/vendor/ext/js/ext-organize-bundle.js  | 2202 +++++++
 modules/organize/views/organize_dialog.html.php    |   23 +
 modules/organize/views/organize_frame.html.php     |  604 ++
 modules/recaptcha/controllers/admin_recaptcha.php  |   61 +
 modules/recaptcha/css/recaptcha.css                |    7 +
 modules/recaptcha/helpers/recaptcha.php            |  152 +
 modules/recaptcha/helpers/recaptcha_event.php      |   42 +
 modules/recaptcha/helpers/recaptcha_installer.php  |   28 +
 modules/recaptcha/helpers/recaptcha_theme.php      |   28 +
 modules/recaptcha/libraries/Form_Recaptcha.php     |   67 +
 modules/recaptcha/module.info                      |    7 +
 modules/recaptcha/views/admin_recaptcha.html.php   |   35 +
 modules/recaptcha/views/form_recaptcha.html.php    |   18 +
 modules/rest/controllers/rest.php                  |  121 +
 modules/rest/helpers/registry_rest.php             |   30 +
 modules/rest/helpers/rest.php                      |  191 +
 modules/rest/helpers/rest_event.php                |  102 +
 modules/rest/helpers/rest_installer.php            |   52 +
 modules/rest/libraries/Rest_Exception.php          |   37 +
 modules/rest/models/user_access_key.php            |   21 +
 modules/rest/module.info                           |    8 +
 modules/rest/views/error_rest.json.php             |    6 +
 modules/rest/views/reset_api_key_confirm.html.php  |    7 +
 modules/rest/views/user_profile_rest.html.php      |   13 +
 modules/rss/controllers/rss.php                    |   66 +
 modules/rss/helpers/rss.php                        |   36 +
 modules/rss/helpers/rss_block.php                  |   49 +
 modules/rss/module.info                            |    7 +
 modules/rss/views/feed.mrss.php                    |   79 +
 modules/rss/views/rss_block.html.php               |   13 +
 modules/search/controllers/search.php              |  123 +
 modules/search/helpers/search.php                  |  163 +
 modules/search/helpers/search_event.php            |   39 +
 modules/search/helpers/search_installer.php        |   50 +
 modules/search/helpers/search_task.php             |   84 +
 modules/search/helpers/search_theme.php            |   29 +
 modules/search/models/search_record.php            |   24 +
 modules/search/module.info                         |    7 +
 modules/search/views/search.html.php               |   65 +
 modules/search/views/search_link.html.php          |   22 +
 .../server_add/controllers/admin_server_add.php    |   97 +
 modules/server_add/controllers/server_add.php      |  315 +
 modules/server_add/css/server_add.css              |   38 +
 modules/server_add/helpers/server_add.php          |   49 +
 modules/server_add/helpers/server_add_event.php    |   42 +
 .../server_add/helpers/server_add_installer.php    |   73 +
 modules/server_add/helpers/server_add_theme.php    |   27 +
 modules/server_add/js/server_add.js                |  125 +
 modules/server_add/models/server_add_entry.php     |   21 +
 modules/server_add/module.info                     |    7 +
 modules/server_add/views/admin_server_add.html.php |   40 +
 modules/server_add/views/server_add_tree.html.php  |   37 +
 .../views/server_add_tree_dialog.html.php          |   52 +
 modules/slideshow/helpers/slideshow_event.php      |   80 +
 modules/slideshow/helpers/slideshow_installer.php  |   43 +
 modules/slideshow/helpers/slideshow_theme.php      |   26 +
 modules/slideshow/module.info                      |    7 +
 modules/tag/controllers/admin_tags.php             |  119 +
 modules/tag/controllers/tag.php                    |   96 +
 modules/tag/controllers/tag_name.php               |   33 +
 modules/tag/controllers/tags.php                   |   65 +
 modules/tag/css/tag.css                            |  102 +
 modules/tag/helpers/item_tags_rest.php             |   66 +
 modules/tag/helpers/tag.php                        |  181 +
 modules/tag/helpers/tag_block.php                  |   45 +
 modules/tag/helpers/tag_event.php                  |  165 +
 modules/tag/helpers/tag_installer.php              |   59 +
 modules/tag/helpers/tag_item_rest.php              |   51 +
 modules/tag/helpers/tag_items_rest.php             |   64 +
 modules/tag/helpers/tag_rest.php                   |   88 +
 modules/tag/helpers/tag_rss.php                    |   48 +
 modules/tag/helpers/tag_task.php                   |   97 +
 modules/tag/helpers/tag_theme.php                  |   31 +
 modules/tag/helpers/tags_rest.php                  |   77 +
 modules/tag/models/tag.php                         |  169 +
 modules/tag/module.info                            |    7 +
 modules/tag/views/admin_tags.html.php              |   59 +
 modules/tag/views/tag_block.html.php               |   30 +
 modules/tag/views/tag_cloud.html.php               |    9 +
 modules/thumbnav/changelog.log                     |   20 +
 modules/thumbnav/controllers/admin_thumbnav.php    |   65 +
 modules/thumbnav/css/thumbnav.css                  |   11 +
 modules/thumbnav/helpers/thumbnav_block.php        |   89 +
 modules/thumbnav/helpers/thumbnav_event.php        |   20 +
 modules/thumbnav/helpers/thumbnav_theme.php        |    8 +
 modules/thumbnav/module.info                       |    7 +
 modules/thumbnav/views/admin_include.html.php      |   95 +
 modules/thumbnav/views/admin_thumbnav.html.php     |   10 +
 modules/thumbnav/views/thumbnav_block.html.php     |    5 +
 modules/user/config/identity.php                   |   37 +
 modules/user/controllers/admin_users.php           |  442 ++
 modules/user/controllers/password.php              |  141 +
 modules/user/controllers/users.php                 |  239 +
 modules/user/css/user.css                          |  120 +
 modules/user/helpers/group.php                     |   82 +
 modules/user/helpers/user.php                      |  176 +
 modules/user/helpers/user_event.php                |   30 +
 modules/user/helpers/user_installer.php            |  142 +
 modules/user/helpers/user_theme.php                |   30 +
 modules/user/images/progressImg1.png               |  Bin 0 -> 390 bytes
 modules/user/js/password_strength.js               |   39 +
 modules/user/lib/PasswordHash.php                  |  248 +
 .../libraries/drivers/IdentityProvider/Gallery.php |  164 +
 modules/user/models/group.php                      |   89 +
 modules/user/models/user.php                       |  185 +
 modules/user/module.info                           |    8 +
 modules/user/views/admin_users.html.php            |  142 +
 .../user/views/admin_users_delete_user.html.php    |    7 +
 modules/user/views/admin_users_group.html.php      |   40 +
 modules/user/views/reset_password.html.php         |   18 +
 modules/watermark/controllers/admin_watermarks.php |  158 +
 modules/watermark/helpers/watermark.php            |   82 +
 modules/watermark/helpers/watermark_event.php      |   29 +
 modules/watermark/helpers/watermark_installer.php  |   42 +
 modules/watermark/module.info                      |    7 +
 modules/watermark/views/admin_watermarks.html.php  |   39 +
 php.ini                                            |   19 +
 robots.txt                                         |   14 +
 serveradd/Raphael_2013-10-18_optimiert.mpg         |  Bin 0 -> 31750148 bytes
 system/KohanaLicense.html                          |   30 +
 system/config/cache.php                            |   37 +
 system/config/cookie.php                           |   55 +
 system/config/credit_cards.php                     |   70 +
 system/config/database.php                         |   53 +
 system/config/encryption.php                       |   39 +
 system/config/http.php                             |   30 +
 system/config/image.php                            |   22 +
 system/config/inflector.php                        |   70 +
 system/config/locale.php                           |   26 +
 system/config/log.php                              |   35 +
 system/config/mimes.php                            |  228 +
 system/config/profiler.php                         |   16 +
 system/config/routes.php                           |   58 +
 system/config/session.php                          |   56 +
 system/config/sql_types.php                        |   99 +
 system/config/upload.php                           |   24 +
 system/config/user_agents.php                      |  120 +
 system/config/view.php                             |   25 +
 system/controllers/template.php                    |   54 +
 system/core/Benchmark.php                          |  126 +
 system/core/Event.php                              |  231 +
 system/core/Kohana.php                             | 1118 ++++
 system/core/Kohana_Config.php                      |  329 +
 system/core/Kohana_Exception.php                   |  622 ++
 system/helpers/arr.php                             |  273 +
 system/helpers/cookie.php                          |  149 +
 system/helpers/date.php                            |  395 ++
 system/helpers/db.php                              |   47 +
 system/helpers/download.php                        |  135 +
 system/helpers/expires.php                         |  129 +
 system/helpers/feed.php                            |  120 +
 system/helpers/file.php                            |  184 +
 system/helpers/form.php                            |  466 ++
 system/helpers/format.php                          |  112 +
 system/helpers/html.php                            |  364 +
 system/helpers/inflector.php                       |  252 +
 system/helpers/num.php                             |   24 +
 system/helpers/remote.php                          |   64 +
 system/helpers/request.php                         |  618 ++
 system/helpers/security.php                        |   35 +
 system/helpers/text.php                            |  596 ++
 system/helpers/upload.php                          |  157 +
 system/helpers/url.php                             |  264 +
 system/helpers/utf8.php                            |  744 +++
 system/helpers/valid.php                           |  453 ++
 system/libraries/Cache.php                         |  248 +
 system/libraries/Cache_Exception.php               |   11 +
 system/libraries/Controller.php                    |   44 +
 system/libraries/Database.php                      |  648 ++
 system/libraries/Database_Builder.php              | 1241 ++++
 system/libraries/Database_Cache_Result.php         |   81 +
 system/libraries/Database_Exception.php            |   15 +
 system/libraries/Database_Expression.php           |   23 +
 system/libraries/Database_Mysql.php                |  226 +
 system/libraries/Database_Mysql_Result.php         |  174 +
 system/libraries/Database_Mysqli.php               |   90 +
 system/libraries/Database_Mysqli_Result.php        |  175 +
 system/libraries/Database_Query.php                |   95 +
 system/libraries/Database_Result.php               |  170 +
 system/libraries/Encrypt.php                       |  176 +
 system/libraries/I18n.php                          |  100 +
 system/libraries/Image.php                         |  501 ++
 system/libraries/Input.php                         |  507 ++
 system/libraries/Kohana_404_Exception.php          |   56 +
 system/libraries/Kohana_Log.php                    |   90 +
 system/libraries/Kohana_PHP_Exception.php          |   99 +
 system/libraries/Kohana_User_Exception.php         |   30 +
 system/libraries/Model.php                         |   62 +
 system/libraries/ORM.php                           | 1528 +++++
 system/libraries/ORM_Iterator.php                  |  266 +
 system/libraries/ORM_Validation_Exception.php      |   24 +
 system/libraries/Profiler.php                      |  306 +
 system/libraries/Profiler_Table.php                |   67 +
 system/libraries/Router.php                        |  315 +
 system/libraries/Session.php                       |  500 ++
 system/libraries/URI.php                           |  279 +
 system/libraries/Validation.php                    |  815 +++
 system/libraries/View.php                          |  329 +
 system/libraries/drivers/Cache.php                 |   42 +
 system/libraries/drivers/Cache/File.php            |  255 +
 system/libraries/drivers/Cache/Memcache.php        |  132 +
 system/libraries/drivers/Cache/Xcache.php          |  161 +
 system/libraries/drivers/Config.php                |  257 +
 system/libraries/drivers/Config/Array.php          |   83 +
 system/libraries/drivers/Image.php                 |  158 +
 system/libraries/drivers/Image/GD.php              |  440 ++
 system/libraries/drivers/Image/GraphicsMagick.php  |  225 +
 system/libraries/drivers/Image/ImageMagick.php     |  233 +
 system/libraries/drivers/Log.php                   |   22 +
 system/libraries/drivers/Log/Database.php          |   40 +
 system/libraries/drivers/Log/File.php              |   44 +
 system/libraries/drivers/Log/Syslog.php            |   34 +
 system/libraries/drivers/Session.php               |   70 +
 system/libraries/drivers/Session/Cache.php         |  108 +
 system/libraries/drivers/Session/Cookie.php        |   83 +
 system/libraries/drivers/Session/Database.php      |  178 +
 system/messages/kohana/core.php                    |   37 +
 system/messages/validation/default.php             |   25 +
 system/views/kohana/error.php                      |  252 +
 system/views/kohana/error_disabled.php             |   19 +
 system/views/kohana/template.php                   |   36 +
 system/views/profiler/profiler.php                 |   37 +
 system/views/profiler/table.css                    |   53 +
 system/views/profiler/table.php                    |   24 +
 themes/admin_wind/css/fix-ie.css                   |   18 +
 themes/admin_wind/css/screen-rtl.css               |  400 ++
 themes/admin_wind/css/screen.css                   | 1058 +++
 .../images/ui-bg_flat_0_aaaaaa_40x100.png          |  Bin 0 -> 180 bytes
 .../images/ui-bg_flat_55_fbec88_40x100.png         |  Bin 0 -> 182 bytes
 .../images/ui-bg_glass_75_d0e5f5_1x400.png         |  Bin 0 -> 124 bytes
 .../images/ui-bg_glass_85_dfeffc_1x400.png         |  Bin 0 -> 123 bytes
 .../images/ui-bg_glass_95_fef1ec_1x400.png         |  Bin 0 -> 119 bytes
 .../images/ui-bg_gloss-wave_55_5c9ccc_500x100.png  |  Bin 0 -> 4033 bytes
 .../images/ui-bg_inset-hard_100_f5f8f9_1x100.png   |  Bin 0 -> 104 bytes
 .../images/ui-bg_inset-hard_100_fcfdfd_1x100.png   |  Bin 0 -> 88 bytes
 .../themeroller/images/ui-icons_217bc0_256x240.png |  Bin 0 -> 7638 bytes
 .../themeroller/images/ui-icons_2e83ff_256x240.png |  Bin 0 -> 7626 bytes
 .../themeroller/images/ui-icons_469bdd_256x240.png |  Bin 0 -> 5399 bytes
 .../themeroller/images/ui-icons_6da8d5_256x240.png |  Bin 0 -> 8447 bytes
 .../themeroller/images/ui-icons_cd0a0a_256x240.png |  Bin 0 -> 4379 bytes
 .../themeroller/images/ui-icons_d8e7f3_256x240.png |  Bin 0 -> 4379 bytes
 .../themeroller/images/ui-icons_f9bd01_256x240.png |  Bin 0 -> 4379 bytes
 themes/admin_wind/css/themeroller/ui.base.css      |    7 +
 themes/admin_wind/css/themeroller/ui.core.css      |   37 +
 .../admin_wind/css/themeroller/ui.datepicker.css   |   62 +
 themes/admin_wind/css/themeroller/ui.dialog.css    |   13 +
 .../admin_wind/css/themeroller/ui.progressbar.css  |    4 +
 themes/admin_wind/css/themeroller/ui.resizable.css |   13 +
 themes/admin_wind/css/themeroller/ui.tabs.css      |    9 +
 themes/admin_wind/css/themeroller/ui.theme.css     |  243 +
 themes/admin_wind/images/avatar.jpg                |  Bin 0 -> 1172 bytes
 themes/admin_wind/images/ico-denied-inactive.png   |  Bin 0 -> 604 bytes
 themes/admin_wind/images/ico-denied-passive.png    |  Bin 0 -> 916 bytes
 themes/admin_wind/images/ico-denied.png            |  Bin 0 -> 715 bytes
 themes/admin_wind/images/ico-error.png             |  Bin 0 -> 701 bytes
 themes/admin_wind/images/ico-info.png              |  Bin 0 -> 778 bytes
 themes/admin_wind/images/ico-lock.png              |  Bin 0 -> 749 bytes
 themes/admin_wind/images/ico-separator-rtl.gif     |  Bin 0 -> 106 bytes
 themes/admin_wind/images/ico-separator.gif         |  Bin 0 -> 106 bytes
 themes/admin_wind/images/ico-success-inactive.png  |  Bin 0 -> 476 bytes
 themes/admin_wind/images/ico-success-passive.png   |  Bin 0 -> 617 bytes
 themes/admin_wind/images/ico-success.png           |  Bin 0 -> 537 bytes
 themes/admin_wind/images/ico-warning.png           |  Bin 0 -> 666 bytes
 themes/admin_wind/images/loading-large.gif         |  Bin 0 -> 8238 bytes
 themes/admin_wind/images/loading-small.gif         |  Bin 0 -> 673 bytes
 themes/admin_wind/js/ui.init.js                    |   62 +
 themes/admin_wind/theme.info                       |   10 +
 themes/admin_wind/thumbnail.png                    |  Bin 0 -> 28330 bytes
 themes/admin_wind/views/admin.html.php             |  104 +
 themes/admin_wind/views/block.html.php             |   18 +
 themes/admin_wind/views/paginator.html.php         |   88 +
 .../admin/controllers/admin_theme_options.php      |  860 +++
 .../admin/views/admin_theme_options.html.php       |   38 +
 themes/greydragon/changelog.txt                    |  641 ++
 themes/greydragon/controllers/greydragon.php       |   14 +
 themes/greydragon/css/base.css                     |  322 +
 .../css/colorpacks/blackhawk/css/colors.css        |  169 +
 .../colorpacks/blackhawk/images/ajax-loading.gif   |  Bin 0 -> 4782 bytes
 .../css/colorpacks/blackhawk/images/colorpack.png  |  Bin 0 -> 307 bytes
 .../css/colorpacks/blackhawk/images/ico-album.png  |  Bin 0 -> 351 bytes
 .../css/colorpacks/blackhawk/images/ico-error.png  |  Bin 0 -> 701 bytes
 .../css/colorpacks/blackhawk/images/ico-help.png   |  Bin 0 -> 786 bytes
 .../css/colorpacks/blackhawk/images/ico-info.png   |  Bin 0 -> 778 bytes
 .../colorpacks/blackhawk/images/ico-warning.png    |  Bin 0 -> 666 bytes
 .../colorpacks/blackhawk/images/loading-large.gif  |  Bin 0 -> 8238 bytes
 .../colorpacks/blackhawk/images/loading-small.gif  |  Bin 0 -> 673 bytes
 .../css/colorpacks/blackhawk/images/search.png     |  Bin 0 -> 969 bytes
 .../css/colorpacks/blackhawk/images/ui-icons.png   |  Bin 0 -> 13169 bytes
 .../blackhawk/images/view-calendar-b.png           |  Bin 0 -> 653 bytes
 .../colorpacks/blackhawk/images/view-calendar.png  |  Bin 0 -> 429 bytes
 .../blackhawk/images/view-comments-b.png           |  Bin 0 -> 600 bytes
 .../colorpacks/blackhawk/images/view-comments.png  |  Bin 0 -> 492 bytes
 .../blackhawk/images/view-fullsize-b.png           |  Bin 0 -> 699 bytes
 .../colorpacks/blackhawk/images/view-fullsize.png  |  Bin 0 -> 407 bytes
 .../colorpacks/blackhawk/images/view-info-b.png    |  Bin 0 -> 493 bytes
 .../colorpacks/blackhawk/images/view-info-o.png    |  Bin 0 -> 259 bytes
 .../css/colorpacks/blackhawk/images/view-info.png  |  Bin 0 -> 938 bytes
 .../blackhawk/images/view-slideshow-b.png          |  Bin 0 -> 1179 bytes
 .../css/colorpacks/carbon/css/colors.css           |  188 +
 .../css/colorpacks/carbon/images/ajax-loading.gif  |  Bin 0 -> 4782 bytes
 .../css/colorpacks/carbon/images/colorpack.png     |  Bin 0 -> 286 bytes
 .../css/colorpacks/carbon/images/ico-album.png     |  Bin 0 -> 351 bytes
 .../css/colorpacks/carbon/images/ico-error.png     |  Bin 0 -> 701 bytes
 .../css/colorpacks/carbon/images/ico-help.png      |  Bin 0 -> 786 bytes
 .../css/colorpacks/carbon/images/ico-info.png      |  Bin 0 -> 778 bytes
 .../css/colorpacks/carbon/images/ico-warning.png   |  Bin 0 -> 666 bytes
 .../css/colorpacks/carbon/images/loading-large.gif |  Bin 0 -> 8238 bytes
 .../css/colorpacks/carbon/images/loading-small.gif |  Bin 0 -> 673 bytes
 .../css/colorpacks/carbon/images/search.png        |  Bin 0 -> 969 bytes
 .../css/colorpacks/carbon/images/section.png       |  Bin 0 -> 192 bytes
 .../css/colorpacks/carbon/images/ui-icons.png      |  Bin 0 -> 13162 bytes
 .../colorpacks/carbon/images/view-calendar-b.png   |  Bin 0 -> 653 bytes
 .../css/colorpacks/carbon/images/view-calendar.png |  Bin 0 -> 429 bytes
 .../colorpacks/carbon/images/view-comments-b.png   |  Bin 0 -> 600 bytes
 .../css/colorpacks/carbon/images/view-comments.png |  Bin 0 -> 492 bytes
 .../colorpacks/carbon/images/view-fullsize-b.png   |  Bin 0 -> 699 bytes
 .../css/colorpacks/carbon/images/view-fullsize.png |  Bin 0 -> 407 bytes
 .../css/colorpacks/carbon/images/view-info-b.png   |  Bin 0 -> 493 bytes
 .../css/colorpacks/carbon/images/view-info-o.png   |  Bin 0 -> 259 bytes
 .../css/colorpacks/carbon/images/view-info.png     |  Bin 0 -> 938 bytes
 .../colorpacks/carbon/images/view-slideshow-b.png  |  Bin 0 -> 1179 bytes
 .../css/colorpacks/greydragon/css/colors.css       |  173 +
 .../colorpacks/greydragon/images/ajax-loading.gif  |  Bin 0 -> 4782 bytes
 .../greydragon/images/background-bottom.gif        |  Bin 0 -> 1040 bytes
 .../greydragon/images/background-top.gif           |  Bin 0 -> 862 bytes
 .../colorpacks/greydragon/images/background.gif    |  Bin 0 -> 1098 bytes
 .../css/colorpacks/greydragon/images/colorpack.png |  Bin 0 -> 414 bytes
 .../css/colorpacks/greydragon/images/footer.png    |  Bin 0 -> 376 bytes
 .../css/colorpacks/greydragon/images/ico-album.png |  Bin 0 -> 351 bytes
 .../css/colorpacks/greydragon/images/ico-error.png |  Bin 0 -> 701 bytes
 .../css/colorpacks/greydragon/images/ico-help.png  |  Bin 0 -> 786 bytes
 .../css/colorpacks/greydragon/images/ico-info.png  |  Bin 0 -> 778 bytes
 .../colorpacks/greydragon/images/ico-warning.png   |  Bin 0 -> 666 bytes
 .../colorpacks/greydragon/images/image-thumb.gif   |  Bin 0 -> 830 bytes
 .../colorpacks/greydragon/images/loading-large.gif |  Bin 0 -> 8238 bytes
 .../colorpacks/greydragon/images/loading-small.gif |  Bin 0 -> 673 bytes
 .../css/colorpacks/greydragon/images/search.png    |  Bin 0 -> 969 bytes
 .../css/colorpacks/greydragon/images/section.png   |  Bin 0 -> 192 bytes
 .../css/colorpacks/greydragon/images/ui-icons.png  |  Bin 0 -> 13160 bytes
 .../greydragon/images/view-calendar-b.png          |  Bin 0 -> 653 bytes
 .../colorpacks/greydragon/images/view-calendar.png |  Bin 0 -> 429 bytes
 .../greydragon/images/view-comments-b.png          |  Bin 0 -> 600 bytes
 .../colorpacks/greydragon/images/view-comments.png |  Bin 0 -> 492 bytes
 .../greydragon/images/view-fullsize-b.png          |  Bin 0 -> 699 bytes
 .../colorpacks/greydragon/images/view-fullsize.png |  Bin 0 -> 407 bytes
 .../colorpacks/greydragon/images/view-info-b.png   |  Bin 0 -> 493 bytes
 .../colorpacks/greydragon/images/view-info-o.png   |  Bin 0 -> 259 bytes
 .../css/colorpacks/greydragon/images/view-info.png |  Bin 0 -> 938 bytes
 .../greydragon/images/view-slideshow-b.png         |  Bin 0 -> 1179 bytes
 .../css/colorpacks/roundrobin/css/colors.css       |  192 +
 .../colorpacks/roundrobin/images/ajax-loading.gif  |  Bin 0 -> 2545 bytes
 .../css/colorpacks/roundrobin/images/bg-body.jpg   |  Bin 0 -> 13916 bytes
 .../css/colorpacks/roundrobin/images/bg-header.jpg |  Bin 0 -> 13609 bytes
 .../css/colorpacks/roundrobin/images/colorpack.png |  Bin 0 -> 475 bytes
 .../css/colorpacks/roundrobin/images/gallery.png   |  Bin 0 -> 553 bytes
 .../css/colorpacks/roundrobin/images/ico-album.png |  Bin 0 -> 351 bytes
 .../css/colorpacks/roundrobin/images/ico-error.png |  Bin 0 -> 701 bytes
 .../css/colorpacks/roundrobin/images/ico-help.png  |  Bin 0 -> 786 bytes
 .../css/colorpacks/roundrobin/images/ico-info.png  |  Bin 0 -> 778 bytes
 .../colorpacks/roundrobin/images/ico-warning.png   |  Bin 0 -> 666 bytes
 .../colorpacks/roundrobin/images/loading-large.gif |  Bin 0 -> 8238 bytes
 .../colorpacks/roundrobin/images/loading-small.gif |  Bin 0 -> 673 bytes
 .../css/colorpacks/roundrobin/images/search.png    |  Bin 0 -> 550 bytes
 .../css/colorpacks/roundrobin/images/ui-icons.png  |  Bin 0 -> 14168 bytes
 .../roundrobin/images/view-calendar-b.png          |  Bin 0 -> 891 bytes
 .../colorpacks/roundrobin/images/view-calendar.png |  Bin 0 -> 260 bytes
 .../roundrobin/images/view-comments-b.png          |  Bin 0 -> 600 bytes
 .../colorpacks/roundrobin/images/view-comments.png |  Bin 0 -> 298 bytes
 .../roundrobin/images/view-fullsize-b.png          |  Bin 0 -> 670 bytes
 .../colorpacks/roundrobin/images/view-fullsize.png |  Bin 0 -> 275 bytes
 .../colorpacks/roundrobin/images/view-info-b.png   |  Bin 0 -> 698 bytes
 .../colorpacks/roundrobin/images/view-info-o.png   |  Bin 0 -> 259 bytes
 .../css/colorpacks/roundrobin/images/view-info.png |  Bin 0 -> 286 bytes
 .../roundrobin/images/view-slideshow-b.png         |  Bin 0 -> 1179 bytes
 .../css/colorpacks/slateblue/css/colors.css        |  176 +
 .../colorpacks/slateblue/images/ajax-loading.gif   |  Bin 0 -> 4782 bytes
 .../css/colorpacks/slateblue/images/background.jpg |  Bin 0 -> 907 bytes
 .../css/colorpacks/slateblue/images/colorpack.png  |  Bin 0 -> 414 bytes
 .../css/colorpacks/slateblue/images/footer.png     |  Bin 0 -> 376 bytes
 .../css/colorpacks/slateblue/images/ico-album.png  |  Bin 0 -> 351 bytes
 .../css/colorpacks/slateblue/images/ico-error.png  |  Bin 0 -> 701 bytes
 .../css/colorpacks/slateblue/images/ico-help.png   |  Bin 0 -> 786 bytes
 .../css/colorpacks/slateblue/images/ico-info.png   |  Bin 0 -> 778 bytes
 .../colorpacks/slateblue/images/ico-warning.png    |  Bin 0 -> 666 bytes
 .../colorpacks/slateblue/images/loading-large.gif  |  Bin 0 -> 8238 bytes
 .../colorpacks/slateblue/images/loading-small.gif  |  Bin 0 -> 673 bytes
 .../css/colorpacks/slateblue/images/search.png     |  Bin 0 -> 969 bytes
 .../css/colorpacks/slateblue/images/section.png    |  Bin 0 -> 192 bytes
 .../css/colorpacks/slateblue/images/ui-icons.png   |  Bin 0 -> 13160 bytes
 .../slateblue/images/view-calendar-b.png           |  Bin 0 -> 653 bytes
 .../colorpacks/slateblue/images/view-calendar.png  |  Bin 0 -> 429 bytes
 .../slateblue/images/view-comments-b.png           |  Bin 0 -> 600 bytes
 .../colorpacks/slateblue/images/view-comments.png  |  Bin 0 -> 492 bytes
 .../slateblue/images/view-fullsize-b.png           |  Bin 0 -> 699 bytes
 .../colorpacks/slateblue/images/view-fullsize.png  |  Bin 0 -> 407 bytes
 .../colorpacks/slateblue/images/view-info-b.png    |  Bin 0 -> 493 bytes
 .../colorpacks/slateblue/images/view-info-o.png    |  Bin 0 -> 259 bytes
 .../css/colorpacks/slateblue/images/view-info.png  |  Bin 0 -> 938 bytes
 .../slateblue/images/view-slideshow-b.png          |  Bin 0 -> 1179 bytes
 .../css/colorpacks/whitehawk/css/colors.css        |  172 +
 .../colorpacks/whitehawk/images/ajax-loading.gif   |  Bin 0 -> 2545 bytes
 .../css/colorpacks/whitehawk/images/colorpack.png  |  Bin 0 -> 417 bytes
 .../css/colorpacks/whitehawk/images/gallery.png    |  Bin 0 -> 1383 bytes
 .../css/colorpacks/whitehawk/images/ico-album.png  |  Bin 0 -> 351 bytes
 .../css/colorpacks/whitehawk/images/ico-error.png  |  Bin 0 -> 701 bytes
 .../css/colorpacks/whitehawk/images/ico-help.png   |  Bin 0 -> 786 bytes
 .../css/colorpacks/whitehawk/images/ico-info.png   |  Bin 0 -> 778 bytes
 .../colorpacks/whitehawk/images/ico-warning.png    |  Bin 0 -> 666 bytes
 .../colorpacks/whitehawk/images/loading-large.gif  |  Bin 0 -> 8238 bytes
 .../colorpacks/whitehawk/images/loading-small.gif  |  Bin 0 -> 673 bytes
 .../css/colorpacks/whitehawk/images/search.png     |  Bin 0 -> 571 bytes
 .../css/colorpacks/whitehawk/images/ui-icons.png   |  Bin 0 -> 9914 bytes
 .../whitehawk/images/view-calendar-b.png           |  Bin 0 -> 891 bytes
 .../colorpacks/whitehawk/images/view-calendar.png  |  Bin 0 -> 260 bytes
 .../whitehawk/images/view-comments-b.png           |  Bin 0 -> 600 bytes
 .../colorpacks/whitehawk/images/view-comments.png  |  Bin 0 -> 298 bytes
 .../whitehawk/images/view-fullsize-b.png           |  Bin 0 -> 670 bytes
 .../colorpacks/whitehawk/images/view-fullsize.png  |  Bin 0 -> 275 bytes
 .../colorpacks/whitehawk/images/view-info-b.png    |  Bin 0 -> 698 bytes
 .../colorpacks/whitehawk/images/view-info-o.png    |  Bin 0 -> 259 bytes
 .../css/colorpacks/whitehawk/images/view-info.png  |  Bin 0 -> 286 bytes
 .../whitehawk/images/view-slideshow-b.png          |  Bin 0 -> 1179 bytes
 .../greydragon/css/colorpacks/wind/css/colors.css  |  175 +
 .../css/colorpacks/wind/images/ajax-loading.gif    |  Bin 0 -> 2545 bytes
 .../css/colorpacks/wind/images/colorpack.png       |  Bin 0 -> 397 bytes
 .../css/colorpacks/wind/images/ico-album.png       |  Bin 0 -> 351 bytes
 .../css/colorpacks/wind/images/ico-error.png       |  Bin 0 -> 701 bytes
 .../css/colorpacks/wind/images/ico-help.png        |  Bin 0 -> 786 bytes
 .../css/colorpacks/wind/images/ico-info.png        |  Bin 0 -> 778 bytes
 .../colorpacks/wind/images/ico-view-fullsize.png   |  Bin 0 -> 1207 bytes
 .../wind/images/ico-view-slideshow-rtl.png         |  Bin 0 -> 1013 bytes
 .../colorpacks/wind/images/ico-view-slideshow.png  |  Bin 0 -> 854 bytes
 .../css/colorpacks/wind/images/ico-warning.png     |  Bin 0 -> 666 bytes
 .../css/colorpacks/wind/images/loading-large.gif   |  Bin 0 -> 8238 bytes
 .../css/colorpacks/wind/images/loading-small.gif   |  Bin 0 -> 673 bytes
 .../css/colorpacks/wind/images/section.png         |  Bin 0 -> 314 bytes
 .../css/colorpacks/wind/images/ui-icons.png        |  Bin 0 -> 10682 bytes
 .../css/colorpacks/wind/images/view-calendar.png   |  Bin 0 -> 637 bytes
 .../css/colorpacks/wind/images/view-comments-b.png |  Bin 0 -> 892 bytes
 .../css/colorpacks/wind/images/view-comments.png   |  Bin 0 -> 347 bytes
 .../css/colorpacks/wind/images/view-fullsize.png   |  Bin 0 -> 365 bytes
 .../css/colorpacks/wind/images/view-info-b.png     |  Bin 0 -> 698 bytes
 .../css/colorpacks/wind/images/view-info-o.png     |  Bin 0 -> 259 bytes
 .../css/colorpacks/wind/images/view-info.png       |  Bin 0 -> 383 bytes
 .../colorpacks/wind/images/view-slideshow-b.png    |  Bin 0 -> 1179 bytes
 themes/greydragon/css/custom.css                   |   61 +
 themes/greydragon/css/forms.css                    |  120 +
 .../css/framepacks/android/css/frame.css           |   32 +
 .../css/framepacks/android/images/thumb-dgt-e.png  |  Bin 0 -> 1482 bytes
 .../framepacks/android/images/thumb-dgt-eext.png   |  Bin 0 -> 1939 bytes
 .../framepacks/android/images/thumb-dgt-ext.png    |  Bin 0 -> 1791 bytes
 .../css/framepacks/android/images/thumb-dgt.png    |  Bin 0 -> 1447 bytes
 .../css/framepacks/android/images/thumb-flm-e.png  |  Bin 0 -> 1443 bytes
 .../framepacks/android/images/thumb-flm-eext.png   |  Bin 0 -> 1796 bytes
 .../framepacks/android/images/thumb-flm-ext.png    |  Bin 0 -> 1737 bytes
 .../css/framepacks/android/images/thumb-flm.png    |  Bin 0 -> 1413 bytes
 .../css/framepacks/android/images/thumb-sqr-e.png  |  Bin 0 -> 1579 bytes
 .../framepacks/android/images/thumb-sqr-eext.png   |  Bin 0 -> 1916 bytes
 .../framepacks/android/images/thumb-sqr-ext.png    |  Bin 0 -> 1900 bytes
 .../css/framepacks/android/images/thumb-sqr.png    |  Bin 0 -> 1544 bytes
 .../css/framepacks/android/images/thumb-wd-e.png   |  Bin 0 -> 1428 bytes
 .../framepacks/android/images/thumb-wd-eext.png    |  Bin 0 -> 1720 bytes
 .../css/framepacks/android/images/thumb-wd-ext.png |  Bin 0 -> 1659 bytes
 .../css/framepacks/android/images/thumb-wd.png     |  Bin 0 -> 1379 bytes
 .../greydragon/css/framepacks/book/css/frame.css   |   64 +
 .../css/framepacks/book/images/a-thumb-dgt-e.png   |  Bin 0 -> 1130 bytes
 .../framepacks/book/images/a-thumb-dgt-eext.png    |  Bin 0 -> 1579 bytes
 .../css/framepacks/book/images/a-thumb-dgt-ext.png |  Bin 0 -> 1513 bytes
 .../css/framepacks/book/images/a-thumb-dgt.png     |  Bin 0 -> 1062 bytes
 .../css/framepacks/book/images/a-thumb-flm-e.png   |  Bin 0 -> 1105 bytes
 .../framepacks/book/images/a-thumb-flm-eext.png    |  Bin 0 -> 1478 bytes
 .../css/framepacks/book/images/a-thumb-flm-ext.png |  Bin 0 -> 1300 bytes
 .../css/framepacks/book/images/a-thumb-flm.png     |  Bin 0 -> 1030 bytes
 .../css/framepacks/book/images/a-thumb-sqr-e.png   |  Bin 0 -> 1283 bytes
 .../framepacks/book/images/a-thumb-sqr-eext.png    |  Bin 0 -> 1863 bytes
 .../css/framepacks/book/images/a-thumb-sqr-ext.png |  Bin 0 -> 1733 bytes
 .../css/framepacks/book/images/a-thumb-sqr.png     |  Bin 0 -> 1225 bytes
 .../css/framepacks/book/images/a-thumb-wd-e.png    |  Bin 0 -> 1073 bytes
 .../css/framepacks/book/images/a-thumb-wd-eext.png |  Bin 0 -> 1371 bytes
 .../css/framepacks/book/images/a-thumb-wd-ext.png  |  Bin 0 -> 1265 bytes
 .../css/framepacks/book/images/a-thumb-wd.png      |  Bin 0 -> 991 bytes
 .../css/framepacks/book/images/thumb-dgt-e.png     |  Bin 0 -> 619 bytes
 .../css/framepacks/book/images/thumb-dgt-eext.png  |  Bin 0 -> 802 bytes
 .../css/framepacks/book/images/thumb-dgt-ext.png   |  Bin 0 -> 773 bytes
 .../css/framepacks/book/images/thumb-dgt.png       |  Bin 0 -> 575 bytes
 .../css/framepacks/book/images/thumb-flm-e.png     |  Bin 0 -> 613 bytes
 .../css/framepacks/book/images/thumb-flm-eext.png  |  Bin 0 -> 783 bytes
 .../css/framepacks/book/images/thumb-flm-ext.png   |  Bin 0 -> 625 bytes
 .../css/framepacks/book/images/thumb-flm.png       |  Bin 0 -> 587 bytes
 .../css/framepacks/book/images/thumb-sqr-e.png     |  Bin 0 -> 676 bytes
 .../css/framepacks/book/images/thumb-sqr-eext.png  |  Bin 0 -> 902 bytes
 .../css/framepacks/book/images/thumb-sqr-ext.png   |  Bin 0 -> 864 bytes
 .../css/framepacks/book/images/thumb-sqr.png       |  Bin 0 -> 648 bytes
 .../css/framepacks/book/images/thumb-wd-e.png      |  Bin 0 -> 600 bytes
 .../css/framepacks/book/images/thumb-wd-eext.png   |  Bin 0 -> 727 bytes
 .../css/framepacks/book/images/thumb-wd-ext.png    |  Bin 0 -> 695 bytes
 .../css/framepacks/book/images/thumb-wd.png        |  Bin 0 -> 575 bytes
 .../css/framepacks/darkglass/css/frame.css         |   32 +
 .../framepacks/darkglass/images/thumb-dgt-e.png    |  Bin 0 -> 1876 bytes
 .../framepacks/darkglass/images/thumb-dgt-eext.png |  Bin 0 -> 2132 bytes
 .../framepacks/darkglass/images/thumb-dgt-ext.png  |  Bin 0 -> 2097 bytes
 .../css/framepacks/darkglass/images/thumb-dgt.png  |  Bin 0 -> 1873 bytes
 .../framepacks/darkglass/images/thumb-flm-e.png    |  Bin 0 -> 1814 bytes
 .../framepacks/darkglass/images/thumb-flm-eext.png |  Bin 0 -> 2092 bytes
 .../framepacks/darkglass/images/thumb-flm-ext.png  |  Bin 0 -> 2048 bytes
 .../css/framepacks/darkglass/images/thumb-flm.png  |  Bin 0 -> 1811 bytes
 .../framepacks/darkglass/images/thumb-sqr-e.png    |  Bin 0 -> 1896 bytes
 .../framepacks/darkglass/images/thumb-sqr-eext.png |  Bin 0 -> 2220 bytes
 .../framepacks/darkglass/images/thumb-sqr-ext.png  |  Bin 0 -> 2187 bytes
 .../css/framepacks/darkglass/images/thumb-sqr.png  |  Bin 0 -> 3675 bytes
 .../css/framepacks/darkglass/images/thumb-wd-e.png |  Bin 0 -> 1787 bytes
 .../framepacks/darkglass/images/thumb-wd-eext.png  |  Bin 0 -> 2051 bytes
 .../framepacks/darkglass/images/thumb-wd-ext.png   |  Bin 0 -> 2006 bytes
 .../css/framepacks/darkglass/images/thumb-wd.png   |  Bin 0 -> 1767 bytes
 .../css/framepacks/greydragon/css/frame.css        |   43 +
 .../greydragon/css/framepacks/iphone/css/frame.css |   31 +
 .../css/framepacks/iphone/images/thumb-dgt-e.png   |  Bin 0 -> 2923 bytes
 .../framepacks/iphone/images/thumb-dgt-eext.png    |  Bin 0 -> 3544 bytes
 .../css/framepacks/iphone/images/thumb-dgt-ext.png |  Bin 0 -> 3449 bytes
 .../css/framepacks/iphone/images/thumb-dgt.png     |  Bin 0 -> 2813 bytes
 .../css/framepacks/iphone/images/thumb-flm-e.png   |  Bin 0 -> 2734 bytes
 .../framepacks/iphone/images/thumb-flm-eext.png    |  Bin 0 -> 3414 bytes
 .../css/framepacks/iphone/images/thumb-flm-ext.png |  Bin 0 -> 3272 bytes
 .../css/framepacks/iphone/images/thumb-flm.png     |  Bin 0 -> 2612 bytes
 .../css/framepacks/iphone/images/thumb-sqr-e.png   |  Bin 0 -> 2848 bytes
 .../framepacks/iphone/images/thumb-sqr-eext.png    |  Bin 0 -> 3930 bytes
 .../css/framepacks/iphone/images/thumb-sqr-ext.png |  Bin 0 -> 3850 bytes
 .../css/framepacks/iphone/images/thumb-sqr.png     |  Bin 0 -> 2759 bytes
 .../css/framepacks/iphone/images/thumb-wd-e.png    |  Bin 0 -> 2769 bytes
 .../css/framepacks/iphone/images/thumb-wd-eext.png |  Bin 0 -> 3108 bytes
 .../css/framepacks/iphone/images/thumb-wd-ext.png  |  Bin 0 -> 3012 bytes
 .../css/framepacks/iphone/images/thumb-wd.png      |  Bin 0 -> 2676 bytes
 .../greydragon/css/framepacks/iphoto/css/frame.css |   31 +
 .../css/framepacks/iphoto/images/thumb-dgt-e.png   |  Bin 0 -> 1093 bytes
 .../framepacks/iphoto/images/thumb-dgt-eext.png    |  Bin 0 -> 1294 bytes
 .../css/framepacks/iphoto/images/thumb-dgt-ext.png |  Bin 0 -> 1251 bytes
 .../css/framepacks/iphoto/images/thumb-dgt.png     |  Bin 0 -> 1065 bytes
 .../css/framepacks/iphoto/images/thumb-flm-e.png   |  Bin 0 -> 1071 bytes
 .../framepacks/iphoto/images/thumb-flm-eext.png    |  Bin 0 -> 1258 bytes
 .../css/framepacks/iphoto/images/thumb-flm-ext.png |  Bin 0 -> 1218 bytes
 .../css/framepacks/iphoto/images/thumb-flm.png     |  Bin 0 -> 1045 bytes
 .../css/framepacks/iphoto/images/thumb-sqr-e.png   |  Bin 0 -> 1141 bytes
 .../framepacks/iphoto/images/thumb-sqr-eext.png    |  Bin 0 -> 1382 bytes
 .../css/framepacks/iphoto/images/thumb-sqr-ext.png |  Bin 0 -> 1342 bytes
 .../css/framepacks/iphoto/images/thumb-sqr.png     |  Bin 0 -> 1110 bytes
 .../css/framepacks/iphoto/images/thumb-wd-e.png    |  Bin 0 -> 1056 bytes
 .../css/framepacks/iphoto/images/thumb-wd-eext.png |  Bin 0 -> 1209 bytes
 .../css/framepacks/iphoto/images/thumb-wd-ext.png  |  Bin 0 -> 1168 bytes
 .../css/framepacks/iphoto/images/thumb-wd.png      |  Bin 0 -> 1015 bytes
 .../css/framepacks/iphoto/views/frame.html.php     |    5 +
 .../greydragon/css/framepacks/panel/css/frame.css  |   37 +
 .../css/framepacks/roundcorners/css/frame.css      |   44 +
 .../greydragon/css/framepacks/simple/css/frame.css |   39 +
 .../greydragon/css/framepacks/wall/css/frame.css   |   48 +
 themes/greydragon/css/ipad.css                     |   20 +
 themes/greydragon/css/layout.css                   |   77 +
 themes/greydragon/css/menus.css                    |   58 +
 themes/greydragon/css/modules.css                  |  165 +
 themes/greydragon/css/normalize.css                |  431 ++
 themes/greydragon/css/rtl.css                      |   47 +
 themes/greydragon/css/screen.css                   |   17 +
 themes/greydragon/helpers/exif_event.php           |   45 +
 themes/greydragon/helpers/greydragon_event.php     |   92 +
 themes/greydragon/helpers/greydragon_installer.php |   30 +
 themes/greydragon/images/apple-touch-icon.png      |  Bin 0 -> 9420 bytes
 themes/greydragon/images/arrows_left.png           |  Bin 0 -> 1895 bytes
 themes/greydragon/images/arrows_right.png          |  Bin 0 -> 1826 bytes
 themes/greydragon/images/avatar.jpg                |  Bin 0 -> 1442 bytes
 themes/greydragon/images/blue-grad.png             |  Bin 0 -> 337 bytes
 themes/greydragon/images/button-grad-active-vs.png |  Bin 0 -> 152 bytes
 themes/greydragon/images/button-grad-vs.png        |  Bin 0 -> 155 bytes
 themes/greydragon/images/close.png                 |  Bin 0 -> 564 bytes
 themes/greydragon/images/donate.png                |  Bin 0 -> 399 bytes
 themes/greydragon/images/gallery.png               |  Bin 0 -> 627 bytes
 themes/greydragon/images/ico-allowed.png           |  Bin 0 -> 715 bytes
 themes/greydragon/images/ico-denied-inactive.png   |  Bin 0 -> 604 bytes
 themes/greydragon/images/ico-denied-passive.png    |  Bin 0 -> 916 bytes
 themes/greydragon/images/ico-denied.png            |  Bin 0 -> 715 bytes
 themes/greydragon/images/ico-error.png             |  Bin 0 -> 701 bytes
 themes/greydragon/images/ico-help.png              |  Bin 0 -> 786 bytes
 themes/greydragon/images/ico-info.png              |  Bin 0 -> 778 bytes
 themes/greydragon/images/ico-lock.png              |  Bin 0 -> 749 bytes
 themes/greydragon/images/ico-success-inactive.png  |  Bin 0 -> 261 bytes
 themes/greydragon/images/ico-success-passive.png   |  Bin 0 -> 561 bytes
 themes/greydragon/images/ico-success.png           |  Bin 0 -> 537 bytes
 themes/greydragon/images/ico-warning.png           |  Bin 0 -> 666 bytes
 themes/greydragon/images/missing-img.png           |  Bin 0 -> 33136 bytes
 themes/greydragon/js/gallery.ajax.custom.js        |   14 +
 themes/greydragon/js/gallery.dialog.custom.js      |  232 +
 themes/greydragon/js/jquery-ui.min.js              |    7 +
 themes/greydragon/js/jquery.cycle.js               | 1543 +++++
 themes/greydragon/js/jquery.form.custom.js         | 1076 +++
 themes/greydragon/js/jquery.json.min.js            |   31 +
 themes/greydragon/js/jquery.min.js                 |    4 +
 themes/greydragon/js/ui.support.js                 |   80 +
 themes/greydragon/libraries/MY_Theme_View.php      |  925 +++
 themes/greydragon/theme.info                       |   10 +
 themes/greydragon/thumbnail.png                    |  Bin 0 -> 25791 bytes
 themes/greydragon/views/album.html.php             |   68 +
 themes/greydragon/views/block.html.php             |   29 +
 themes/greydragon/views/calpage.html.php           |  257 +
 themes/greydragon/views/dynamic.html.php           |   38 +
 themes/greydragon/views/exif_sidebar.html.php      |   18 +
 themes/greydragon/views/info_block.html.php        |   29 +
 themes/greydragon/views/login_ajax.html.php        |   10 +
 themes/greydragon/views/movie.html.php             |   38 +
 themes/greydragon/views/no_sidebar.html.php        |   19 +
 themes/greydragon/views/page.html.php              |  267 +
 themes/greydragon/views/paginator.html.php         |  216 +
 themes/greydragon/views/photo.html.php             |  129 +
 themes/greydragon/views/rootpage.html.php          |   59 +
 themes/greydragon/views/rootpage.html.php_fix      |   46 +
 themes/greydragon/views/rss_block.html.php         |   30 +
 themes/greydragon/views/search.html.php            |   35 +
 themes/greydragon/views/sidebar.html.php           |   27 +
 themes/greydragon/views/user_profile.html.php      |   44 +
 .../admin/controllers/admin_theme_options.php      |  866 +++
 .../admin/views/admin_theme_options.html.php       |   38 +
 themes/greydragon_old/changelog.txt                |  616 ++
 themes/greydragon_old/controllers/greydragon.php   |   14 +
 themes/greydragon_old/css/base.css                 |  321 +
 .../css/colorpacks/blackhawk/css/colors.css        |  170 +
 .../colorpacks/blackhawk/images/ajax-loading.gif   |  Bin 0 -> 4782 bytes
 .../css/colorpacks/blackhawk/images/colorpack.png  |  Bin 0 -> 307 bytes
 .../css/colorpacks/blackhawk/images/ico-album.png  |  Bin 0 -> 351 bytes
 .../css/colorpacks/blackhawk/images/ico-error.png  |  Bin 0 -> 701 bytes
 .../css/colorpacks/blackhawk/images/ico-help.png   |  Bin 0 -> 786 bytes
 .../css/colorpacks/blackhawk/images/ico-info.png   |  Bin 0 -> 778 bytes
 .../colorpacks/blackhawk/images/ico-warning.png    |  Bin 0 -> 666 bytes
 .../colorpacks/blackhawk/images/loading-large.gif  |  Bin 0 -> 8238 bytes
 .../colorpacks/blackhawk/images/loading-small.gif  |  Bin 0 -> 673 bytes
 .../css/colorpacks/blackhawk/images/search.png     |  Bin 0 -> 969 bytes
 .../css/colorpacks/blackhawk/images/ui-icons.png   |  Bin 0 -> 13169 bytes
 .../blackhawk/images/view-calendar-b.png           |  Bin 0 -> 653 bytes
 .../colorpacks/blackhawk/images/view-calendar.png  |  Bin 0 -> 429 bytes
 .../blackhawk/images/view-comments-b.png           |  Bin 0 -> 600 bytes
 .../colorpacks/blackhawk/images/view-comments.png  |  Bin 0 -> 492 bytes
 .../blackhawk/images/view-fullsize-b.png           |  Bin 0 -> 699 bytes
 .../colorpacks/blackhawk/images/view-fullsize.png  |  Bin 0 -> 407 bytes
 .../colorpacks/blackhawk/images/view-info-b.png    |  Bin 0 -> 493 bytes
 .../colorpacks/blackhawk/images/view-info-o.png    |  Bin 0 -> 259 bytes
 .../css/colorpacks/blackhawk/images/view-info.png  |  Bin 0 -> 938 bytes
 .../blackhawk/images/view-slideshow-b.png          |  Bin 0 -> 1179 bytes
 .../css/colorpacks/carbon/css/colors.css           |  188 +
 .../css/colorpacks/carbon/images/ajax-loading.gif  |  Bin 0 -> 4782 bytes
 .../css/colorpacks/carbon/images/colorpack.png     |  Bin 0 -> 307 bytes
 .../css/colorpacks/carbon/images/ico-album.png     |  Bin 0 -> 351 bytes
 .../css/colorpacks/carbon/images/ico-error.png     |  Bin 0 -> 701 bytes
 .../css/colorpacks/carbon/images/ico-help.png      |  Bin 0 -> 786 bytes
 .../css/colorpacks/carbon/images/ico-info.png      |  Bin 0 -> 778 bytes
 .../css/colorpacks/carbon/images/ico-warning.png   |  Bin 0 -> 666 bytes
 .../css/colorpacks/carbon/images/loading-large.gif |  Bin 0 -> 8238 bytes
 .../css/colorpacks/carbon/images/loading-small.gif |  Bin 0 -> 673 bytes
 .../css/colorpacks/carbon/images/search.png        |  Bin 0 -> 969 bytes
 .../css/colorpacks/carbon/images/section.png       |  Bin 0 -> 192 bytes
 .../css/colorpacks/carbon/images/ui-icons.png      |  Bin 0 -> 13162 bytes
 .../colorpacks/carbon/images/view-calendar-b.png   |  Bin 0 -> 653 bytes
 .../css/colorpacks/carbon/images/view-calendar.png |  Bin 0 -> 429 bytes
 .../colorpacks/carbon/images/view-comments-b.png   |  Bin 0 -> 600 bytes
 .../css/colorpacks/carbon/images/view-comments.png |  Bin 0 -> 492 bytes
 .../colorpacks/carbon/images/view-fullsize-b.png   |  Bin 0 -> 699 bytes
 .../css/colorpacks/carbon/images/view-fullsize.png |  Bin 0 -> 407 bytes
 .../css/colorpacks/carbon/images/view-info-b.png   |  Bin 0 -> 493 bytes
 .../css/colorpacks/carbon/images/view-info-o.png   |  Bin 0 -> 259 bytes
 .../css/colorpacks/carbon/images/view-info.png     |  Bin 0 -> 938 bytes
 .../colorpacks/carbon/images/view-slideshow-b.png  |  Bin 0 -> 1179 bytes
 .../css/colorpacks/greydragon/css/colors.css       |  174 +
 .../colorpacks/greydragon/images/ajax-loading.gif  |  Bin 0 -> 4782 bytes
 .../greydragon/images/background-bottom.gif        |  Bin 0 -> 1040 bytes
 .../greydragon/images/background-top.gif           |  Bin 0 -> 862 bytes
 .../colorpacks/greydragon/images/background.gif    |  Bin 0 -> 1098 bytes
 .../css/colorpacks/greydragon/images/colorpack.png |  Bin 0 -> 414 bytes
 .../css/colorpacks/greydragon/images/footer.png    |  Bin 0 -> 376 bytes
 .../css/colorpacks/greydragon/images/ico-album.png |  Bin 0 -> 351 bytes
 .../css/colorpacks/greydragon/images/ico-error.png |  Bin 0 -> 701 bytes
 .../css/colorpacks/greydragon/images/ico-help.png  |  Bin 0 -> 786 bytes
 .../css/colorpacks/greydragon/images/ico-info.png  |  Bin 0 -> 778 bytes
 .../colorpacks/greydragon/images/ico-warning.png   |  Bin 0 -> 666 bytes
 .../colorpacks/greydragon/images/image-thumb.gif   |  Bin 0 -> 830 bytes
 .../colorpacks/greydragon/images/loading-large.gif |  Bin 0 -> 8238 bytes
 .../colorpacks/greydragon/images/loading-small.gif |  Bin 0 -> 673 bytes
 .../css/colorpacks/greydragon/images/search.png    |  Bin 0 -> 969 bytes
 .../css/colorpacks/greydragon/images/section.png   |  Bin 0 -> 192 bytes
 .../css/colorpacks/greydragon/images/ui-icons.png  |  Bin 0 -> 13160 bytes
 .../greydragon/images/view-calendar-b.png          |  Bin 0 -> 653 bytes
 .../colorpacks/greydragon/images/view-calendar.png |  Bin 0 -> 429 bytes
 .../greydragon/images/view-comments-b.png          |  Bin 0 -> 600 bytes
 .../colorpacks/greydragon/images/view-comments.png |  Bin 0 -> 492 bytes
 .../greydragon/images/view-fullsize-b.png          |  Bin 0 -> 699 bytes
 .../colorpacks/greydragon/images/view-fullsize.png |  Bin 0 -> 407 bytes
 .../colorpacks/greydragon/images/view-info-b.png   |  Bin 0 -> 493 bytes
 .../colorpacks/greydragon/images/view-info-o.png   |  Bin 0 -> 259 bytes
 .../css/colorpacks/greydragon/images/view-info.png |  Bin 0 -> 938 bytes
 .../greydragon/images/view-slideshow-b.png         |  Bin 0 -> 1179 bytes
 .../css/colorpacks/roundrobin/css/colors.css       |  193 +
 .../colorpacks/roundrobin/images/ajax-loading.gif  |  Bin 0 -> 2545 bytes
 .../css/colorpacks/roundrobin/images/bg-body.jpg   |  Bin 0 -> 13916 bytes
 .../css/colorpacks/roundrobin/images/bg-header.jpg |  Bin 0 -> 13609 bytes
 .../css/colorpacks/roundrobin/images/colorpack.png |  Bin 0 -> 475 bytes
 .../css/colorpacks/roundrobin/images/gallery.png   |  Bin 0 -> 553 bytes
 .../css/colorpacks/roundrobin/images/ico-album.png |  Bin 0 -> 351 bytes
 .../css/colorpacks/roundrobin/images/ico-error.png |  Bin 0 -> 701 bytes
 .../css/colorpacks/roundrobin/images/ico-help.png  |  Bin 0 -> 786 bytes
 .../css/colorpacks/roundrobin/images/ico-info.png  |  Bin 0 -> 778 bytes
 .../colorpacks/roundrobin/images/ico-warning.png   |  Bin 0 -> 666 bytes
 .../colorpacks/roundrobin/images/loading-large.gif |  Bin 0 -> 8238 bytes
 .../colorpacks/roundrobin/images/loading-small.gif |  Bin 0 -> 673 bytes
 .../css/colorpacks/roundrobin/images/search.png    |  Bin 0 -> 550 bytes
 .../css/colorpacks/roundrobin/images/ui-icons.png  |  Bin 0 -> 14168 bytes
 .../roundrobin/images/view-calendar-b.png          |  Bin 0 -> 891 bytes
 .../colorpacks/roundrobin/images/view-calendar.png |  Bin 0 -> 260 bytes
 .../roundrobin/images/view-comments-b.png          |  Bin 0 -> 600 bytes
 .../colorpacks/roundrobin/images/view-comments.png |  Bin 0 -> 298 bytes
 .../roundrobin/images/view-fullsize-b.png          |  Bin 0 -> 670 bytes
 .../colorpacks/roundrobin/images/view-fullsize.png |  Bin 0 -> 275 bytes
 .../colorpacks/roundrobin/images/view-info-b.png   |  Bin 0 -> 698 bytes
 .../colorpacks/roundrobin/images/view-info-o.png   |  Bin 0 -> 259 bytes
 .../css/colorpacks/roundrobin/images/view-info.png |  Bin 0 -> 286 bytes
 .../roundrobin/images/view-slideshow-b.png         |  Bin 0 -> 1179 bytes
 .../css/colorpacks/slateblue/css/colors.css        |  177 +
 .../colorpacks/slateblue/images/ajax-loading.gif   |  Bin 0 -> 4782 bytes
 .../css/colorpacks/slateblue/images/background.jpg |  Bin 0 -> 907 bytes
 .../css/colorpacks/slateblue/images/colorpack.png  |  Bin 0 -> 414 bytes
 .../css/colorpacks/slateblue/images/footer.png     |  Bin 0 -> 376 bytes
 .../css/colorpacks/slateblue/images/ico-album.png  |  Bin 0 -> 351 bytes
 .../css/colorpacks/slateblue/images/ico-error.png  |  Bin 0 -> 701 bytes
 .../css/colorpacks/slateblue/images/ico-help.png   |  Bin 0 -> 786 bytes
 .../css/colorpacks/slateblue/images/ico-info.png   |  Bin 0 -> 778 bytes
 .../colorpacks/slateblue/images/ico-warning.png    |  Bin 0 -> 666 bytes
 .../colorpacks/slateblue/images/loading-large.gif  |  Bin 0 -> 8238 bytes
 .../colorpacks/slateblue/images/loading-small.gif  |  Bin 0 -> 673 bytes
 .../css/colorpacks/slateblue/images/search.png     |  Bin 0 -> 969 bytes
 .../css/colorpacks/slateblue/images/section.png    |  Bin 0 -> 192 bytes
 .../css/colorpacks/slateblue/images/ui-icons.png   |  Bin 0 -> 13160 bytes
 .../slateblue/images/view-calendar-b.png           |  Bin 0 -> 653 bytes
 .../colorpacks/slateblue/images/view-calendar.png  |  Bin 0 -> 429 bytes
 .../slateblue/images/view-comments-b.png           |  Bin 0 -> 600 bytes
 .../colorpacks/slateblue/images/view-comments.png  |  Bin 0 -> 492 bytes
 .../slateblue/images/view-fullsize-b.png           |  Bin 0 -> 699 bytes
 .../colorpacks/slateblue/images/view-fullsize.png  |  Bin 0 -> 407 bytes
 .../colorpacks/slateblue/images/view-info-b.png    |  Bin 0 -> 493 bytes
 .../colorpacks/slateblue/images/view-info-o.png    |  Bin 0 -> 259 bytes
 .../css/colorpacks/slateblue/images/view-info.png  |  Bin 0 -> 938 bytes
 .../slateblue/images/view-slideshow-b.png          |  Bin 0 -> 1179 bytes
 .../css/colorpacks/whitehawk/css/colors.css        |  174 +
 .../colorpacks/whitehawk/images/ajax-loading.gif   |  Bin 0 -> 2545 bytes
 .../css/colorpacks/whitehawk/images/colorpack.png  |  Bin 0 -> 417 bytes
 .../css/colorpacks/whitehawk/images/gallery.png    |  Bin 0 -> 1383 bytes
 .../css/colorpacks/whitehawk/images/ico-album.png  |  Bin 0 -> 351 bytes
 .../css/colorpacks/whitehawk/images/ico-error.png  |  Bin 0 -> 701 bytes
 .../css/colorpacks/whitehawk/images/ico-help.png   |  Bin 0 -> 786 bytes
 .../css/colorpacks/whitehawk/images/ico-info.png   |  Bin 0 -> 778 bytes
 .../colorpacks/whitehawk/images/ico-warning.png    |  Bin 0 -> 666 bytes
 .../colorpacks/whitehawk/images/loading-large.gif  |  Bin 0 -> 8238 bytes
 .../colorpacks/whitehawk/images/loading-small.gif  |  Bin 0 -> 673 bytes
 .../css/colorpacks/whitehawk/images/search.png     |  Bin 0 -> 571 bytes
 .../css/colorpacks/whitehawk/images/ui-icons.png   |  Bin 0 -> 9914 bytes
 .../whitehawk/images/view-calendar-b.png           |  Bin 0 -> 891 bytes
 .../colorpacks/whitehawk/images/view-calendar.png  |  Bin 0 -> 260 bytes
 .../whitehawk/images/view-comments-b.png           |  Bin 0 -> 600 bytes
 .../colorpacks/whitehawk/images/view-comments.png  |  Bin 0 -> 298 bytes
 .../whitehawk/images/view-fullsize-b.png           |  Bin 0 -> 670 bytes
 .../colorpacks/whitehawk/images/view-fullsize.png  |  Bin 0 -> 275 bytes
 .../colorpacks/whitehawk/images/view-info-b.png    |  Bin 0 -> 698 bytes
 .../colorpacks/whitehawk/images/view-info-o.png    |  Bin 0 -> 259 bytes
 .../css/colorpacks/whitehawk/images/view-info.png  |  Bin 0 -> 286 bytes
 .../whitehawk/images/view-slideshow-b.png          |  Bin 0 -> 1179 bytes
 .../css/colorpacks/wind/css/colors.css             |  176 +
 .../css/colorpacks/wind/images/ajax-loading.gif    |  Bin 0 -> 2545 bytes
 .../css/colorpacks/wind/images/colorpack.png       |  Bin 0 -> 397 bytes
 .../css/colorpacks/wind/images/ico-album.png       |  Bin 0 -> 351 bytes
 .../css/colorpacks/wind/images/ico-error.png       |  Bin 0 -> 701 bytes
 .../css/colorpacks/wind/images/ico-help.png        |  Bin 0 -> 786 bytes
 .../css/colorpacks/wind/images/ico-info.png        |  Bin 0 -> 778 bytes
 .../colorpacks/wind/images/ico-view-fullsize.png   |  Bin 0 -> 1207 bytes
 .../wind/images/ico-view-slideshow-rtl.png         |  Bin 0 -> 1013 bytes
 .../colorpacks/wind/images/ico-view-slideshow.png  |  Bin 0 -> 854 bytes
 .../css/colorpacks/wind/images/ico-warning.png     |  Bin 0 -> 666 bytes
 .../css/colorpacks/wind/images/loading-large.gif   |  Bin 0 -> 8238 bytes
 .../css/colorpacks/wind/images/loading-small.gif   |  Bin 0 -> 673 bytes
 .../css/colorpacks/wind/images/section.png         |  Bin 0 -> 314 bytes
 .../css/colorpacks/wind/images/ui-icons.png        |  Bin 0 -> 10682 bytes
 .../css/colorpacks/wind/images/view-calendar.png   |  Bin 0 -> 637 bytes
 .../css/colorpacks/wind/images/view-comments-b.png |  Bin 0 -> 892 bytes
 .../css/colorpacks/wind/images/view-comments.png   |  Bin 0 -> 347 bytes
 .../css/colorpacks/wind/images/view-fullsize.png   |  Bin 0 -> 365 bytes
 .../css/colorpacks/wind/images/view-info-b.png     |  Bin 0 -> 698 bytes
 .../css/colorpacks/wind/images/view-info-o.png     |  Bin 0 -> 259 bytes
 .../css/colorpacks/wind/images/view-info.png       |  Bin 0 -> 383 bytes
 .../colorpacks/wind/images/view-slideshow-b.png    |  Bin 0 -> 1179 bytes
 themes/greydragon_old/css/custom.css               |    2 +
 themes/greydragon_old/css/forms.css                |  113 +
 .../css/framepacks/android/css/frame.css           |   32 +
 .../css/framepacks/android/images/thumb-dgt-e.png  |  Bin 0 -> 1482 bytes
 .../framepacks/android/images/thumb-dgt-eext.png   |  Bin 0 -> 1939 bytes
 .../framepacks/android/images/thumb-dgt-ext.png    |  Bin 0 -> 1791 bytes
 .../css/framepacks/android/images/thumb-dgt.png    |  Bin 0 -> 1447 bytes
 .../css/framepacks/android/images/thumb-flm-e.png  |  Bin 0 -> 1443 bytes
 .../framepacks/android/images/thumb-flm-eext.png   |  Bin 0 -> 1796 bytes
 .../framepacks/android/images/thumb-flm-ext.png    |  Bin 0 -> 1737 bytes
 .../css/framepacks/android/images/thumb-flm.png    |  Bin 0 -> 1413 bytes
 .../css/framepacks/android/images/thumb-sqr-e.png  |  Bin 0 -> 1579 bytes
 .../framepacks/android/images/thumb-sqr-eext.png   |  Bin 0 -> 1916 bytes
 .../framepacks/android/images/thumb-sqr-ext.png    |  Bin 0 -> 1900 bytes
 .../css/framepacks/android/images/thumb-sqr.png    |  Bin 0 -> 1544 bytes
 .../css/framepacks/android/images/thumb-wd-e.png   |  Bin 0 -> 1428 bytes
 .../framepacks/android/images/thumb-wd-eext.png    |  Bin 0 -> 1720 bytes
 .../css/framepacks/android/images/thumb-wd-ext.png |  Bin 0 -> 1659 bytes
 .../css/framepacks/android/images/thumb-wd.png     |  Bin 0 -> 1379 bytes
 .../css/framepacks/book/css/frame.css              |   59 +
 .../css/framepacks/book/images/a-thumb-dgt-e.png   |  Bin 0 -> 1130 bytes
 .../framepacks/book/images/a-thumb-dgt-eext.png    |  Bin 0 -> 1579 bytes
 .../css/framepacks/book/images/a-thumb-dgt-ext.png |  Bin 0 -> 1513 bytes
 .../css/framepacks/book/images/a-thumb-dgt.png     |  Bin 0 -> 1062 bytes
 .../css/framepacks/book/images/a-thumb-flm-e.png   |  Bin 0 -> 1105 bytes
 .../framepacks/book/images/a-thumb-flm-eext.png    |  Bin 0 -> 1478 bytes
 .../css/framepacks/book/images/a-thumb-flm-ext.png |  Bin 0 -> 1300 bytes
 .../css/framepacks/book/images/a-thumb-flm.png     |  Bin 0 -> 1030 bytes
 .../css/framepacks/book/images/a-thumb-sqr-e.png   |  Bin 0 -> 1283 bytes
 .../framepacks/book/images/a-thumb-sqr-eext.png    |  Bin 0 -> 1863 bytes
 .../css/framepacks/book/images/a-thumb-sqr-ext.png |  Bin 0 -> 1733 bytes
 .../css/framepacks/book/images/a-thumb-sqr.png     |  Bin 0 -> 1225 bytes
 .../css/framepacks/book/images/a-thumb-wd-e.png    |  Bin 0 -> 1073 bytes
 .../css/framepacks/book/images/a-thumb-wd-eext.png |  Bin 0 -> 1371 bytes
 .../css/framepacks/book/images/a-thumb-wd-ext.png  |  Bin 0 -> 1265 bytes
 .../css/framepacks/book/images/a-thumb-wd.png      |  Bin 0 -> 991 bytes
 .../css/framepacks/book/images/thumb-dgt-e.png     |  Bin 0 -> 619 bytes
 .../css/framepacks/book/images/thumb-dgt-eext.png  |  Bin 0 -> 802 bytes
 .../css/framepacks/book/images/thumb-dgt-ext.png   |  Bin 0 -> 773 bytes
 .../css/framepacks/book/images/thumb-dgt.png       |  Bin 0 -> 575 bytes
 .../css/framepacks/book/images/thumb-flm-e.png     |  Bin 0 -> 613 bytes
 .../css/framepacks/book/images/thumb-flm-eext.png  |  Bin 0 -> 783 bytes
 .../css/framepacks/book/images/thumb-flm-ext.png   |  Bin 0 -> 625 bytes
 .../css/framepacks/book/images/thumb-flm.png       |  Bin 0 -> 587 bytes
 .../css/framepacks/book/images/thumb-sqr-e.png     |  Bin 0 -> 676 bytes
 .../css/framepacks/book/images/thumb-sqr-eext.png  |  Bin 0 -> 902 bytes
 .../css/framepacks/book/images/thumb-sqr-ext.png   |  Bin 0 -> 864 bytes
 .../css/framepacks/book/images/thumb-sqr.png       |  Bin 0 -> 648 bytes
 .../css/framepacks/book/images/thumb-wd-e.png      |  Bin 0 -> 600 bytes
 .../css/framepacks/book/images/thumb-wd-eext.png   |  Bin 0 -> 727 bytes
 .../css/framepacks/book/images/thumb-wd-ext.png    |  Bin 0 -> 695 bytes
 .../css/framepacks/book/images/thumb-wd.png        |  Bin 0 -> 575 bytes
 .../css/framepacks/darkglass/css/frame.css         |   32 +
 .../framepacks/darkglass/images/thumb-dgt-e.png    |  Bin 0 -> 1876 bytes
 .../framepacks/darkglass/images/thumb-dgt-eext.png |  Bin 0 -> 2132 bytes
 .../framepacks/darkglass/images/thumb-dgt-ext.png  |  Bin 0 -> 2097 bytes
 .../css/framepacks/darkglass/images/thumb-dgt.png  |  Bin 0 -> 1873 bytes
 .../framepacks/darkglass/images/thumb-flm-e.png    |  Bin 0 -> 1814 bytes
 .../framepacks/darkglass/images/thumb-flm-eext.png |  Bin 0 -> 2092 bytes
 .../framepacks/darkglass/images/thumb-flm-ext.png  |  Bin 0 -> 2048 bytes
 .../css/framepacks/darkglass/images/thumb-flm.png  |  Bin 0 -> 1811 bytes
 .../framepacks/darkglass/images/thumb-sqr-e.png    |  Bin 0 -> 1896 bytes
 .../framepacks/darkglass/images/thumb-sqr-eext.png |  Bin 0 -> 2220 bytes
 .../framepacks/darkglass/images/thumb-sqr-ext.png  |  Bin 0 -> 2187 bytes
 .../css/framepacks/darkglass/images/thumb-sqr.png  |  Bin 0 -> 3675 bytes
 .../css/framepacks/darkglass/images/thumb-wd-e.png |  Bin 0 -> 1787 bytes
 .../framepacks/darkglass/images/thumb-wd-eext.png  |  Bin 0 -> 2051 bytes
 .../framepacks/darkglass/images/thumb-wd-ext.png   |  Bin 0 -> 2006 bytes
 .../css/framepacks/darkglass/images/thumb-wd.png   |  Bin 0 -> 1767 bytes
 .../css/framepacks/greydragon/css/frame.css        |   40 +
 .../css/framepacks/iphone/css/frame.css            |   31 +
 .../css/framepacks/iphone/images/thumb-dgt-e.png   |  Bin 0 -> 2923 bytes
 .../framepacks/iphone/images/thumb-dgt-eext.png    |  Bin 0 -> 3544 bytes
 .../css/framepacks/iphone/images/thumb-dgt-ext.png |  Bin 0 -> 3449 bytes
 .../css/framepacks/iphone/images/thumb-dgt.png     |  Bin 0 -> 2813 bytes
 .../css/framepacks/iphone/images/thumb-flm-e.png   |  Bin 0 -> 2734 bytes
 .../framepacks/iphone/images/thumb-flm-eext.png    |  Bin 0 -> 3414 bytes
 .../css/framepacks/iphone/images/thumb-flm-ext.png |  Bin 0 -> 3272 bytes
 .../css/framepacks/iphone/images/thumb-flm.png     |  Bin 0 -> 2612 bytes
 .../css/framepacks/iphone/images/thumb-sqr-e.png   |  Bin 0 -> 2848 bytes
 .../framepacks/iphone/images/thumb-sqr-eext.png    |  Bin 0 -> 3930 bytes
 .../css/framepacks/iphone/images/thumb-sqr-ext.png |  Bin 0 -> 3850 bytes
 .../css/framepacks/iphone/images/thumb-sqr.png     |  Bin 0 -> 2759 bytes
 .../css/framepacks/iphone/images/thumb-wd-e.png    |  Bin 0 -> 2769 bytes
 .../css/framepacks/iphone/images/thumb-wd-eext.png |  Bin 0 -> 3108 bytes
 .../css/framepacks/iphone/images/thumb-wd-ext.png  |  Bin 0 -> 3012 bytes
 .../css/framepacks/iphone/images/thumb-wd.png      |  Bin 0 -> 2676 bytes
 .../css/framepacks/iphoto/css/frame.css            |   31 +
 .../css/framepacks/iphoto/images/thumb-dgt-e.png   |  Bin 0 -> 1093 bytes
 .../framepacks/iphoto/images/thumb-dgt-eext.png    |  Bin 0 -> 1294 bytes
 .../css/framepacks/iphoto/images/thumb-dgt-ext.png |  Bin 0 -> 1251 bytes
 .../css/framepacks/iphoto/images/thumb-dgt.png     |  Bin 0 -> 1065 bytes
 .../css/framepacks/iphoto/images/thumb-flm-e.png   |  Bin 0 -> 1071 bytes
 .../framepacks/iphoto/images/thumb-flm-eext.png    |  Bin 0 -> 1258 bytes
 .../css/framepacks/iphoto/images/thumb-flm-ext.png |  Bin 0 -> 1218 bytes
 .../css/framepacks/iphoto/images/thumb-flm.png     |  Bin 0 -> 1045 bytes
 .../css/framepacks/iphoto/images/thumb-sqr-e.png   |  Bin 0 -> 1141 bytes
 .../framepacks/iphoto/images/thumb-sqr-eext.png    |  Bin 0 -> 1382 bytes
 .../css/framepacks/iphoto/images/thumb-sqr-ext.png |  Bin 0 -> 1342 bytes
 .../css/framepacks/iphoto/images/thumb-sqr.png     |  Bin 0 -> 1110 bytes
 .../css/framepacks/iphoto/images/thumb-wd-e.png    |  Bin 0 -> 1056 bytes
 .../css/framepacks/iphoto/images/thumb-wd-eext.png |  Bin 0 -> 1209 bytes
 .../css/framepacks/iphoto/images/thumb-wd-ext.png  |  Bin 0 -> 1168 bytes
 .../css/framepacks/iphoto/images/thumb-wd.png      |  Bin 0 -> 1015 bytes
 .../css/framepacks/iphoto/views/frame.html.php     |    5 +
 .../css/framepacks/panel/css/frame.css             |   35 +
 .../css/framepacks/roundcorners/css/frame.css      |   42 +
 .../css/framepacks/simple/css/frame.css            |   33 +
 .../css/framepacks/wall/css/frame.css              |   46 +
 themes/greydragon_old/css/gd_common.css            |   59 +
 themes/greydragon_old/css/ipad.css                 |   20 +
 themes/greydragon_old/css/layout.css               |   67 +
 themes/greydragon_old/css/menus.css                |   58 +
 themes/greydragon_old/css/modules.css              |  164 +
 themes/greydragon_old/css/normalize.css            |  431 ++
 themes/greydragon_old/css/rtl.css                  |   47 +
 themes/greydragon_old/css/screen.css               |   17 +
 themes/greydragon_old/helpers/exif_event.php       |   45 +
 themes/greydragon_old/helpers/greydragon_event.php |   92 +
 .../helpers/greydragon_installer.php               |   30 +
 themes/greydragon_old/helpers/greydragon_theme.php |   20 +
 themes/greydragon_old/images/apple-touch-icon.png  |  Bin 0 -> 9420 bytes
 themes/greydragon_old/images/arrows_left.png       |  Bin 0 -> 1895 bytes
 themes/greydragon_old/images/arrows_right.png      |  Bin 0 -> 1826 bytes
 themes/greydragon_old/images/avatar.jpg            |  Bin 0 -> 1442 bytes
 themes/greydragon_old/images/blue-grad.png         |  Bin 0 -> 337 bytes
 .../images/button-grad-active-vs.png               |  Bin 0 -> 152 bytes
 themes/greydragon_old/images/button-grad-vs.png    |  Bin 0 -> 155 bytes
 themes/greydragon_old/images/close.png             |  Bin 0 -> 564 bytes
 themes/greydragon_old/images/donate.png            |  Bin 0 -> 399 bytes
 themes/greydragon_old/images/gallery.png           |  Bin 0 -> 627 bytes
 themes/greydragon_old/images/ico-allowed.png       |  Bin 0 -> 715 bytes
 .../greydragon_old/images/ico-denied-inactive.png  |  Bin 0 -> 604 bytes
 .../greydragon_old/images/ico-denied-passive.png   |  Bin 0 -> 916 bytes
 themes/greydragon_old/images/ico-denied.png        |  Bin 0 -> 715 bytes
 themes/greydragon_old/images/ico-error.png         |  Bin 0 -> 701 bytes
 themes/greydragon_old/images/ico-help.png          |  Bin 0 -> 786 bytes
 themes/greydragon_old/images/ico-info.png          |  Bin 0 -> 778 bytes
 themes/greydragon_old/images/ico-lock.png          |  Bin 0 -> 749 bytes
 .../greydragon_old/images/ico-success-inactive.png |  Bin 0 -> 261 bytes
 .../greydragon_old/images/ico-success-passive.png  |  Bin 0 -> 561 bytes
 themes/greydragon_old/images/ico-success.png       |  Bin 0 -> 537 bytes
 themes/greydragon_old/images/ico-warning.png       |  Bin 0 -> 666 bytes
 themes/greydragon_old/images/missing-img.png       |  Bin 0 -> 33136 bytes
 themes/greydragon_old/js/jquery.cycle.js           | 1544 +++++
 themes/greydragon_old/js/ui.support.js             |   80 +
 themes/greydragon_old/libraries/MY_Theme_View.php  |  902 +++
 themes/greydragon_old/module.info                  |    9 +
 themes/greydragon_old/theme.info                   |   11 +
 themes/greydragon_old/thumbnail.png                |  Bin 0 -> 25791 bytes
 themes/greydragon_old/views/album.html.php         |   68 +
 themes/greydragon_old/views/block.html.php         |   29 +
 themes/greydragon_old/views/calpage.html.php       |  257 +
 themes/greydragon_old/views/dynamic.html.php       |   38 +
 themes/greydragon_old/views/exif_sidebar.html.php  |   18 +
 .../greydragon_old/views/gd_admin_include.html.php |  180 +
 themes/greydragon_old/views/info_block.html.php    |   29 +
 themes/greydragon_old/views/movie.html.php         |   38 +
 themes/greydragon_old/views/no_sidebar.html.php    |   19 +
 themes/greydragon_old/views/page.html.php          |  259 +
 themes/greydragon_old/views/paginator.html.php     |  194 +
 themes/greydragon_old/views/photo.html.php         |  124 +
 themes/greydragon_old/views/rootpage.html.php      |   59 +
 themes/greydragon_old/views/rootpage.html.php_fix  |   46 +
 themes/greydragon_old/views/rss_block.html.php     |   30 +
 themes/greydragon_old/views/search.html.php        |   35 +
 themes/greydragon_old/views/sidebar.html.php       |   27 +
 themes/greydragon_old/views/user_profile.html.php  |   44 +
 themes/wind/css/fix-ie.css                         |   59 +
 themes/wind/css/screen-rtl.css                     |  333 +
 themes/wind/css/screen.css                         | 1066 +++
 .../images/ui-bg_flat_0_aaaaaa_40x100.png          |  Bin 0 -> 180 bytes
 .../images/ui-bg_flat_55_fbec88_40x100.png         |  Bin 0 -> 182 bytes
 .../images/ui-bg_glass_75_d0e5f5_1x400.png         |  Bin 0 -> 124 bytes
 .../images/ui-bg_glass_85_dfeffc_1x400.png         |  Bin 0 -> 123 bytes
 .../images/ui-bg_glass_95_fef1ec_1x400.png         |  Bin 0 -> 119 bytes
 .../images/ui-bg_gloss-wave_55_5c9ccc_500x100.png  |  Bin 0 -> 4033 bytes
 .../images/ui-bg_inset-hard_100_f5f8f9_1x100.png   |  Bin 0 -> 104 bytes
 .../images/ui-bg_inset-hard_100_fcfdfd_1x100.png   |  Bin 0 -> 88 bytes
 .../themeroller/images/ui-icons_217bc0_256x240.png |  Bin 0 -> 7638 bytes
 .../themeroller/images/ui-icons_2e83ff_256x240.png |  Bin 0 -> 7626 bytes
 .../themeroller/images/ui-icons_469bdd_256x240.png |  Bin 0 -> 5399 bytes
 .../themeroller/images/ui-icons_6da8d5_256x240.png |  Bin 0 -> 8447 bytes
 .../themeroller/images/ui-icons_cd0a0a_256x240.png |  Bin 0 -> 4379 bytes
 .../themeroller/images/ui-icons_d8e7f3_256x240.png |  Bin 0 -> 4379 bytes
 .../themeroller/images/ui-icons_f9bd01_256x240.png |  Bin 0 -> 4379 bytes
 themes/wind/css/themeroller/ui.base.css            |    7 +
 themes/wind/css/themeroller/ui.core.css            |   37 +
 themes/wind/css/themeroller/ui.datepicker.css      |   62 +
 themes/wind/css/themeroller/ui.dialog.css          |   13 +
 themes/wind/css/themeroller/ui.progressbar.css     |    4 +
 themes/wind/css/themeroller/ui.resizable.css       |   13 +
 themes/wind/css/themeroller/ui.tabs.css            |    9 +
 themes/wind/css/themeroller/ui.theme.css           |  243 +
 themes/wind/images/avatar.jpg                      |  Bin 0 -> 1172 bytes
 themes/wind/images/ico-album.png                   |  Bin 0 -> 397 bytes
 themes/wind/images/ico-denied-inactive.png         |  Bin 0 -> 604 bytes
 themes/wind/images/ico-denied-passive.png          |  Bin 0 -> 916 bytes
 themes/wind/images/ico-denied.png                  |  Bin 0 -> 715 bytes
 themes/wind/images/ico-error.png                   |  Bin 0 -> 701 bytes
 themes/wind/images/ico-help.png                    |  Bin 0 -> 786 bytes
 themes/wind/images/ico-info.png                    |  Bin 0 -> 778 bytes
 themes/wind/images/ico-lock.png                    |  Bin 0 -> 749 bytes
 themes/wind/images/ico-print.png                   |  Bin 0 -> 989 bytes
 themes/wind/images/ico-separator-rtl.gif           |  Bin 0 -> 106 bytes
 themes/wind/images/ico-separator.gif               |  Bin 0 -> 106 bytes
 themes/wind/images/ico-success-inactive.png        |  Bin 0 -> 476 bytes
 themes/wind/images/ico-success-passive.png         |  Bin 0 -> 617 bytes
 themes/wind/images/ico-success.png                 |  Bin 0 -> 537 bytes
 themes/wind/images/ico-view-comments.png           |  Bin 0 -> 768 bytes
 themes/wind/images/ico-view-fullsize.png           |  Bin 0 -> 1046 bytes
 themes/wind/images/ico-view-slideshow-rtl.png      |  Bin 0 -> 1137 bytes
 themes/wind/images/ico-view-slideshow.png          |  Bin 0 -> 960 bytes
 themes/wind/images/ico-warning.png                 |  Bin 0 -> 666 bytes
 themes/wind/images/loading-large.gif               |  Bin 0 -> 8238 bytes
 themes/wind/images/loading-small.gif               |  Bin 0 -> 673 bytes
 themes/wind/images/select-photos-backg.png         |  Bin 0 -> 1154 bytes
 themes/wind/js/ui.init.js                          |  118 +
 themes/wind/theme.info                             |   10 +
 themes/wind/thumbnail.png                          |  Bin 0 -> 26927 bytes
 themes/wind/views/album.html.php                   |   47 +
 themes/wind/views/block.html.php                   |   10 +
 themes/wind/views/dynamic.html.php                 |   29 +
 themes/wind/views/movie.html.php                   |   19 +
 themes/wind/views/no_sidebar.html.php              |   11 +
 themes/wind/views/page.html.php                    |  153 +
 themes/wind/views/paginator.html.php               |   87 +
 themes/wind/views/photo.html.php                   |   51 +
 themes/wind/views/sidebar.html.php                 |   16 +
 1476 files changed, 103573 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 .htaccess
 create mode 100644 LICENSE
 create mode 100644 README
 create mode 100644 application/Bootstrap.php
 create mode 100644 application/config/config.php
 create mode 100755 bin/.htaccess
 create mode 100644 bin/README
 create mode 100644 index.php
 create mode 100644 installer/cli.php
 create mode 100644 installer/database_config.php
 create mode 100644 installer/index.php
 create mode 100755 installer/init_var.php
 create mode 100644 installer/install.css
 create mode 100644 installer/install.sql
 create mode 100644 installer/installer.php
 create mode 100644 installer/views/already_installed.html.php
 create mode 100644 installer/views/db_not_empty.html.php
 create mode 100644 installer/views/environment_errors.html.php
 create mode 100644 installer/views/get_db_info.html.php
 create mode 100644 installer/views/install.html.php
 create mode 100644 installer/views/invalid_db_info.html.php
 create mode 100644 installer/views/invalid_db_version.html.php
 create mode 100644 installer/views/missing_db.html.php
 create mode 100644 installer/views/oops.html.php
 create mode 100644 installer/views/success.html.php
 create mode 100644 installer/web.php
 create mode 100644 lib/flowplayer.controls.swf.php
 create mode 100644 lib/flowplayer.js
 create mode 100644 lib/flowplayer.pseudostreaming-byterange.swf.php
 create mode 100644 lib/flowplayer.pseudostreaming.swf.php
 create mode 100644 lib/flowplayer.swf.php
 create mode 100644 lib/gallery.ajax.js
 create mode 100644 lib/gallery.common.js
 create mode 100644 lib/gallery.dialog.js
 create mode 100644 lib/gallery.in_place_edit.js
 create mode 100644 lib/gallery.panel.js
 create mode 100644 lib/gallery.show_full_size.js
 create mode 100644 lib/images/Galerie-Logo.png
 create mode 100644 lib/images/apple-touch-icon.png
 create mode 100644 lib/images/favicon.ico
 create mode 100644 lib/images/logo.png
 create mode 100644 lib/jquery-ui.js
 create mode 100644 lib/jquery.MultiFile.js
 create mode 100644 lib/jquery.autocomplete.css
 create mode 100644 lib/jquery.autocomplete.js
 create mode 100644 lib/jquery.cookie.js
 create mode 100644 lib/jquery.form.js
 create mode 100644 lib/jquery.jeditable.js
 create mode 100644 lib/jquery.js
 create mode 100644 lib/jquery.localscroll.js
 create mode 100644 lib/jquery.scrollTo.js
 create mode 100644 lib/json2-min.js
 create mode 100644 lib/superfish/css/superfish.css
 create mode 100644 lib/superfish/images/arrows-ffffff-rtl.png
 create mode 100644 lib/superfish/images/arrows-ffffff.png
 create mode 100644 lib/superfish/images/shadow.png
 create mode 100644 lib/superfish/js/superfish.js
 create mode 100644 lib/swfobject.js
 create mode 100644 lib/uploadify/cancel.png
 create mode 100644 lib/uploadify/jquery.uploadify.min.js
 create mode 100644 lib/uploadify/uploadify.allglyphs.swf.php
 create mode 100644 lib/uploadify/uploadify.css
 create mode 100644 lib/uploadify/uploadify.fla
 create mode 100644 lib/uploadify/uploadify.swf.php
 create mode 100644 lib/yui/base-min.css
 create mode 100644 lib/yui/reset-fonts-grids.css
 create mode 100644 modules/akismet/controllers/admin_akismet.php
 create mode 100644 modules/akismet/helpers/akismet.php
 create mode 100644 modules/akismet/helpers/akismet_event.php
 create mode 100644 modules/akismet/helpers/akismet_installer.php
 create mode 100644 modules/akismet/module.info
 create mode 100644 modules/akismet/views/admin_akismet.html.php
 create mode 100644 modules/akismet/views/admin_akismet_stats.html.php
 create mode 100644 modules/calendarview/controllers/calendarview.php
 create mode 100644 modules/calendarview/css/calendarview_calendar.css
 create mode 100644 modules/calendarview/css/calendarview_menu.css
 create mode 100644 modules/calendarview/helpers/calendarview.php
 create mode 100644 modules/calendarview/helpers/calendarview_block.php
 create mode 100644 modules/calendarview/helpers/calendarview_event.php
 create mode 100644 modules/calendarview/helpers/calendarview_installer.php
 create mode 100644 modules/calendarview/helpers/calendarview_theme.php
 create mode 100644 modules/calendarview/images/ico-view-calendarview.png
 create mode 100644 modules/calendarview/libraries/PHPCalendar.php
 create mode 100644 modules/calendarview/module.info
 create mode 100644 modules/calendarview/views/calendarview_sidebar.html.php
 create mode 100644 modules/calendarview/views/calendarview_year.html.php
 create mode 100644 modules/calendarview/views/user_profile_calendarview.html.php
 create mode 100644 modules/comment/controllers/admin_comments.php
 create mode 100644 modules/comment/controllers/admin_manage_comments.php
 create mode 100644 modules/comment/controllers/comments.php
 create mode 100644 modules/comment/css/comment.css
 create mode 100644 modules/comment/helpers/comment.php
 create mode 100644 modules/comment/helpers/comment_block.php
 create mode 100644 modules/comment/helpers/comment_event.php
 create mode 100644 modules/comment/helpers/comment_installer.php
 create mode 100644 modules/comment/helpers/comment_rest.php
 create mode 100644 modules/comment/helpers/comment_rss.php
 create mode 100644 modules/comment/helpers/comment_theme.php
 create mode 100644 modules/comment/helpers/comments_rest.php
 create mode 100644 modules/comment/helpers/item_comments_rest.php
 create mode 100644 modules/comment/js/comment.js
 create mode 100644 modules/comment/models/comment.php
 create mode 100644 modules/comment/module.info
 create mode 100644 modules/comment/views/admin_block_recent_comments.html.php
 create mode 100644 modules/comment/views/admin_comments.html.php
 create mode 100644 modules/comment/views/admin_manage_comments.html.php
 create mode 100644 modules/comment/views/admin_manage_comments_queue.html.php
 create mode 100644 modules/comment/views/comment.html.php
 create mode 100644 modules/comment/views/comment.mrss.php
 create mode 100644 modules/comment/views/comments.html.php
 create mode 100644 modules/comment/views/user_profile_comments.html.php
 create mode 100644 modules/downloadalbum/controllers/downloadalbum.php
 create mode 100644 modules/downloadalbum/css/downloadalbum_menu.css
 create mode 100644 modules/downloadalbum/helpers/downloadalbum_event.php
 create mode 100644 modules/downloadalbum/helpers/downloadalbum_theme.php
 create mode 100644 modules/downloadalbum/images/ico-view-downloadalbum.png
 create mode 100644 modules/downloadalbum/module.info
 create mode 100644 modules/downloadfullsize/controllers/admin_downloadfullsize.php
 create mode 100644 modules/downloadfullsize/controllers/downloadfullsize.php
 create mode 100644 modules/downloadfullsize/css/downloadfullsize_menu.css
 create mode 100644 modules/downloadfullsize/helpers/downloadfullsize_block.php
 create mode 100644 modules/downloadfullsize/helpers/downloadfullsize_event.php
 create mode 100644 modules/downloadfullsize/helpers/downloadfullsize_theme.php
 create mode 100644 modules/downloadfullsize/images/ico-view-downloadfullsize.png
 create mode 100644 modules/downloadfullsize/module.info
 create mode 100644 modules/downloadfullsize/views/admin_downloadfullsize.html.php
 create mode 100644 modules/downloadfullsize/views/downloadfullsize_block.html.php
 create mode 100644 modules/exif/controllers/exif.php
 create mode 100644 modules/exif/helpers/exif.php
 create mode 100644 modules/exif/helpers/exif_event.php
 create mode 100644 modules/exif/helpers/exif_installer.php
 create mode 100644 modules/exif/helpers/exif_task.php
 create mode 100644 modules/exif/helpers/exif_theme.php
 create mode 100644 modules/exif/lib/exif.php
 create mode 100644 modules/exif/lib/makers/canon.php
 create mode 100644 modules/exif/lib/makers/fujifilm.php
 create mode 100644 modules/exif/lib/makers/gps.php
 create mode 100644 modules/exif/lib/makers/nikon.php
 create mode 100644 modules/exif/lib/makers/olympus.php
 create mode 100644 modules/exif/lib/makers/panasonic.php
 create mode 100644 modules/exif/lib/makers/sanyo.php
 create mode 100644 modules/exif/models/exif_key.php
 create mode 100644 modules/exif/models/exif_record.php
 create mode 100644 modules/exif/module.info
 create mode 100644 modules/exif/views/exif_dialog.html.php
 create mode 100644 modules/exif/views/exif_sidebar.html.php
 create mode 100644 modules/familygallery/controllers/login.php.backup
 create mode 100644 modules/familygallery/helpers/familygallery_event.php
 create mode 100644 modules/familygallery/module.info
 create mode 100644 modules/forge/libraries/Forge.php
 create mode 100644 modules/forge/libraries/Form_Checkbox.php
 create mode 100644 modules/forge/libraries/Form_Checklist.php
 create mode 100644 modules/forge/libraries/Form_Dateselect.php
 create mode 100644 modules/forge/libraries/Form_Dropdown.php
 create mode 100644 modules/forge/libraries/Form_Group.php
 create mode 100644 modules/forge/libraries/Form_Hidden.php
 create mode 100644 modules/forge/libraries/Form_Input.php
 create mode 100644 modules/forge/libraries/Form_Password.php
 create mode 100644 modules/forge/libraries/Form_Phonenumber.php
 create mode 100644 modules/forge/libraries/Form_Radio.php
 create mode 100644 modules/forge/libraries/Form_Submit.php
 create mode 100644 modules/forge/libraries/Form_Textarea.php
 create mode 100644 modules/forge/libraries/Form_Upload.php
 create mode 100644 modules/g2_import/controllers/admin_g2_import.php
 create mode 100644 modules/g2_import/controllers/g2.php
 create mode 100755 modules/g2_import/data/broken-image.gif
 create mode 100644 modules/g2_import/helpers/g2_import.php
 create mode 100644 modules/g2_import/helpers/g2_import_event.php
 create mode 100644 modules/g2_import/helpers/g2_import_installer.php
 create mode 100644 modules/g2_import/helpers/g2_import_task.php
 create mode 100644 modules/g2_import/libraries/G2_Import_Exception.php
 create mode 100644 modules/g2_import/models/g2_map.php
 create mode 100644 modules/g2_import/module.info
 create mode 100644 modules/g2_import/views/admin_g2_import.html.php
 create mode 100644 modules/gallery/config/cache.php
 create mode 100644 modules/gallery/config/cookie.php
 create mode 100644 modules/gallery/config/database.php
 create mode 100644 modules/gallery/config/locale.php
 create mode 100644 modules/gallery/config/log_file.php
 create mode 100644 modules/gallery/config/routes.php
 create mode 100644 modules/gallery/config/session.php
 create mode 100644 modules/gallery/config/upload.php
 create mode 100644 modules/gallery/config/user_agents.php
 create mode 100644 modules/gallery/controllers/admin.php
 create mode 100644 modules/gallery/controllers/admin_advanced_settings.php
 create mode 100644 modules/gallery/controllers/admin_dashboard.php
 create mode 100644 modules/gallery/controllers/admin_graphics.php
 create mode 100644 modules/gallery/controllers/admin_languages.php
 create mode 100644 modules/gallery/controllers/admin_maintenance.php
 create mode 100644 modules/gallery/controllers/admin_modules.php
 create mode 100644 modules/gallery/controllers/admin_movies.php
 create mode 100644 modules/gallery/controllers/admin_sidebar.php
 create mode 100644 modules/gallery/controllers/admin_theme_options.php
 create mode 100644 modules/gallery/controllers/admin_themes.php
 create mode 100644 modules/gallery/controllers/admin_upgrade_checker.php
 create mode 100644 modules/gallery/controllers/albums.php
 create mode 100644 modules/gallery/controllers/combined.php
 create mode 100644 modules/gallery/controllers/file_proxy.php
 create mode 100644 modules/gallery/controllers/items.php
 create mode 100644 modules/gallery/controllers/l10n_client.php
 create mode 100644 modules/gallery/controllers/login.php
 create mode 100644 modules/gallery/controllers/logout.php
 create mode 100644 modules/gallery/controllers/movies.php
 create mode 100644 modules/gallery/controllers/packager.php
 create mode 100644 modules/gallery/controllers/permissions.php
 create mode 100644 modules/gallery/controllers/photos.php
 create mode 100644 modules/gallery/controllers/quick.php
 create mode 100644 modules/gallery/controllers/reauthenticate.php
 create mode 100644 modules/gallery/controllers/upgrader.php
 create mode 100644 modules/gallery/controllers/uploader.php
 create mode 100644 modules/gallery/controllers/user_profile.php
 create mode 100644 modules/gallery/controllers/welcome_message.php
 create mode 100644 modules/gallery/css/debug.css
 create mode 100644 modules/gallery/css/gallery.css
 create mode 100644 modules/gallery/css/l10n_client.css
 create mode 100644 modules/gallery/css/upgrader.css
 create mode 100644 modules/gallery/helpers/MY_html.php
 create mode 100644 modules/gallery/helpers/MY_num.php
 create mode 100644 modules/gallery/helpers/MY_remote.php
 create mode 100644 modules/gallery/helpers/MY_url.php
 create mode 100644 modules/gallery/helpers/MY_valid.php
 create mode 100644 modules/gallery/helpers/access.php
 create mode 100644 modules/gallery/helpers/ajax.php
 create mode 100644 modules/gallery/helpers/album.php
 create mode 100644 modules/gallery/helpers/auth.php
 create mode 100644 modules/gallery/helpers/batch.php
 create mode 100644 modules/gallery/helpers/block_manager.php
 create mode 100644 modules/gallery/helpers/data_rest.php
 create mode 100644 modules/gallery/helpers/dir.php
 create mode 100644 modules/gallery/helpers/encoding.php
 create mode 100644 modules/gallery/helpers/gallery.php
 create mode 100644 modules/gallery/helpers/gallery_block.php
 create mode 100644 modules/gallery/helpers/gallery_error.php
 create mode 100644 modules/gallery/helpers/gallery_event.php
 create mode 100644 modules/gallery/helpers/gallery_graphics.php
 create mode 100644 modules/gallery/helpers/gallery_installer.php
 create mode 100644 modules/gallery/helpers/gallery_rss.php
 create mode 100644 modules/gallery/helpers/gallery_task.php
 create mode 100644 modules/gallery/helpers/gallery_theme.php
 create mode 100644 modules/gallery/helpers/graphics.php
 create mode 100644 modules/gallery/helpers/identity.php
 create mode 100644 modules/gallery/helpers/item.php
 create mode 100644 modules/gallery/helpers/item_rest.php
 create mode 100644 modules/gallery/helpers/items_rest.php
 create mode 100644 modules/gallery/helpers/json.php
 create mode 100644 modules/gallery/helpers/l10n_client.php
 create mode 100644 modules/gallery/helpers/l10n_scanner.php
 create mode 100644 modules/gallery/helpers/legal_file.php
 create mode 100644 modules/gallery/helpers/locales.php
 create mode 100644 modules/gallery/helpers/log.php
 create mode 100644 modules/gallery/helpers/message.php
 create mode 100644 modules/gallery/helpers/model_cache.php
 create mode 100644 modules/gallery/helpers/module.php
 create mode 100644 modules/gallery/helpers/movie.php
 create mode 100644 modules/gallery/helpers/photo.php
 create mode 100644 modules/gallery/helpers/random.php
 create mode 100644 modules/gallery/helpers/site_status.php
 create mode 100644 modules/gallery/helpers/system.php
 create mode 100644 modules/gallery/helpers/task.php
 create mode 100644 modules/gallery/helpers/theme.php
 create mode 100644 modules/gallery/helpers/tree_rest.php
 create mode 100644 modules/gallery/helpers/upgrade_checker.php
 create mode 100644 modules/gallery/helpers/user_profile.php
 create mode 100644 modules/gallery/helpers/xml.php
 create mode 100644 modules/gallery/hooks/init_gallery.php
 create mode 100644 modules/gallery/images/ffmpeg.png
 create mode 100644 modules/gallery/images/gallery.png
 create mode 100644 modules/gallery/images/gd.png
 create mode 100644 modules/gallery/images/graphicsmagick.png
 create mode 100644 modules/gallery/images/imagemagick.jpg
 create mode 100644 modules/gallery/images/missing_album_cover.jpg
 create mode 100644 modules/gallery/images/missing_movie.jpg
 create mode 100644 modules/gallery/images/missing_photo.jpg
 create mode 100644 modules/gallery/js/albums_form_add.js
 create mode 100644 modules/gallery/js/item_form_delete.js
 create mode 100644 modules/gallery/js/l10n_client.js
 create mode 100644 modules/gallery/libraries/Admin_View.php
 create mode 100644 modules/gallery/libraries/Block.php
 create mode 100644 modules/gallery/libraries/Breadcrumb.php
 create mode 100644 modules/gallery/libraries/Form_Script.php
 create mode 100644 modules/gallery/libraries/Form_Uploadify.php
 create mode 100644 modules/gallery/libraries/Form_Uploadify_buttons.php
 create mode 100644 modules/gallery/libraries/Gallery_I18n.php
 create mode 100644 modules/gallery/libraries/Gallery_View.php
 create mode 100644 modules/gallery/libraries/IdentityProvider.php
 create mode 100644 modules/gallery/libraries/InPlaceEdit.php
 create mode 100644 modules/gallery/libraries/MY_Database.php
 create mode 100644 modules/gallery/libraries/MY_Forge.php
 create mode 100644 modules/gallery/libraries/MY_Input.php
 create mode 100644 modules/gallery/libraries/MY_Kohana_Exception.php
 create mode 100644 modules/gallery/libraries/MY_ORM.php
 create mode 100644 modules/gallery/libraries/MY_View.php
 create mode 100644 modules/gallery/libraries/Menu.php
 create mode 100644 modules/gallery/libraries/ORM_MPTT.php
 create mode 100644 modules/gallery/libraries/SafeString.php
 create mode 100644 modules/gallery/libraries/Sendmail.php
 create mode 100644 modules/gallery/libraries/Task_Definition.php
 create mode 100644 modules/gallery/libraries/Theme_View.php
 create mode 100644 modules/gallery/libraries/drivers/Cache/Database.php
 create mode 100644 modules/gallery/libraries/drivers/IdentityProvider.php
 create mode 100644 modules/gallery/models/access_cache.php
 create mode 100644 modules/gallery/models/access_intent.php
 create mode 100644 modules/gallery/models/cache.php
 create mode 100644 modules/gallery/models/failed_auth.php
 create mode 100644 modules/gallery/models/graphics_rule.php
 create mode 100644 modules/gallery/models/incoming_translation.php
 create mode 100644 modules/gallery/models/item.php
 create mode 100644 modules/gallery/models/log.php
 create mode 100644 modules/gallery/models/message.php
 create mode 100644 modules/gallery/models/module.php
 create mode 100644 modules/gallery/models/outgoing_translation.php
 create mode 100644 modules/gallery/models/permission.php
 create mode 100644 modules/gallery/models/task.php
 create mode 100644 modules/gallery/models/theme.php
 create mode 100644 modules/gallery/models/var.php
 create mode 100644 modules/gallery/module.info
 create mode 100644 modules/gallery/vendor/joomla/crypt.php
 create mode 100644 modules/gallery/views/admin_advanced_settings.html.php
 create mode 100644 modules/gallery/views/admin_block_log_entries.html.php
 create mode 100644 modules/gallery/views/admin_block_news.html.php
 create mode 100644 modules/gallery/views/admin_block_photo_stream.html.php
 create mode 100644 modules/gallery/views/admin_block_platform.html.php
 create mode 100644 modules/gallery/views/admin_block_stats.html.php
 create mode 100644 modules/gallery/views/admin_block_welcome.html.php
 create mode 100644 modules/gallery/views/admin_dashboard.html.php
 create mode 100644 modules/gallery/views/admin_graphics.html.php
 create mode 100644 modules/gallery/views/admin_graphics_gd.html.php
 create mode 100644 modules/gallery/views/admin_graphics_graphicsmagick.html.php
 create mode 100644 modules/gallery/views/admin_graphics_imagemagick.html.php
 create mode 100644 modules/gallery/views/admin_graphics_none.html.php
 create mode 100644 modules/gallery/views/admin_languages.html.php
 create mode 100644 modules/gallery/views/admin_maintenance.html.php
 create mode 100644 modules/gallery/views/admin_maintenance_show_log.html.php
 create mode 100644 modules/gallery/views/admin_maintenance_task.html.php
 create mode 100644 modules/gallery/views/admin_modules.html.php
 create mode 100644 modules/gallery/views/admin_modules_confirm.html.php
 create mode 100644 modules/gallery/views/admin_movies.html.php
 create mode 100644 modules/gallery/views/admin_sidebar.html.php
 create mode 100644 modules/gallery/views/admin_sidebar_blocks.html.php
 create mode 100644 modules/gallery/views/admin_theme_options.html.php
 create mode 100644 modules/gallery/views/admin_themes.html.php
 create mode 100644 modules/gallery/views/admin_themes_buttonset.html.php
 create mode 100644 modules/gallery/views/admin_themes_preview.html.php
 create mode 100644 modules/gallery/views/error.html.php
 create mode 100644 modules/gallery/views/error_404.html.php
 create mode 100644 modules/gallery/views/error_admin.html.php
 create mode 100644 modules/gallery/views/error_cli.txt.php
 create mode 100644 modules/gallery/views/error_user.html.php
 create mode 100644 modules/gallery/views/form.html.php
 create mode 100644 modules/gallery/views/form_uploadify.html.php
 create mode 100644 modules/gallery/views/form_uploadify_buttons.html.php
 create mode 100644 modules/gallery/views/in_place_edit.html.php
 create mode 100644 modules/gallery/views/kohana/error.php
 create mode 100644 modules/gallery/views/kohana_profiler.php
 create mode 100644 modules/gallery/views/l10n_client.html.php
 create mode 100644 modules/gallery/views/login_ajax.html.php
 create mode 100644 modules/gallery/views/login_current_user.html.php
 create mode 100644 modules/gallery/views/menu.html.php
 create mode 100644 modules/gallery/views/menu_ajax_link.html.php
 create mode 100644 modules/gallery/views/menu_dialog.html.php
 create mode 100644 modules/gallery/views/menu_link.html.php
 create mode 100644 modules/gallery/views/movieplayer.html.php
 create mode 100644 modules/gallery/views/permissions_browse.html.php
 create mode 100644 modules/gallery/views/permissions_form.html.php
 create mode 100644 modules/gallery/views/quick_delete_confirm.html.php
 create mode 100644 modules/gallery/views/reauthenticate.html.php
 create mode 100644 modules/gallery/views/upgrade_checker_block.html.php
 create mode 100644 modules/gallery/views/upgrader.html.php
 create mode 100644 modules/gallery/views/user_languages_block.html.php
 create mode 100644 modules/gallery/views/user_profile.html.php
 create mode 100644 modules/gallery/views/user_profile_info.html.php
 create mode 100644 modules/gallery/views/welcome_message.html.php
 create mode 100644 modules/gallery/views/welcome_message_loader.html.php
 create mode 100644 modules/greydragon/changelog.txt
 create mode 100644 modules/greydragon/css/gd_common.css
 create mode 100644 modules/greydragon/images/blue-grad.png
 create mode 100644 modules/greydragon/module.info
 create mode 100644 modules/greydragon/views/gd_admin_include.html.php
 create mode 100644 modules/html5_uploader/controllers/uploader.php
 create mode 100644 modules/html5_uploader/module.info
 create mode 100644 modules/image_block/controllers/image_block.php
 create mode 100644 modules/image_block/helpers/image_block_block.php
 create mode 100644 modules/image_block/helpers/image_block_installer.php
 create mode 100644 modules/image_block/module.info
 create mode 100644 modules/image_block/views/image_block_block.html.php
 create mode 100644 modules/info/helpers/info_block.php
 create mode 100644 modules/info/helpers/info_installer.php
 create mode 100644 modules/info/helpers/info_theme.php
 create mode 100644 modules/info/module.info
 create mode 100644 modules/info/views/info_block.html.php
 create mode 100644 modules/kbd_nav/changelog.txt
 create mode 100644 modules/kbd_nav/helpers/kbd_nav_theme.php
 create mode 100644 modules/kbd_nav/js/kbd_nav.js
 create mode 100644 modules/kbd_nav/module.info
 create mode 100644 modules/kohana23_compat/config/pagination.php
 create mode 100644 modules/kohana23_compat/libraries/MY_Database_Builder.php
 create mode 100644 modules/kohana23_compat/libraries/Pagination.php
 create mode 100644 modules/localprint/controllers/admin_localprint.php
 create mode 100644 modules/localprint/css/localprint_menu.css
 create mode 100644 modules/localprint/helpers/localprint_event.php
 create mode 100644 modules/localprint/helpers/localprint_installer.php
 create mode 100644 modules/localprint/helpers/localprint_theme.php
 create mode 100644 modules/localprint/images/localprint_logo.png
 create mode 100644 modules/localprint/js/localprint.js
 create mode 100644 modules/localprint/module.info
 create mode 100644 modules/localprint/views/admin_localprint.html.php
 create mode 100644 modules/localprint/views/localprint_code.html.php
 create mode 100644 modules/notification/controllers/notification.php
 create mode 100644 modules/notification/helpers/notification.php
 create mode 100644 modules/notification/helpers/notification_event.php
 create mode 100644 modules/notification/helpers/notification_installer.php
 create mode 100644 modules/notification/models/pending_notification.php
 create mode 100644 modules/notification/models/subscription.php
 create mode 100644 modules/notification/module.info
 create mode 100644 modules/notification/views/comment_published.html.php
 create mode 100644 modules/notification/views/item_added.html.php
 create mode 100644 modules/notification/views/item_deleted.html.php
 create mode 100644 modules/notification/views/item_updated.html.php
 create mode 100644 modules/notification/views/user_profile_notification.html.php
 create mode 100644 modules/organize/controllers/organize.php
 create mode 100644 modules/organize/css/organize_dialog.css
 create mode 100644 modules/organize/css/organize_frame.css
 create mode 100644 modules/organize/helpers/organize_event.php
 create mode 100644 modules/organize/helpers/organize_installer.php
 create mode 100644 modules/organize/module.info
 create mode 100644 modules/organize/vendor/ext/css/ext-all.css
 create mode 100644 modules/organize/vendor/ext/css/ux-all.css
 create mode 100644 modules/organize/vendor/ext/images/default/box/tb-blue.gif
 create mode 100644 modules/organize/vendor/ext/images/default/button/btn.gif
 create mode 100644 modules/organize/vendor/ext/images/default/dd/drop-no.gif
 create mode 100644 modules/organize/vendor/ext/images/default/dd/drop-yes.gif
 create mode 100644 modules/organize/vendor/ext/images/default/form/text-bg.gif
 create mode 100644 modules/organize/vendor/ext/images/default/form/trigger.gif
 create mode 100644 modules/organize/vendor/ext/images/default/grid/invalid_line.gif
 create mode 100644 modules/organize/vendor/ext/images/default/grid/loading.gif
 create mode 100644 modules/organize/vendor/ext/images/default/panel/tool-sprites.gif
 create mode 100644 modules/organize/vendor/ext/images/default/panel/white-top-bottom.gif
 create mode 100644 modules/organize/vendor/ext/images/default/progress/progress-bg.gif
 create mode 100644 modules/organize/vendor/ext/images/default/qtip/bg.gif
 create mode 100644 modules/organize/vendor/ext/images/default/s.gif
 create mode 100644 modules/organize/vendor/ext/images/default/shadow-c.png
 create mode 100644 modules/organize/vendor/ext/images/default/shadow-lr.png
 create mode 100644 modules/organize/vendor/ext/images/default/shadow.png
 create mode 100644 modules/organize/vendor/ext/images/default/toolbar/bg.gif
 create mode 100644 modules/organize/vendor/ext/images/default/tree/arrows.gif
 create mode 100644 modules/organize/vendor/ext/images/default/tree/drop-add.gif
 create mode 100644 modules/organize/vendor/ext/images/default/tree/drop-between.gif
 create mode 100644 modules/organize/vendor/ext/images/default/tree/drop-over.gif
 create mode 100644 modules/organize/vendor/ext/images/default/tree/folder-open.gif
 create mode 100644 modules/organize/vendor/ext/images/default/tree/folder.gif
 create mode 100644 modules/organize/vendor/ext/images/default/tree/loading.gif
 create mode 100644 modules/organize/vendor/ext/images/default/window/left-corners.png
 create mode 100644 modules/organize/vendor/ext/images/default/window/left-right.png
 create mode 100644 modules/organize/vendor/ext/images/default/window/right-corners.png
 create mode 100644 modules/organize/vendor/ext/images/default/window/top-bottom.png
 create mode 100644 modules/organize/vendor/ext/images/fam/delete.gif
 create mode 100644 modules/organize/vendor/ext/js/ext-organize-bundle.js
 create mode 100644 modules/organize/views/organize_dialog.html.php
 create mode 100644 modules/organize/views/organize_frame.html.php
 create mode 100644 modules/recaptcha/controllers/admin_recaptcha.php
 create mode 100644 modules/recaptcha/css/recaptcha.css
 create mode 100644 modules/recaptcha/helpers/recaptcha.php
 create mode 100644 modules/recaptcha/helpers/recaptcha_event.php
 create mode 100644 modules/recaptcha/helpers/recaptcha_installer.php
 create mode 100644 modules/recaptcha/helpers/recaptcha_theme.php
 create mode 100644 modules/recaptcha/libraries/Form_Recaptcha.php
 create mode 100644 modules/recaptcha/module.info
 create mode 100644 modules/recaptcha/views/admin_recaptcha.html.php
 create mode 100644 modules/recaptcha/views/form_recaptcha.html.php
 create mode 100644 modules/rest/controllers/rest.php
 create mode 100644 modules/rest/helpers/registry_rest.php
 create mode 100644 modules/rest/helpers/rest.php
 create mode 100644 modules/rest/helpers/rest_event.php
 create mode 100644 modules/rest/helpers/rest_installer.php
 create mode 100644 modules/rest/libraries/Rest_Exception.php
 create mode 100644 modules/rest/models/user_access_key.php
 create mode 100644 modules/rest/module.info
 create mode 100644 modules/rest/views/error_rest.json.php
 create mode 100644 modules/rest/views/reset_api_key_confirm.html.php
 create mode 100644 modules/rest/views/user_profile_rest.html.php
 create mode 100644 modules/rss/controllers/rss.php
 create mode 100644 modules/rss/helpers/rss.php
 create mode 100644 modules/rss/helpers/rss_block.php
 create mode 100644 modules/rss/module.info
 create mode 100644 modules/rss/views/feed.mrss.php
 create mode 100644 modules/rss/views/rss_block.html.php
 create mode 100644 modules/search/controllers/search.php
 create mode 100644 modules/search/helpers/search.php
 create mode 100644 modules/search/helpers/search_event.php
 create mode 100644 modules/search/helpers/search_installer.php
 create mode 100644 modules/search/helpers/search_task.php
 create mode 100644 modules/search/helpers/search_theme.php
 create mode 100644 modules/search/models/search_record.php
 create mode 100644 modules/search/module.info
 create mode 100644 modules/search/views/search.html.php
 create mode 100644 modules/search/views/search_link.html.php
 create mode 100644 modules/server_add/controllers/admin_server_add.php
 create mode 100644 modules/server_add/controllers/server_add.php
 create mode 100644 modules/server_add/css/server_add.css
 create mode 100644 modules/server_add/helpers/server_add.php
 create mode 100644 modules/server_add/helpers/server_add_event.php
 create mode 100644 modules/server_add/helpers/server_add_installer.php
 create mode 100644 modules/server_add/helpers/server_add_theme.php
 create mode 100644 modules/server_add/js/server_add.js
 create mode 100644 modules/server_add/models/server_add_entry.php
 create mode 100644 modules/server_add/module.info
 create mode 100644 modules/server_add/views/admin_server_add.html.php
 create mode 100644 modules/server_add/views/server_add_tree.html.php
 create mode 100644 modules/server_add/views/server_add_tree_dialog.html.php
 create mode 100644 modules/slideshow/helpers/slideshow_event.php
 create mode 100644 modules/slideshow/helpers/slideshow_installer.php
 create mode 100644 modules/slideshow/helpers/slideshow_theme.php
 create mode 100644 modules/slideshow/module.info
 create mode 100644 modules/tag/controllers/admin_tags.php
 create mode 100644 modules/tag/controllers/tag.php
 create mode 100644 modules/tag/controllers/tag_name.php
 create mode 100644 modules/tag/controllers/tags.php
 create mode 100644 modules/tag/css/tag.css
 create mode 100644 modules/tag/helpers/item_tags_rest.php
 create mode 100644 modules/tag/helpers/tag.php
 create mode 100644 modules/tag/helpers/tag_block.php
 create mode 100644 modules/tag/helpers/tag_event.php
 create mode 100644 modules/tag/helpers/tag_installer.php
 create mode 100644 modules/tag/helpers/tag_item_rest.php
 create mode 100644 modules/tag/helpers/tag_items_rest.php
 create mode 100644 modules/tag/helpers/tag_rest.php
 create mode 100644 modules/tag/helpers/tag_rss.php
 create mode 100644 modules/tag/helpers/tag_task.php
 create mode 100644 modules/tag/helpers/tag_theme.php
 create mode 100644 modules/tag/helpers/tags_rest.php
 create mode 100644 modules/tag/models/tag.php
 create mode 100644 modules/tag/module.info
 create mode 100644 modules/tag/views/admin_tags.html.php
 create mode 100644 modules/tag/views/tag_block.html.php
 create mode 100644 modules/tag/views/tag_cloud.html.php
 create mode 100644 modules/thumbnav/changelog.log
 create mode 100644 modules/thumbnav/controllers/admin_thumbnav.php
 create mode 100644 modules/thumbnav/css/thumbnav.css
 create mode 100644 modules/thumbnav/helpers/thumbnav_block.php
 create mode 100644 modules/thumbnav/helpers/thumbnav_event.php
 create mode 100644 modules/thumbnav/helpers/thumbnav_theme.php
 create mode 100644 modules/thumbnav/module.info
 create mode 100644 modules/thumbnav/views/admin_include.html.php
 create mode 100644 modules/thumbnav/views/admin_thumbnav.html.php
 create mode 100644 modules/thumbnav/views/thumbnav_block.html.php
 create mode 100644 modules/user/config/identity.php
 create mode 100644 modules/user/controllers/admin_users.php
 create mode 100644 modules/user/controllers/password.php
 create mode 100644 modules/user/controllers/users.php
 create mode 100644 modules/user/css/user.css
 create mode 100644 modules/user/helpers/group.php
 create mode 100644 modules/user/helpers/user.php
 create mode 100644 modules/user/helpers/user_event.php
 create mode 100644 modules/user/helpers/user_installer.php
 create mode 100644 modules/user/helpers/user_theme.php
 create mode 100644 modules/user/images/progressImg1.png
 create mode 100644 modules/user/js/password_strength.js
 create mode 100644 modules/user/lib/PasswordHash.php
 create mode 100644 modules/user/libraries/drivers/IdentityProvider/Gallery.php
 create mode 100644 modules/user/models/group.php
 create mode 100644 modules/user/models/user.php
 create mode 100644 modules/user/module.info
 create mode 100644 modules/user/views/admin_users.html.php
 create mode 100644 modules/user/views/admin_users_delete_user.html.php
 create mode 100644 modules/user/views/admin_users_group.html.php
 create mode 100644 modules/user/views/reset_password.html.php
 create mode 100644 modules/watermark/controllers/admin_watermarks.php
 create mode 100644 modules/watermark/helpers/watermark.php
 create mode 100644 modules/watermark/helpers/watermark_event.php
 create mode 100644 modules/watermark/helpers/watermark_installer.php
 create mode 100644 modules/watermark/module.info
 create mode 100644 modules/watermark/views/admin_watermarks.html.php
 create mode 100644 php.ini
 create mode 100644 robots.txt
 create mode 100644 serveradd/Raphael_2013-10-18_optimiert.mpg
 create mode 100644 system/KohanaLicense.html
 create mode 100644 system/config/cache.php
 create mode 100644 system/config/cookie.php
 create mode 100644 system/config/credit_cards.php
 create mode 100644 system/config/database.php
 create mode 100644 system/config/encryption.php
 create mode 100644 system/config/http.php
 create mode 100644 system/config/image.php
 create mode 100644 system/config/inflector.php
 create mode 100644 system/config/locale.php
 create mode 100644 system/config/log.php
 create mode 100644 system/config/mimes.php
 create mode 100644 system/config/profiler.php
 create mode 100644 system/config/routes.php
 create mode 100644 system/config/session.php
 create mode 100644 system/config/sql_types.php
 create mode 100644 system/config/upload.php
 create mode 100644 system/config/user_agents.php
 create mode 100644 system/config/view.php
 create mode 100644 system/controllers/template.php
 create mode 100644 system/core/Benchmark.php
 create mode 100644 system/core/Event.php
 create mode 100644 system/core/Kohana.php
 create mode 100644 system/core/Kohana_Config.php
 create mode 100644 system/core/Kohana_Exception.php
 create mode 100644 system/helpers/arr.php
 create mode 100644 system/helpers/cookie.php
 create mode 100644 system/helpers/date.php
 create mode 100644 system/helpers/db.php
 create mode 100644 system/helpers/download.php
 create mode 100644 system/helpers/expires.php
 create mode 100644 system/helpers/feed.php
 create mode 100644 system/helpers/file.php
 create mode 100644 system/helpers/form.php
 create mode 100644 system/helpers/format.php
 create mode 100644 system/helpers/html.php
 create mode 100644 system/helpers/inflector.php
 create mode 100644 system/helpers/num.php
 create mode 100644 system/helpers/remote.php
 create mode 100644 system/helpers/request.php
 create mode 100644 system/helpers/security.php
 create mode 100644 system/helpers/text.php
 create mode 100644 system/helpers/upload.php
 create mode 100644 system/helpers/url.php
 create mode 100644 system/helpers/utf8.php
 create mode 100644 system/helpers/valid.php
 create mode 100644 system/libraries/Cache.php
 create mode 100644 system/libraries/Cache_Exception.php
 create mode 100644 system/libraries/Controller.php
 create mode 100644 system/libraries/Database.php
 create mode 100644 system/libraries/Database_Builder.php
 create mode 100644 system/libraries/Database_Cache_Result.php
 create mode 100644 system/libraries/Database_Exception.php
 create mode 100644 system/libraries/Database_Expression.php
 create mode 100644 system/libraries/Database_Mysql.php
 create mode 100644 system/libraries/Database_Mysql_Result.php
 create mode 100644 system/libraries/Database_Mysqli.php
 create mode 100644 system/libraries/Database_Mysqli_Result.php
 create mode 100644 system/libraries/Database_Query.php
 create mode 100644 system/libraries/Database_Result.php
 create mode 100644 system/libraries/Encrypt.php
 create mode 100644 system/libraries/I18n.php
 create mode 100644 system/libraries/Image.php
 create mode 100644 system/libraries/Input.php
 create mode 100644 system/libraries/Kohana_404_Exception.php
 create mode 100644 system/libraries/Kohana_Log.php
 create mode 100644 system/libraries/Kohana_PHP_Exception.php
 create mode 100644 system/libraries/Kohana_User_Exception.php
 create mode 100644 system/libraries/Model.php
 create mode 100644 system/libraries/ORM.php
 create mode 100644 system/libraries/ORM_Iterator.php
 create mode 100644 system/libraries/ORM_Validation_Exception.php
 create mode 100644 system/libraries/Profiler.php
 create mode 100644 system/libraries/Profiler_Table.php
 create mode 100644 system/libraries/Router.php
 create mode 100644 system/libraries/Session.php
 create mode 100644 system/libraries/URI.php
 create mode 100644 system/libraries/Validation.php
 create mode 100644 system/libraries/View.php
 create mode 100644 system/libraries/drivers/Cache.php
 create mode 100644 system/libraries/drivers/Cache/File.php
 create mode 100644 system/libraries/drivers/Cache/Memcache.php
 create mode 100644 system/libraries/drivers/Cache/Xcache.php
 create mode 100644 system/libraries/drivers/Config.php
 create mode 100644 system/libraries/drivers/Config/Array.php
 create mode 100644 system/libraries/drivers/Image.php
 create mode 100644 system/libraries/drivers/Image/GD.php
 create mode 100644 system/libraries/drivers/Image/GraphicsMagick.php
 create mode 100644 system/libraries/drivers/Image/ImageMagick.php
 create mode 100644 system/libraries/drivers/Log.php
 create mode 100644 system/libraries/drivers/Log/Database.php
 create mode 100644 system/libraries/drivers/Log/File.php
 create mode 100644 system/libraries/drivers/Log/Syslog.php
 create mode 100644 system/libraries/drivers/Session.php
 create mode 100644 system/libraries/drivers/Session/Cache.php
 create mode 100644 system/libraries/drivers/Session/Cookie.php
 create mode 100644 system/libraries/drivers/Session/Database.php
 create mode 100644 system/messages/kohana/core.php
 create mode 100644 system/messages/validation/default.php
 create mode 100644 system/views/kohana/error.php
 create mode 100644 system/views/kohana/error_disabled.php
 create mode 100644 system/views/kohana/template.php
 create mode 100644 system/views/profiler/profiler.php
 create mode 100644 system/views/profiler/table.css
 create mode 100644 system/views/profiler/table.php
 create mode 100644 themes/admin_wind/css/fix-ie.css
 create mode 100644 themes/admin_wind/css/screen-rtl.css
 create mode 100644 themes/admin_wind/css/screen.css
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-icons_217bc0_256x240.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-icons_2e83ff_256x240.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-icons_469bdd_256x240.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-icons_6da8d5_256x240.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png
 create mode 100644 themes/admin_wind/css/themeroller/images/ui-icons_f9bd01_256x240.png
 create mode 100644 themes/admin_wind/css/themeroller/ui.base.css
 create mode 100644 themes/admin_wind/css/themeroller/ui.core.css
 create mode 100644 themes/admin_wind/css/themeroller/ui.datepicker.css
 create mode 100644 themes/admin_wind/css/themeroller/ui.dialog.css
 create mode 100644 themes/admin_wind/css/themeroller/ui.progressbar.css
 create mode 100644 themes/admin_wind/css/themeroller/ui.resizable.css
 create mode 100644 themes/admin_wind/css/themeroller/ui.tabs.css
 create mode 100644 themes/admin_wind/css/themeroller/ui.theme.css
 create mode 100644 themes/admin_wind/images/avatar.jpg
 create mode 100644 themes/admin_wind/images/ico-denied-inactive.png
 create mode 100644 themes/admin_wind/images/ico-denied-passive.png
 create mode 100644 themes/admin_wind/images/ico-denied.png
 create mode 100644 themes/admin_wind/images/ico-error.png
 create mode 100644 themes/admin_wind/images/ico-info.png
 create mode 100644 themes/admin_wind/images/ico-lock.png
 create mode 100644 themes/admin_wind/images/ico-separator-rtl.gif
 create mode 100644 themes/admin_wind/images/ico-separator.gif
 create mode 100644 themes/admin_wind/images/ico-success-inactive.png
 create mode 100644 themes/admin_wind/images/ico-success-passive.png
 create mode 100644 themes/admin_wind/images/ico-success.png
 create mode 100644 themes/admin_wind/images/ico-warning.png
 create mode 100644 themes/admin_wind/images/loading-large.gif
 create mode 100644 themes/admin_wind/images/loading-small.gif
 create mode 100644 themes/admin_wind/js/ui.init.js
 create mode 100644 themes/admin_wind/theme.info
 create mode 100644 themes/admin_wind/thumbnail.png
 create mode 100644 themes/admin_wind/views/admin.html.php
 create mode 100644 themes/admin_wind/views/block.html.php
 create mode 100644 themes/admin_wind/views/paginator.html.php
 create mode 100644 themes/greydragon/admin/controllers/admin_theme_options.php
 create mode 100644 themes/greydragon/admin/views/admin_theme_options.html.php
 create mode 100644 themes/greydragon/changelog.txt
 create mode 100644 themes/greydragon/controllers/greydragon.php
 create mode 100644 themes/greydragon/css/base.css
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/css/colors.css
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/ajax-loading.gif
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/colorpack.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/ico-album.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/ico-error.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/ico-help.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/ico-info.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/ico-warning.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/loading-large.gif
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/loading-small.gif
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/search.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/ui-icons.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/view-calendar-b.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/view-calendar.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/view-comments-b.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/view-comments.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/view-fullsize-b.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/view-fullsize.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/view-info-b.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/view-info-o.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/view-info.png
 create mode 100644 themes/greydragon/css/colorpacks/blackhawk/images/view-slideshow-b.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/css/colors.css
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/ajax-loading.gif
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/colorpack.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/ico-album.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/ico-error.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/ico-help.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/ico-info.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/ico-warning.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/loading-large.gif
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/loading-small.gif
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/search.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/section.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/ui-icons.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/view-calendar-b.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/view-calendar.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/view-comments-b.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/view-comments.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/view-fullsize-b.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/view-fullsize.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/view-info-b.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/view-info-o.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/view-info.png
 create mode 100644 themes/greydragon/css/colorpacks/carbon/images/view-slideshow-b.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/css/colors.css
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/ajax-loading.gif
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/background-bottom.gif
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/background-top.gif
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/background.gif
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/colorpack.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/footer.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/ico-album.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/ico-error.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/ico-help.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/ico-info.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/ico-warning.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/image-thumb.gif
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/loading-large.gif
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/loading-small.gif
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/search.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/section.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/ui-icons.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/view-calendar-b.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/view-calendar.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/view-comments-b.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/view-comments.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/view-fullsize-b.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/view-fullsize.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/view-info-b.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/view-info-o.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/view-info.png
 create mode 100644 themes/greydragon/css/colorpacks/greydragon/images/view-slideshow-b.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/css/colors.css
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/ajax-loading.gif
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/bg-body.jpg
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/bg-header.jpg
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/colorpack.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/gallery.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/ico-album.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/ico-error.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/ico-help.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/ico-info.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/ico-warning.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/loading-large.gif
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/loading-small.gif
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/search.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/ui-icons.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/view-calendar-b.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/view-calendar.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/view-comments-b.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/view-comments.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/view-fullsize-b.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/view-fullsize.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/view-info-b.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/view-info-o.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/view-info.png
 create mode 100644 themes/greydragon/css/colorpacks/roundrobin/images/view-slideshow-b.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/css/colors.css
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/ajax-loading.gif
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/background.jpg
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/colorpack.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/footer.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/ico-album.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/ico-error.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/ico-help.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/ico-info.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/ico-warning.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/loading-large.gif
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/loading-small.gif
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/search.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/section.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/ui-icons.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/view-calendar-b.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/view-calendar.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/view-comments-b.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/view-comments.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/view-fullsize-b.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/view-fullsize.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/view-info-b.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/view-info-o.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/view-info.png
 create mode 100644 themes/greydragon/css/colorpacks/slateblue/images/view-slideshow-b.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/css/colors.css
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/ajax-loading.gif
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/colorpack.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/gallery.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/ico-album.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/ico-error.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/ico-help.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/ico-info.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/ico-warning.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/loading-large.gif
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/loading-small.gif
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/search.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/ui-icons.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/view-calendar-b.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/view-calendar.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/view-comments-b.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/view-comments.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/view-fullsize-b.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/view-fullsize.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/view-info-b.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/view-info-o.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/view-info.png
 create mode 100644 themes/greydragon/css/colorpacks/whitehawk/images/view-slideshow-b.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/css/colors.css
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/ajax-loading.gif
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/colorpack.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/ico-album.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/ico-error.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/ico-help.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/ico-info.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/ico-view-fullsize.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/ico-view-slideshow-rtl.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/ico-view-slideshow.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/ico-warning.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/loading-large.gif
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/loading-small.gif
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/section.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/ui-icons.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/view-calendar.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/view-comments-b.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/view-comments.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/view-fullsize.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/view-info-b.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/view-info-o.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/view-info.png
 create mode 100644 themes/greydragon/css/colorpacks/wind/images/view-slideshow-b.png
 create mode 100644 themes/greydragon/css/custom.css
 create mode 100644 themes/greydragon/css/forms.css
 create mode 100644 themes/greydragon/css/framepacks/android/css/frame.css
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-dgt-e.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-dgt-eext.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-dgt-ext.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-dgt.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-flm-e.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-flm-eext.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-flm-ext.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-flm.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-sqr-e.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-sqr-eext.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-sqr-ext.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-sqr.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-wd-e.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-wd-eext.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-wd-ext.png
 create mode 100644 themes/greydragon/css/framepacks/android/images/thumb-wd.png
 create mode 100644 themes/greydragon/css/framepacks/book/css/frame.css
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-dgt-e.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-dgt-eext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-dgt-ext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-dgt.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-flm-e.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-flm-eext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-flm-ext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-flm.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-sqr-e.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-sqr-eext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-sqr-ext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-sqr.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-wd-e.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-wd-eext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-wd-ext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/a-thumb-wd.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-dgt-e.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-dgt-eext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-dgt-ext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-dgt.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-flm-e.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-flm-eext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-flm-ext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-flm.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-sqr-e.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-sqr-eext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-sqr-ext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-sqr.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-wd-e.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-wd-eext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-wd-ext.png
 create mode 100644 themes/greydragon/css/framepacks/book/images/thumb-wd.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/css/frame.css
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-e.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-eext.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-ext.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-dgt.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-flm-e.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-flm-eext.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-flm-ext.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-flm.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-e.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-eext.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-ext.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-sqr.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-wd-e.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-wd-eext.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-wd-ext.png
 create mode 100644 themes/greydragon/css/framepacks/darkglass/images/thumb-wd.png
 create mode 100644 themes/greydragon/css/framepacks/greydragon/css/frame.css
 create mode 100644 themes/greydragon/css/framepacks/iphone/css/frame.css
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-dgt-e.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-dgt-eext.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-dgt-ext.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-dgt.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-flm-e.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-flm-eext.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-flm-ext.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-flm.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-sqr-e.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-sqr-eext.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-sqr-ext.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-sqr.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-wd-e.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-wd-eext.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-wd-ext.png
 create mode 100644 themes/greydragon/css/framepacks/iphone/images/thumb-wd.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/css/frame.css
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-e.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-eext.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-ext.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-dgt.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-flm-e.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-flm-eext.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-flm-ext.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-flm.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-e.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-eext.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-ext.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-sqr.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-wd-e.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-wd-eext.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-wd-ext.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/images/thumb-wd.png
 create mode 100644 themes/greydragon/css/framepacks/iphoto/views/frame.html.php
 create mode 100644 themes/greydragon/css/framepacks/panel/css/frame.css
 create mode 100644 themes/greydragon/css/framepacks/roundcorners/css/frame.css
 create mode 100644 themes/greydragon/css/framepacks/simple/css/frame.css
 create mode 100644 themes/greydragon/css/framepacks/wall/css/frame.css
 create mode 100644 themes/greydragon/css/ipad.css
 create mode 100644 themes/greydragon/css/layout.css
 create mode 100644 themes/greydragon/css/menus.css
 create mode 100644 themes/greydragon/css/modules.css
 create mode 100644 themes/greydragon/css/normalize.css
 create mode 100644 themes/greydragon/css/rtl.css
 create mode 100644 themes/greydragon/css/screen.css
 create mode 100644 themes/greydragon/helpers/exif_event.php
 create mode 100644 themes/greydragon/helpers/greydragon_event.php
 create mode 100644 themes/greydragon/helpers/greydragon_installer.php
 create mode 100644 themes/greydragon/images/apple-touch-icon.png
 create mode 100644 themes/greydragon/images/arrows_left.png
 create mode 100644 themes/greydragon/images/arrows_right.png
 create mode 100644 themes/greydragon/images/avatar.jpg
 create mode 100644 themes/greydragon/images/blue-grad.png
 create mode 100644 themes/greydragon/images/button-grad-active-vs.png
 create mode 100644 themes/greydragon/images/button-grad-vs.png
 create mode 100644 themes/greydragon/images/close.png
 create mode 100644 themes/greydragon/images/donate.png
 create mode 100644 themes/greydragon/images/gallery.png
 create mode 100644 themes/greydragon/images/ico-allowed.png
 create mode 100644 themes/greydragon/images/ico-denied-inactive.png
 create mode 100644 themes/greydragon/images/ico-denied-passive.png
 create mode 100644 themes/greydragon/images/ico-denied.png
 create mode 100644 themes/greydragon/images/ico-error.png
 create mode 100644 themes/greydragon/images/ico-help.png
 create mode 100644 themes/greydragon/images/ico-info.png
 create mode 100644 themes/greydragon/images/ico-lock.png
 create mode 100644 themes/greydragon/images/ico-success-inactive.png
 create mode 100644 themes/greydragon/images/ico-success-passive.png
 create mode 100644 themes/greydragon/images/ico-success.png
 create mode 100644 themes/greydragon/images/ico-warning.png
 create mode 100644 themes/greydragon/images/missing-img.png
 create mode 100644 themes/greydragon/js/gallery.ajax.custom.js
 create mode 100644 themes/greydragon/js/gallery.dialog.custom.js
 create mode 100644 themes/greydragon/js/jquery-ui.min.js
 create mode 100644 themes/greydragon/js/jquery.cycle.js
 create mode 100644 themes/greydragon/js/jquery.form.custom.js
 create mode 100644 themes/greydragon/js/jquery.json.min.js
 create mode 100644 themes/greydragon/js/jquery.min.js
 create mode 100644 themes/greydragon/js/ui.support.js
 create mode 100644 themes/greydragon/libraries/MY_Theme_View.php
 create mode 100644 themes/greydragon/theme.info
 create mode 100644 themes/greydragon/thumbnail.png
 create mode 100644 themes/greydragon/views/album.html.php
 create mode 100644 themes/greydragon/views/block.html.php
 create mode 100644 themes/greydragon/views/calpage.html.php
 create mode 100644 themes/greydragon/views/dynamic.html.php
 create mode 100644 themes/greydragon/views/exif_sidebar.html.php
 create mode 100644 themes/greydragon/views/info_block.html.php
 create mode 100644 themes/greydragon/views/login_ajax.html.php
 create mode 100644 themes/greydragon/views/movie.html.php
 create mode 100644 themes/greydragon/views/no_sidebar.html.php
 create mode 100644 themes/greydragon/views/page.html.php
 create mode 100644 themes/greydragon/views/paginator.html.php
 create mode 100644 themes/greydragon/views/photo.html.php
 create mode 100644 themes/greydragon/views/rootpage.html.php
 create mode 100644 themes/greydragon/views/rootpage.html.php_fix
 create mode 100644 themes/greydragon/views/rss_block.html.php
 create mode 100644 themes/greydragon/views/search.html.php
 create mode 100644 themes/greydragon/views/sidebar.html.php
 create mode 100644 themes/greydragon/views/user_profile.html.php
 create mode 100644 themes/greydragon_old/admin/controllers/admin_theme_options.php
 create mode 100644 themes/greydragon_old/admin/views/admin_theme_options.html.php
 create mode 100644 themes/greydragon_old/changelog.txt
 create mode 100644 themes/greydragon_old/controllers/greydragon.php
 create mode 100644 themes/greydragon_old/css/base.css
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/css/colors.css
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/ajax-loading.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/colorpack.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/ico-album.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/ico-error.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/ico-help.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/ico-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/ico-warning.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/loading-large.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/loading-small.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/search.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/ui-icons.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/view-calendar-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/view-calendar.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/view-comments-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/view-comments.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/view-fullsize-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/view-fullsize.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/view-info-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/view-info-o.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/view-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/blackhawk/images/view-slideshow-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/css/colors.css
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/ajax-loading.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/colorpack.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/ico-album.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/ico-error.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/ico-help.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/ico-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/ico-warning.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/loading-large.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/loading-small.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/search.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/section.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/ui-icons.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/view-calendar-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/view-calendar.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/view-comments-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/view-comments.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/view-fullsize-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/view-fullsize.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/view-info-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/view-info-o.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/view-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/carbon/images/view-slideshow-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/css/colors.css
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/ajax-loading.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/background-bottom.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/background-top.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/background.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/colorpack.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/footer.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/ico-album.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/ico-error.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/ico-help.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/ico-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/ico-warning.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/image-thumb.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/loading-large.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/loading-small.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/search.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/section.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/ui-icons.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/view-calendar-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/view-calendar.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/view-comments-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/view-comments.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/view-fullsize-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/view-fullsize.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/view-info-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/view-info-o.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/view-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/greydragon/images/view-slideshow-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/css/colors.css
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/ajax-loading.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/bg-body.jpg
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/bg-header.jpg
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/colorpack.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/gallery.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/ico-album.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/ico-error.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/ico-help.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/ico-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/ico-warning.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/loading-large.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/loading-small.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/search.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/ui-icons.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/view-calendar-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/view-calendar.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/view-comments-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/view-comments.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/view-fullsize-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/view-fullsize.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/view-info-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/view-info-o.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/view-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/roundrobin/images/view-slideshow-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/css/colors.css
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/ajax-loading.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/background.jpg
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/colorpack.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/footer.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/ico-album.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/ico-error.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/ico-help.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/ico-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/ico-warning.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/loading-large.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/loading-small.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/search.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/section.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/ui-icons.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/view-calendar-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/view-calendar.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/view-comments-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/view-comments.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/view-fullsize-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/view-fullsize.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/view-info-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/view-info-o.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/view-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/slateblue/images/view-slideshow-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/css/colors.css
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/ajax-loading.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/colorpack.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/gallery.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/ico-album.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/ico-error.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/ico-help.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/ico-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/ico-warning.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/loading-large.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/loading-small.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/search.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/ui-icons.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/view-calendar-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/view-calendar.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/view-comments-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/view-comments.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/view-fullsize-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/view-fullsize.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/view-info-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/view-info-o.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/view-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/whitehawk/images/view-slideshow-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/css/colors.css
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/ajax-loading.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/colorpack.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/ico-album.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/ico-error.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/ico-help.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/ico-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/ico-view-fullsize.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/ico-view-slideshow-rtl.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/ico-view-slideshow.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/ico-warning.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/loading-large.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/loading-small.gif
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/section.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/ui-icons.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/view-calendar.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/view-comments-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/view-comments.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/view-fullsize.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/view-info-b.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/view-info-o.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/view-info.png
 create mode 100644 themes/greydragon_old/css/colorpacks/wind/images/view-slideshow-b.png
 create mode 100644 themes/greydragon_old/css/custom.css
 create mode 100644 themes/greydragon_old/css/forms.css
 create mode 100644 themes/greydragon_old/css/framepacks/android/css/frame.css
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-dgt-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-dgt-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-dgt-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-dgt.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-flm-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-flm-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-flm-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-flm.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-sqr-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-sqr-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-sqr-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-sqr.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-wd-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-wd-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-wd-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/android/images/thumb-wd.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/css/frame.css
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-flm.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/a-thumb-wd.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-dgt-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-dgt-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-dgt-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-dgt.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-flm-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-flm-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-flm-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-flm.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-sqr-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-sqr-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-sqr-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-sqr.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-wd-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-wd-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-wd-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/book/images/thumb-wd.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/css/frame.css
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd.png
 create mode 100644 themes/greydragon_old/css/framepacks/greydragon/css/frame.css
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/css/frame.css
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-flm.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphone/images/thumb-wd.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/css/frame.css
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-e.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-eext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-ext.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd.png
 create mode 100644 themes/greydragon_old/css/framepacks/iphoto/views/frame.html.php
 create mode 100644 themes/greydragon_old/css/framepacks/panel/css/frame.css
 create mode 100644 themes/greydragon_old/css/framepacks/roundcorners/css/frame.css
 create mode 100644 themes/greydragon_old/css/framepacks/simple/css/frame.css
 create mode 100644 themes/greydragon_old/css/framepacks/wall/css/frame.css
 create mode 100644 themes/greydragon_old/css/gd_common.css
 create mode 100644 themes/greydragon_old/css/ipad.css
 create mode 100644 themes/greydragon_old/css/layout.css
 create mode 100644 themes/greydragon_old/css/menus.css
 create mode 100644 themes/greydragon_old/css/modules.css
 create mode 100644 themes/greydragon_old/css/normalize.css
 create mode 100644 themes/greydragon_old/css/rtl.css
 create mode 100644 themes/greydragon_old/css/screen.css
 create mode 100644 themes/greydragon_old/helpers/exif_event.php
 create mode 100644 themes/greydragon_old/helpers/greydragon_event.php
 create mode 100644 themes/greydragon_old/helpers/greydragon_installer.php
 create mode 100644 themes/greydragon_old/helpers/greydragon_theme.php
 create mode 100644 themes/greydragon_old/images/apple-touch-icon.png
 create mode 100644 themes/greydragon_old/images/arrows_left.png
 create mode 100644 themes/greydragon_old/images/arrows_right.png
 create mode 100644 themes/greydragon_old/images/avatar.jpg
 create mode 100644 themes/greydragon_old/images/blue-grad.png
 create mode 100644 themes/greydragon_old/images/button-grad-active-vs.png
 create mode 100644 themes/greydragon_old/images/button-grad-vs.png
 create mode 100644 themes/greydragon_old/images/close.png
 create mode 100644 themes/greydragon_old/images/donate.png
 create mode 100644 themes/greydragon_old/images/gallery.png
 create mode 100644 themes/greydragon_old/images/ico-allowed.png
 create mode 100644 themes/greydragon_old/images/ico-denied-inactive.png
 create mode 100644 themes/greydragon_old/images/ico-denied-passive.png
 create mode 100644 themes/greydragon_old/images/ico-denied.png
 create mode 100644 themes/greydragon_old/images/ico-error.png
 create mode 100644 themes/greydragon_old/images/ico-help.png
 create mode 100644 themes/greydragon_old/images/ico-info.png
 create mode 100644 themes/greydragon_old/images/ico-lock.png
 create mode 100644 themes/greydragon_old/images/ico-success-inactive.png
 create mode 100644 themes/greydragon_old/images/ico-success-passive.png
 create mode 100644 themes/greydragon_old/images/ico-success.png
 create mode 100644 themes/greydragon_old/images/ico-warning.png
 create mode 100644 themes/greydragon_old/images/missing-img.png
 create mode 100644 themes/greydragon_old/js/jquery.cycle.js
 create mode 100644 themes/greydragon_old/js/ui.support.js
 create mode 100644 themes/greydragon_old/libraries/MY_Theme_View.php
 create mode 100644 themes/greydragon_old/module.info
 create mode 100644 themes/greydragon_old/theme.info
 create mode 100644 themes/greydragon_old/thumbnail.png
 create mode 100644 themes/greydragon_old/views/album.html.php
 create mode 100644 themes/greydragon_old/views/block.html.php
 create mode 100644 themes/greydragon_old/views/calpage.html.php
 create mode 100644 themes/greydragon_old/views/dynamic.html.php
 create mode 100644 themes/greydragon_old/views/exif_sidebar.html.php
 create mode 100644 themes/greydragon_old/views/gd_admin_include.html.php
 create mode 100644 themes/greydragon_old/views/info_block.html.php
 create mode 100644 themes/greydragon_old/views/movie.html.php
 create mode 100644 themes/greydragon_old/views/no_sidebar.html.php
 create mode 100644 themes/greydragon_old/views/page.html.php
 create mode 100644 themes/greydragon_old/views/paginator.html.php
 create mode 100644 themes/greydragon_old/views/photo.html.php
 create mode 100644 themes/greydragon_old/views/rootpage.html.php
 create mode 100644 themes/greydragon_old/views/rootpage.html.php_fix
 create mode 100644 themes/greydragon_old/views/rss_block.html.php
 create mode 100644 themes/greydragon_old/views/search.html.php
 create mode 100644 themes/greydragon_old/views/sidebar.html.php
 create mode 100644 themes/greydragon_old/views/user_profile.html.php
 create mode 100644 themes/wind/css/fix-ie.css
 create mode 100644 themes/wind/css/screen-rtl.css
 create mode 100644 themes/wind/css/screen.css
 create mode 100644 themes/wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png
 create mode 100644 themes/wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png
 create mode 100644 themes/wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png
 create mode 100644 themes/wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png
 create mode 100644 themes/wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png
 create mode 100644 themes/wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
 create mode 100644 themes/wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
 create mode 100644 themes/wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
 create mode 100644 themes/wind/css/themeroller/images/ui-icons_217bc0_256x240.png
 create mode 100644 themes/wind/css/themeroller/images/ui-icons_2e83ff_256x240.png
 create mode 100644 themes/wind/css/themeroller/images/ui-icons_469bdd_256x240.png
 create mode 100644 themes/wind/css/themeroller/images/ui-icons_6da8d5_256x240.png
 create mode 100644 themes/wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png
 create mode 100644 themes/wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png
 create mode 100644 themes/wind/css/themeroller/images/ui-icons_f9bd01_256x240.png
 create mode 100644 themes/wind/css/themeroller/ui.base.css
 create mode 100644 themes/wind/css/themeroller/ui.core.css
 create mode 100644 themes/wind/css/themeroller/ui.datepicker.css
 create mode 100644 themes/wind/css/themeroller/ui.dialog.css
 create mode 100644 themes/wind/css/themeroller/ui.progressbar.css
 create mode 100644 themes/wind/css/themeroller/ui.resizable.css
 create mode 100644 themes/wind/css/themeroller/ui.tabs.css
 create mode 100644 themes/wind/css/themeroller/ui.theme.css
 create mode 100644 themes/wind/images/avatar.jpg
 create mode 100644 themes/wind/images/ico-album.png
 create mode 100644 themes/wind/images/ico-denied-inactive.png
 create mode 100644 themes/wind/images/ico-denied-passive.png
 create mode 100644 themes/wind/images/ico-denied.png
 create mode 100644 themes/wind/images/ico-error.png
 create mode 100644 themes/wind/images/ico-help.png
 create mode 100644 themes/wind/images/ico-info.png
 create mode 100644 themes/wind/images/ico-lock.png
 create mode 100644 themes/wind/images/ico-print.png
 create mode 100644 themes/wind/images/ico-separator-rtl.gif
 create mode 100644 themes/wind/images/ico-separator.gif
 create mode 100644 themes/wind/images/ico-success-inactive.png
 create mode 100644 themes/wind/images/ico-success-passive.png
 create mode 100644 themes/wind/images/ico-success.png
 create mode 100644 themes/wind/images/ico-view-comments.png
 create mode 100644 themes/wind/images/ico-view-fullsize.png
 create mode 100644 themes/wind/images/ico-view-slideshow-rtl.png
 create mode 100644 themes/wind/images/ico-view-slideshow.png
 create mode 100644 themes/wind/images/ico-warning.png
 create mode 100644 themes/wind/images/loading-large.gif
 create mode 100644 themes/wind/images/loading-small.gif
 create mode 100644 themes/wind/images/select-photos-backg.png
 create mode 100644 themes/wind/js/ui.init.js
 create mode 100644 themes/wind/theme.info
 create mode 100755 themes/wind/thumbnail.png
 create mode 100644 themes/wind/views/album.html.php
 create mode 100644 themes/wind/views/block.html.php
 create mode 100644 themes/wind/views/dynamic.html.php
 create mode 100644 themes/wind/views/movie.html.php
 create mode 100644 themes/wind/views/no_sidebar.html.php
 create mode 100644 themes/wind/views/page.html.php
 create mode 100644 themes/wind/views/paginator.html.php
 create mode 100644 themes/wind/views/photo.html.php
 create mode 100644 themes/wind/views/sidebar.html.php

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..186857b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+var
diff --git a/.htaccess b/.htaccess
new file mode 100644
index 0000000..1df3359
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,82 @@
+# Set some reasonable defaults for PHP.  Most of these cannot be set
+# inside the script itself.  For hosts that don't have .htaccess
+# support but do support per-dir php.ini files, these settings are
+# mirrored in php.ini
+#
+<IfModule mod_php5.c>
+  php_flag short_open_tag            On
+  php_flag magic_quotes_gpc          Off
+  php_flag magic_quotes_sybase       Off
+  php_flag magic_quotes_runtime      Off
+  php_flag register_globals          Off
+  php_flag session.auto_start        Off
+  php_flag suhosin.session.encrypt   Off
+  php_value upload_max_filesize      100M
+  php_value post_max_size 	     100M
+</IfModule>
+
+# Try to disable the parts of mod_security that interfere with the Flash uploader
+#
+<IfModule mod_security.c>
+  SecFilterEngine Off
+  SecFilterScanPOST Off
+</IfModule>
+
+# Increase security by uncommenting this block.  It keeps browsers
+# from seeing support files that they shouldn't have access to.  We
+# comment this out because Apache2 requires some minor configuration
+# in order for you to use it.  You must specify "AllowOverride Limit"
+# in your Apache2 config file before you uncomment this block or
+# you'll get an "Internal Server Error".
+#
+# <FilesMatch "(\.(class|fla|gitignore|inc|ini|sql|txt)|(README|LICENSE|.build_number))$">
+#   Order deny,allow
+#   Deny from all
+# </FilesMatch>
+# <FilesMatch "robots.txt">
+#   Order allow,deny
+#   Allow from all
+# </FilesMatch>
+
+
+# Improve performance by uncommenting this block.  It tells the
+# browser that your images don't change very often so it won't keep
+# asking for them.  If you get an error after uncommenting this, make
+# sure you specify "AuthConfig Indexes" in your Apache config file.
+#
+# <IfModule mod_expires.c>
+#   ExpiresActive On
+#   # Cache all files for a month after access (A).
+#   ExpiresDefault A2678400
+#   # Do not cache dynamically generated pages.
+#   ExpiresByType text/html A1
+# </IfModule>
+
+# You can use the mod_rewrite Apache module to get rid of the
+# "index.php" from your Gallery 3 urls.  Uncomment the block below
+# inside the <IfModule> ... </IfModule> lines and then edit the
+# RewriteBase line to match your Gallery 3 URL.
+#
+# Here are some RewriteBase values:
+#   Gallery 3 URL                       RewriteBase line
+#   =============                       ====================
+#   http://example.com/gallery3         RewriteBase /gallery3
+#   http://example.com/~bob/photos      RewriteBase /~bob/photos
+#   http://gallery3.example.com/        RewriteBase /
+#
+# Then just use your Gallery 3 without the index.php in the url.
+#
+# NOTE: future upgrades of Gallery 3 will overwrite this file!  If you
+# want these changes to be persistent, talk to your system admin about
+# putting this block into your Apache config files.
+#
+# <IfModule mod_rewrite.c>
+#   Options +FollowSymLinks
+#   RewriteEngine On
+#   RewriteBase /
+#   RewriteCond %{REQUEST_FILENAME} !-f
+#   RewriteCond %{REQUEST_FILENAME} !-d
+#   RewriteRule ^(.*)$ index.php?kohana_uri=$1 [QSA,PT,L]
+#   RewriteRule ^$ index.php?kohana_uri=$1 [QSA,PT,L]
+#   RewriteRule ^index.php/(.*) $1 [QSA,R,L]
+# </IfModule>
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..3912109
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/README b/README
new file mode 100644
index 0000000..d9dc88a
--- /dev/null
+++ b/README
@@ -0,0 +1,85 @@
+Gallery 3.0.9 (Chartres)
+===========================
+
+About
+-----
+
+Gallery 3 is a web based software product that lets you manage your
+photos on your own website.  You must have your own website with PHP
+and database support in order to install and use it.  With Gallery you
+can easily create and share albums of photos via an intuitive
+interface.
+
+Intended Audience
+-----------------
+
+This version is intended for anybody who has a website.  We stand
+ready to support the product and help you to make the most of it. We
+welcome theme and module developers to play with this release and
+start turning out slick new designs for our happy users.  If you have
+questions or problems, you can get help in the Gallery forums:
+
+  http://galleryproject.org/forum/96
+
+Security
+--------
+
+We've contracted a professional security audit, received their results
+and resolved all the issues they found.
+
+Did you find a security flaw?  Please email security@galleryproject.org
+with the details and we'll fix it ASAP!
+
+Supported Configuration
+-----------------------
+
+ - Platform: Linux / Unix.
+ - Web server: Apache 2.2 and newer.
+ - PHP 5.2.3 and newer (PHP's safe_mode must be disabled and simplexml,
+   filter, and json must be installed).
+ - Database: MySQL 5 and newer.
+
+For complete system requirements, please refer to:
+
+  http://codex.galleryproject.org/Gallery3:Requirements
+
+Installing and Upgrading Instructions
+-------------------------------------
+
+For comprehensive instructions, The online User Guide is your best resource:
+
+  http://codex.galleryproject.org/Gallery3:User_guide
+
+There are also simple instructions below.  NOTE: You can upgrade from
+beta 1 and beyond, but not from alpha releases.
+
+ INSTALLATION VIA THE WEB
+
+Point your web browser at gallery3/installer/ and follow the
+instructions.
+
+ INSTALLATION FROM THE COMMAND LINE
+
+php installer/index.php [-h host] [-u user] [-p pass] [-d dbname]
+
+ Command line parameters:
+
+ -h     Database host          (default: localhost)
+ -u     Database user          (default: root)
+ -p     Database user password (default: )
+ -d     Database name          (default: gallery3)
+ -x     Table prefix           (default: )
+
+Bugs?
+-----
+
+Go to http://apps.sourceforge.net/trac/gallery/ click the "login" link
+and log in with your SourceForge username and password, then click the
+"new ticket" button.
+
+Questions, Problems
+-------------------
+
+ - Check out the Gallery 3 FAQ: http://codex.galleryproject.org/Gallery3:FAQ
+ - Post to the Gallery 3 forums: http://galleryproject.org/forum/96
+ - Email gallery-devel@lists.sourceforge.net
diff --git a/application/Bootstrap.php b/application/Bootstrap.php
new file mode 100644
index 0000000..93353b4
--- /dev/null
+++ b/application/Bootstrap.php
@@ -0,0 +1,67 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+// Kohana benchmarks are prefixed to prevent collisions
+define('SYSTEM_BENCHMARK', 'system_benchmark');
+
+// Load benchmarking support
+require SYSPATH.'core/Benchmark'.EXT;
+
+// Start total_execution
+Benchmark::start(SYSTEM_BENCHMARK.'_total_execution');
+
+// Start kohana_loading
+Benchmark::start(SYSTEM_BENCHMARK.'_kohana_loading');
+
+// Load core files
+require SYSPATH.'core/Event'.EXT;
+final class Event extends Event_Core {}
+
+require SYSPATH.'core/Kohana'.EXT;
+final class Kohana extends Kohana_Core {}
+
+require SYSPATH.'core/Kohana_Exception'.EXT;
+require MODPATH.'gallery/libraries/MY_Kohana_Exception'.EXT;
+
+require SYSPATH.'core/Kohana_Config'.EXT;
+require SYSPATH.'libraries/drivers/Config'.EXT;
+require SYSPATH.'libraries/drivers/Config/Array'.EXT;
+final class Kohana_Config extends Kohana_Config_Core {}
+
+// Prepare the environment
+Kohana::setup();
+
+// End kohana_loading
+Benchmark::stop(SYSTEM_BENCHMARK.'_kohana_loading');
+
+// Start system_initialization
+Benchmark::start(SYSTEM_BENCHMARK.'_system_initialization');
+
+// Prepare the system
+Event::run('system.ready');
+
+// Determine routing
+Event::run('system.routing');
+
+// End system_initialization
+Benchmark::stop(SYSTEM_BENCHMARK.'_system_initialization');
+
+// Make the magic happen!
+Event::run('system.execute');
\ No newline at end of file
diff --git a/application/config/config.php b/application/config/config.php
new file mode 100644
index 0000000..5adeaa3
--- /dev/null
+++ b/application/config/config.php
@@ -0,0 +1,156 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * Base path of the web site. If this includes a domain, eg: localhost/kohana/
+ * then a full URL will be used, eg: http://localhost/kohana/. If it only includes
+ * the path, and a site_protocol is specified, the domain will be auto-detected.
+ *
+ * Here we do our best to autodetect the base path to Gallery.  If your url is something like:
+ *   http://example.com/gallery3/index.php/album73/photo5.jpg?param=value
+ *
+ * We want the site_domain to be:
+ *   /gallery3
+ *
+ * In the above example, $_SERVER["SCRIPT_NAME"] contains "/gallery3/index.php" so
+ * dirname($_SERVER["SCRIPT_NAME"]) is what we need.  Except some low end hosts (namely 1and1.com)
+ * break SCRIPT_NAME and it contains the extra path info, so in the above example it'd be:
+ *   /gallery3/index.php/album73/photo5.jpg
+ *
+ * So dirname doesn't work.  So we do a tricky workaround where we look up the SCRIPT_FILENAME (in
+ * this case it'd be "index.php" and we delete from that part onwards.  If you work at 1and1 and
+ * you're reading this, please fix this bug!
+ *
+ * Rawurlencode each of the elements to avoid breaking the page layout.
+ */
+$config["site_domain"] =
+  implode("/", array_map("rawurlencode", explode("/",
+      substr($_SERVER["SCRIPT_NAME"], 0,
+             strpos($_SERVER["SCRIPT_NAME"], basename($_SERVER["SCRIPT_FILENAME"]))))));
+
+/**
+ * Force a default protocol to be used by the site. If no site_protocol is
+ * specified, then the current protocol is used, or when possible, only an
+ * absolute path (with no protocol/domain) is used.
+ */
+$config["site_protocol"] = "";
+
+/**
+ * Name of the front controller for this application. Default: index.php
+ *
+ * This can be removed by using URL rewriting.
+ */
+$config["index_page"] = isset($_GET["kohana_uri"]) ? "" : "index.php";
+
+/**
+ * Fake file extension that will be added to all generated URLs. Example: .html
+ */
+$config["url_suffix"] = "";
+
+/**
+ * Length of time of the internal cache in seconds. 0 or FALSE means no caching.
+ * The internal cache stores file paths and config entries across requests and
+ * can give significant speed improvements at the expense of delayed updating.
+ */
+$config["internal_cache"] = FALSE;
+$config["internal_cache_path"] = VARPATH . "tmp/";
+
+/**
+ * Enable or disable gzip output compression. This can dramatically decrease
+ * server bandwidth usage, at the cost of slightly higher CPU usage. Set to
+ * the compression level (1-9) that you want to use, or FALSE to disable.
+ *
+ * Do not enable this option if you are using output compression in php.ini!
+ */
+$config["output_compression"] = FALSE;
+
+/**
+ * Enable or disable global XSS filtering of GET, POST, and SERVER data. This
+ * option also accepts a string to specify a specific XSS filtering tool.
+ */
+$config["global_xss_filtering"] = TRUE;
+
+/**
+ * Enable or disable hooks. Setting this option to TRUE will enable
+ * all hooks. By using an array of hook filenames, you can control
+ * which hooks are enabled. Setting this option to FALSE disables hooks.
+ */
+$config["enable_hooks"] = TRUE;
+
+/**
+ * Log thresholds:
+ *  0 - Disable logging
+ *  1 - Errors and exceptions
+ *  2 - Warnings
+ *  3 - Notices
+ *  4 - Debugging
+ */
+$config["log_threshold"] = 3;
+
+/**
+ * Message logging directory.
+ */
+$config["log_directory"] = VARPATH . "logs";
+if (@!is_writable($config["log_directory"])) {
+  $config["log_threshold"] = 0;
+}
+
+/**
+ * Enable or disable displaying of Kohana error pages. This will not affect
+ * logging. Turning this off will disable ALL error pages.
+ */
+$config["display_errors"] = TRUE;
+
+/**
+ * Enable or disable statistics in the final output. Stats are replaced via
+ * specific strings, such as {execution_time}.
+ *
+ * @see http://docs.kohanaphp.com/general/configuration
+ */
+$config["render_stats"] = TRUE;
+
+/**
+ * Filename prefixed used to determine extensions. For example, an
+ * extension to the Controller class would be named MY_Controller.php.
+ */
+$config["extension_prefix"] = "MY_";
+
+/**
+ * An optional list of Config Drivers to use, they "fallback" to the one below them if they
+ * dont work so the first driver is tried then so on until it hits the built in "array" driver and fails
+ */
+$config['config_drivers'] = array();
+
+/**
+ * Additional resource paths, or "modules". Each path can either be absolute
+ * or relative to the docroot. Modules can include any resource that can exist
+ * in your application directory, configuration files, controllers, views, etc.
+ */
+$config["modules"] = array(
+  MODPATH . "forge",
+  MODPATH . "kohana23_compat",
+  MODPATH . "gallery",  // gallery must be *last* in the order
+);
+
+if (TEST_MODE) {
+  array_splice($config["modules"], 0, 0,
+               array(MODPATH . "gallery_unit_test",
+                     MODPATH . "unit_test"));
+}
diff --git a/bin/.htaccess b/bin/.htaccess
new file mode 100755
index 0000000..a381552
--- /dev/null
+++ b/bin/.htaccess
@@ -0,0 +1,8 @@
+DirectoryIndex .htaccess
+SetHandler Gallery_Security_Do_Not_Remove
+Options None
+<IfModule mod_rewrite.c>
+RewriteEngine off
+</IfModule>
+Order allow,deny
+Deny from all
diff --git a/bin/README b/bin/README
new file mode 100644
index 0000000..ec09639
--- /dev/null
+++ b/bin/README
@@ -0,0 +1,5 @@
+This directory contains utility software that Gallery uses to perform
+image manipulation and other useful functions.  It should not be
+accessible from a web browser, and by default it's empty.  Gallery
+will instruct you when it's appropriate to download software and
+install it here.
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..e6636cf
--- /dev/null
+++ b/index.php
@@ -0,0 +1,116 @@
+<?php
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+// Set this to true to disable demo/debugging controllers
+define("IN_PRODUCTION", true);
+
+// Gallery requires PHP 5.2+
+version_compare(PHP_VERSION, "5.2.3", "<") and
+  exit("Gallery requires PHP 5.2.3 or newer (you're using " . PHP_VERSION  . ")");
+
+// Gallery is not supported on Windows.
+if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+  exit("Gallery is not supported on Windows (PHP reports that you're using: " . PHP_OS . ")");
+}
+
+// PHP 5.4 requires a timezone - if one isn't set date functions aren't going to work properly.
+// We'll log this once the logging system is initialized (in the gallery_event::gallery_ready).
+if (!ini_get("date.timezone")) {
+  ini_set("date.timezone", "UTC");
+}
+
+// Gallery requires short_tags to be on
+!ini_get("short_open_tag") and exit("Gallery requires short_open_tag to be on.");
+
+// Suppress errors.  For information on how to debug Gallery 3, see:
+// http://codex.galleryproject.org/Gallery3:FAQ#How_do_I_see_debug_information.3F
+error_reporting(0);
+
+// Disabling display_errors will  effectively disable Kohana error display
+// and logging. You can turn off Kohana errors in application/config/config.php
+ini_set("display_errors", false);
+
+// Turn off session.use_trans_sid -- that feature attempts to inject session ids
+// into generated URLs and forms, but it doesn't interoperate will with Gallery's
+// Ajax code.
+ini_set("session.use_trans_sid", false);
+
+// Restrict all response frames to the same origin for security
+header("X-Frame-Options: SAMEORIGIN");
+
+define("EXT", ".php");
+define("DOCROOT", getcwd() . "/");
+define("KOHANA",  "index.php");
+
+// If the front controller is a symlink, change to the real docroot
+is_link(basename(__FILE__)) and chdir(dirname(realpath(__FILE__)));
+
+// Define application and system paths
+define("APPPATH", realpath("application") . "/");
+define("MODPATH", realpath("modules") . "/");
+define("THEMEPATH", realpath("themes") . "/");
+define("SYSPATH", realpath("system") . "/");
+
+// We only accept a few controllers on the command line
+if (PHP_SAPI == "cli") {
+  switch ($arg_1 = $_SERVER["argv"][1]) {
+  case "install":
+    include("installer/index.php");
+    exit(0);
+  case "upgrade":
+  case "package":
+    $_SERVER["argv"] = array("index.php", "{$arg_1}r/$arg_1");
+    define("TEST_MODE", 0);
+    define("VARPATH", realpath("var") . "/");
+    break;
+
+  case "test":
+    array_splice($_SERVER["argv"], 1, 1, "gallery_unit_test");
+    define("TEST_MODE", 1);
+    if (!is_dir("test/var")) {
+      @mkdir("test/var", 0777, true);
+      @mkdir("test/var/logs", 0777, true);
+    }
+    @copy("var/database.php", "test/var/database.php");
+    define("VARPATH", realpath("test/var") . "/");
+    break;
+
+  default:
+    print "To install:\n";
+    print "  php index.php install -d database -h host -u user -p password -x table_prefix -g3p gallery3_admin_password \n\n";
+    print "To upgrade:\n";
+    print "  php index.php upgrade\n\n";
+    print "Developer-only features:\n";
+    print "  ** CAUTION! THESE FEATURES -WILL- DAMAGE YOUR INSTALL **\n";
+    print "  php index.php package  # create new installer files\n";
+    print "  php index.php test     # run unit tests\n";
+    exit(1);
+  }
+} else {
+  define("TEST_MODE", 0);
+  define("VARPATH", realpath("var") . "/");
+}
+define("TMPPATH", VARPATH . "tmp/");
+
+if (file_exists("local.php")) {
+  include("local.php");
+}
+
+// Initialize.
+require APPPATH . "Bootstrap" . EXT;
diff --git a/installer/cli.php b/installer/cli.php
new file mode 100644
index 0000000..b31405f
--- /dev/null
+++ b/installer/cli.php
@@ -0,0 +1,121 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+/**
+ * Command line parameters:
+ * -h     Database host          (default: localhost)
+ * -u     Database user          (default: root)
+ * -p     Database user password (default: )
+ * -d     Database name          (default: gallery3)
+ * -x     Table prefix           (default: )
+ */
+if (installer::already_installed()) {
+  print "Gallery 3 is already installed.\n";
+  return;
+}
+
+$errors = installer::check_environment();
+if ($errors) {
+  oops(implode($errors, "\n"));
+}
+
+$config = parse_cli_params();
+if (!installer::connect($config)) {
+  oops("Unable to connect to the database.\n" . mysql_error() . "\n");
+} else if (!installer::select_db($config)) {
+  oops("Database {$config['dbname']} doesn't exist and can't be created.  " .
+       "Please create the database by hand.");
+} else if (is_string($count = installer::db_empty($config)) || !$count) {
+  if (is_string($count)) {
+    oops($count);
+  } else {
+    oops("Database {$config['dbname']} already has Gallery 3 tables in it. \n" .
+         "    Please remove the Gallery 3 tables, change your prefix,\n" .
+         "    or specify an empty database.\n");
+  }
+} else if (!installer::unpack_var()) {
+  oops("Unable to create files inside the 'var' directory");
+} else if (!installer::unpack_sql($config)) {
+  oops("Failed to create database tables\n" . mysql_error());
+} else if (!installer::create_database_config($config)) {
+  oops("Couldn't create var/database.php");
+} else {
+  system("chmod -R 777 " . VARPATH);
+  try {
+    list ($user, $password) = installer::create_admin($config);
+    print "Your Gallery has been successfully installed!\n";
+    print "We've created an account for you to use:\n";
+    print "  username: $user\n";
+    print "  password: $password\n";
+    print "\n";
+
+    installer::create_private_key($config);
+    exit(0);
+  } catch (Exception $e) {
+    oops($e->getMessage());
+  }
+}
+
+function oops($message) {
+  print "Oops! Something went wrong during the installation:\n\n";
+
+  print "==> " . $message;
+  print "\n";
+  print "For help you can try:\n";
+  print "  * The Gallery 3 FAQ   - http://codex.galleryproject.org/Gallery3:FAQ\n";
+  print "  * The Gallery Forums - http://galleryproject.org/forum\n";
+  print "\n\n** INSTALLATION FAILED **\n";
+  exit(1);
+}
+
+function parse_cli_params() {
+  $config = array("host" => "localhost",
+                  "user" => "root",
+                  "password" => "",
+                  "dbname" => "gallery3",
+                  "prefix" => "",
+                  "g3_password" => "",
+                  "type" => function_exists("mysqli_set_charset") ? "mysqli" : "mysql");
+
+  $argv = $_SERVER["argv"];
+  for ($i = 1; $i < count($argv); $i++) {
+    switch (strtolower($argv[$i])) {
+    case "-d":
+      $config["dbname"] = $argv[++$i];
+      break;
+    case "-h":
+      list ($config["host"], $config["port"]) = explode(":", $argv[++$i]);
+      break;
+    case "-u":
+      $config["user"] = $argv[++$i];
+      break;
+    case "-p":
+      $config["password"] = $argv[++$i];
+      break;
+    case "-x":
+      $config["prefix"] = $argv[++$i];
+      break;
+    case "-g3p":
+      $config["g3_password"] = $argv[++$i];
+      break;
+    }
+  }
+
+  return $config;
+}
diff --git a/installer/database_config.php b/installer/database_config.php
new file mode 100644
index 0000000..fb7dd11
--- /dev/null
+++ b/installer/database_config.php
@@ -0,0 +1,46 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?php print "<?php" ?> defined("SYSPATH") or die("No direct script access.");
+
+/**
+ * @package  Database
+ *
+ * Database connection settings, defined as arrays, or "groups". If no group
+ * name is used when loading the database library, the group named "default"
+ * will be used.
+ *
+ * Each group can be connected to independently, and multiple groups can be
+ * connected at once.
+ *
+ * Group Options:
+ *  benchmark     - Enable or disable database benchmarking
+ *  persistent    - Enable or disable a persistent connection
+ *  connection    - Array of connection specific parameters; alternatively,
+ *                  you can use a DSN though it is not as fast and certain
+ *                  characters could create problems (like an '@' character
+ *                  in a password):
+ *                  'connection'    => 'mysql://dbuser:secret@localhost/kohana'
+ *  character_set - Database character set
+ *  table_prefix  - Database table prefix
+ *  object        - Enable or disable object results
+ *  cache         - Enable or disable query caching
+ *  escape        - Enable automatic query builder escaping
+ */
+$config['default'] = array(
+  'benchmark'     => false,
+  'persistent'    => false,
+  'connection'    => array(
+    'type'     => '<?php print $type ?>',
+    'user'     => '<?php print $user ?>',
+    'pass'     => '<?php print $password ?>',
+    'host'     => '<?php print $host ?>',
+    'port'     => <?php if (!empty($port)): ?>'<?php print $port ?>' <?php else: ?>false<?php endif ?>,
+    'socket'   => false,
+    'database' => '<?php print $dbname ?>',
+    'params'   => null,
+  ),
+  'character_set' => 'utf8',
+  'table_prefix'  => '<?php print $prefix ?>',
+  'object'        => true,
+  'cache'         => false,
+  'escape'        => true
+);
\ No newline at end of file
diff --git a/installer/index.php b/installer/index.php
new file mode 100644
index 0000000..651edc9
--- /dev/null
+++ b/installer/index.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+define("DOCROOT", dirname(dirname(__FILE__)) . "/");
+define("VARPATH", DOCROOT . "var/");
+define("SYSPATH", "DEFINED_TO_SOMETHING_SO_THAT_WE_CAN_KEEP_CONSISTENT_PREAMBLES_IN_THE_INSTALLER");
+
+if (version_compare(PHP_VERSION, "5.2.3", "<")) {
+  print "Gallery 3 requires PHP 5.2.3 or newer.\n";
+  exit;
+}
+
+// Turn off session.use_trans_sid -- that feature attempts to inject session ids
+// into generated URLs and forms, but it doesn't interoperate will with Gallery's
+// Ajax code.
+ini_set("session.use_trans_sid", false);
+
+require(DOCROOT . "installer/installer.php");
+if (PHP_SAPI == "cli") {
+  include("cli.php");
+} else {
+  include("web.php");
+}
+
diff --git a/installer/init_var.php b/installer/init_var.php
new file mode 100755
index 0000000..353665a
--- /dev/null
+++ b/installer/init_var.php
@@ -0,0 +1,12 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?php
+!file_exists(VARPATH . "albums") && mkdir(VARPATH . "albums");
+!file_exists(VARPATH . "logs") && mkdir(VARPATH . "logs");
+!file_exists(VARPATH . "modules") && mkdir(VARPATH . "modules");
+!file_exists(VARPATH . "resizes") && mkdir(VARPATH . "resizes");
+!file_exists(VARPATH . "thumbs") && mkdir(VARPATH . "thumbs");
+!file_exists(VARPATH . "tmp") && mkdir(VARPATH . "tmp");
+!file_exists(VARPATH . "uploads") && mkdir(VARPATH . "uploads");
+file_put_contents(VARPATH . "logs/.htaccess", base64_decode("RGlyZWN0b3J5SW5kZXggLmh0YWNjZXNzClNldEhhbmRsZXIgR2FsbGVyeV9TZWN1cml0eV9Eb19Ob3RfUmVtb3ZlCk9wdGlvbnMgTm9uZQo8SWZNb2R1bGUgbW9kX3Jld3JpdGUuYz4KUmV3cml0ZUVuZ2luZSBvZmYKPC9JZk1vZHVsZT4KT3JkZXIgYWxsb3csZGVueQpEZW55IGZyb20gYWxsCg=="));
+file_put_contents(VARPATH . "tmp/.htaccess", base64_decode("RGlyZWN0b3J5SW5kZXggLmh0YWNjZXNzClNldEhhbmRsZXIgR2FsbGVyeV9TZWN1cml0eV9Eb19Ob3RfUmVtb3ZlCk9wdGlvbnMgTm9uZQo8SWZNb2R1bGUgbW9kX3Jld3JpdGUuYz4KUmV3cml0ZUVuZ2luZSBvZmYKPC9JZk1vZHVsZT4KT3JkZXIgYWxsb3csZGVueQpEZW55IGZyb20gYWxsCg=="));
+file_put_contents(VARPATH . "uploads/.htaccess", base64_decode("RGlyZWN0b3J5SW5kZXggLmh0YWNjZXNzClNldEhhbmRsZXIgR2FsbGVyeV9TZWN1cml0eV9Eb19Ob3RfUmVtb3ZlCk9wdGlvbnMgTm9uZQo8SWZNb2R1bGUgbW9kX3Jld3JpdGUuYz4KUmV3cml0ZUVuZ2luZSBvZmYKPC9JZk1vZHVsZT4KT3JkZXIgYWxsb3csZGVueQpEZW55IGZyb20gYWxsCg=="));
diff --git a/installer/install.css b/installer/install.css
new file mode 100644
index 0000000..e132b80
--- /dev/null
+++ b/installer/install.css
@@ -0,0 +1,92 @@
+h1, h2, h3 {
+    margin-bottom: .1em;
+}
+
+body {
+    background: #eee;
+    font-family: Trebuchet MS, Verdana;
+    font-size: 1.1em;
+}
+
+em {
+  font-style: italic;
+}
+
+div#outer {
+    width: 650px;
+    background: white;
+    border: 1px solid #999;
+    margin: 0 auto;
+    padding: -10px;
+}
+
+div#inner {
+    padding: 0 1em 0 1em;
+    margin: 0px;
+}
+
+div#footer {
+    border-top: 1px solid #ccc;
+    margin: 1em;
+}
+
+.error {
+    border: 1px solid red;
+    background: #fcc;
+    padding: 4px;
+}
+
+.success {
+    border: 1px solid green;
+    background: #cfc;
+    padding: 4px;
+}
+
+p {
+    margin: 0px;
+    padding: 0px;
+}
+
+fieldset {
+    border: 0px;
+    padding-left: 0px;
+    margin-top: 1em;
+    border: 1px solid #ccc;
+    padding: 8px;
+}
+
+fieldset legend {
+    font-weight: bold;
+    margin: 8px;
+    padding: 2px;
+}
+
+table#db_info {
+  padding-left: 2em;
+}
+
+table td {
+  padding-right: 1em;
+}
+
+code {
+  background: #eee;
+  border: 1px solid #bbb;
+  padding: 2px;
+  display: block;
+  width: 200px;
+  margin: 4px 4px 4px 20px;
+}
+
+code.location {
+  display: block;
+  margin: 4px;
+  padding: 4px;
+  width: auto;
+}
+
+span.subtext {
+  font-size: .7em;
+  color: #999;
+}
+
diff --git a/installer/install.sql b/installer/install.sql
new file mode 100644
index 0000000..f4938f6
--- /dev/null
+++ b/installer/install.sql
@@ -0,0 +1,433 @@
+DROP TABLE IF EXISTS {access_caches};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {access_caches} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `item_id` int(9) DEFAULT NULL,
+  `view_full_1` binary(1) NOT NULL DEFAULT '0',
+  `edit_1` binary(1) NOT NULL DEFAULT '0',
+  `add_1` binary(1) NOT NULL DEFAULT '0',
+  `view_full_2` binary(1) NOT NULL DEFAULT '0',
+  `edit_2` binary(1) NOT NULL DEFAULT '0',
+  `add_2` binary(1) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  KEY `item_id` (`item_id`)
+) AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {access_caches} VALUES (1,1,'1','0','0','1','0','0');
+DROP TABLE IF EXISTS {access_intents};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {access_intents} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `item_id` int(9) DEFAULT NULL,
+  `view_1` binary(1) DEFAULT NULL,
+  `view_full_1` binary(1) DEFAULT NULL,
+  `edit_1` binary(1) DEFAULT NULL,
+  `add_1` binary(1) DEFAULT NULL,
+  `view_2` binary(1) DEFAULT NULL,
+  `view_full_2` binary(1) DEFAULT NULL,
+  `edit_2` binary(1) DEFAULT NULL,
+  `add_2` binary(1) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {access_intents} VALUES (1,1,'1','1','0','0','1','1','0','0');
+DROP TABLE IF EXISTS {caches};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {caches} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `key` varchar(255) NOT NULL,
+  `tags` varchar(255) DEFAULT NULL,
+  `expiration` int(9) NOT NULL,
+  `cache` longblob,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `key` (`key`),
+  KEY `tags` (`tags`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS {comments};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {comments} (
+  `author_id` int(9) DEFAULT NULL,
+  `created` int(9) NOT NULL,
+  `guest_email` varchar(128) DEFAULT NULL,
+  `guest_name` varchar(128) DEFAULT NULL,
+  `guest_url` varchar(255) DEFAULT NULL,
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `item_id` int(9) NOT NULL,
+  `server_http_accept_charset` varchar(64) DEFAULT NULL,
+  `server_http_accept_encoding` varchar(64) DEFAULT NULL,
+  `server_http_accept_language` varchar(64) DEFAULT NULL,
+  `server_http_accept` varchar(128) DEFAULT NULL,
+  `server_http_connection` varchar(64) DEFAULT NULL,
+  `server_http_host` varchar(64) DEFAULT NULL,
+  `server_http_referer` varchar(255) DEFAULT NULL,
+  `server_http_user_agent` varchar(128) DEFAULT NULL,
+  `server_query_string` varchar(64) DEFAULT NULL,
+  `server_remote_addr` varchar(40) DEFAULT NULL,
+  `server_remote_host` varchar(255) DEFAULT NULL,
+  `server_remote_port` varchar(16) DEFAULT NULL,
+  `state` varchar(15) DEFAULT 'unpublished',
+  `text` text,
+  `updated` int(9) NOT NULL,
+  PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS {failed_auths};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {failed_auths} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `count` int(9) NOT NULL,
+  `name` varchar(255) NOT NULL,
+  `time` int(9) NOT NULL,
+  PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS {graphics_rules};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {graphics_rules} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `active` tinyint(1) DEFAULT '0',
+  `args` varchar(255) DEFAULT NULL,
+  `module_name` varchar(64) NOT NULL,
+  `operation` varchar(64) NOT NULL,
+  `priority` int(9) NOT NULL,
+  `target` varchar(32) NOT NULL,
+  PRIMARY KEY (`id`)
+) AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {graphics_rules} VALUES (1,1,'a:3:{s:5:\"width\";i:200;s:6:\"height\";i:200;s:6:\"master\";i:2;}','gallery','gallery_graphics::resize',100,'thumb');
+INSERT INTO {graphics_rules} VALUES (2,1,'a:3:{s:5:\"width\";i:640;s:6:\"height\";i:640;s:6:\"master\";i:2;}','gallery','gallery_graphics::resize',100,'resize');
+DROP TABLE IF EXISTS {groups};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {groups} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `name` char(64) DEFAULT NULL,
+  `special` tinyint(1) DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+) AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {groups} VALUES (1,'Everybody',1);
+INSERT INTO {groups} VALUES (2,'Registered Users',1);
+DROP TABLE IF EXISTS {groups_users};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {groups_users} (
+  `group_id` int(9) NOT NULL,
+  `user_id` int(9) NOT NULL,
+  PRIMARY KEY (`group_id`,`user_id`),
+  UNIQUE KEY `user_id` (`user_id`,`group_id`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {groups_users} VALUES (1,1);
+INSERT INTO {groups_users} VALUES (1,2);
+INSERT INTO {groups_users} VALUES (2,2);
+DROP TABLE IF EXISTS {incoming_translations};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {incoming_translations} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `key` char(32) NOT NULL,
+  `locale` char(10) NOT NULL,
+  `message` text NOT NULL,
+  `revision` int(9) DEFAULT NULL,
+  `translation` text,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `key` (`key`,`locale`),
+  KEY `locale_key` (`locale`,`key`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS {items};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {items} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `album_cover_item_id` int(9) DEFAULT NULL,
+  `captured` int(9) DEFAULT NULL,
+  `created` int(9) DEFAULT NULL,
+  `description` text,
+  `height` int(9) DEFAULT NULL,
+  `left_ptr` int(9) NOT NULL,
+  `level` int(9) NOT NULL,
+  `mime_type` varchar(64) DEFAULT NULL,
+  `name` varchar(255) DEFAULT NULL,
+  `owner_id` int(9) DEFAULT NULL,
+  `parent_id` int(9) NOT NULL,
+  `rand_key` decimal(11,10) DEFAULT NULL,
+  `relative_path_cache` varchar(255) DEFAULT NULL,
+  `relative_url_cache` varchar(255) DEFAULT NULL,
+  `resize_dirty` tinyint(1) DEFAULT '1',
+  `resize_height` int(9) DEFAULT NULL,
+  `resize_width` int(9) DEFAULT NULL,
+  `right_ptr` int(9) NOT NULL,
+  `slug` varchar(255) DEFAULT NULL,
+  `sort_column` varchar(64) DEFAULT NULL,
+  `sort_order` char(4) DEFAULT 'ASC',
+  `thumb_dirty` tinyint(1) DEFAULT '1',
+  `thumb_height` int(9) DEFAULT NULL,
+  `thumb_width` int(9) DEFAULT NULL,
+  `title` varchar(255) DEFAULT NULL,
+  `type` varchar(32) NOT NULL,
+  `updated` int(9) DEFAULT NULL,
+  `view_count` int(9) DEFAULT '0',
+  `weight` int(9) NOT NULL DEFAULT '0',
+  `width` int(9) DEFAULT NULL,
+  `view_1` binary(1) DEFAULT '0',
+  `view_2` binary(1) DEFAULT '0',
+  PRIMARY KEY (`id`),
+  KEY `parent_id` (`parent_id`),
+  KEY `type` (`type`),
+  KEY `random` (`rand_key`),
+  KEY `weight` (`weight`),
+  KEY `left_ptr` (`left_ptr`),
+  KEY `relative_path_cache` (`relative_path_cache`)
+) AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {items} VALUES (1,NULL,NULL,UNIX_TIMESTAMP(),'',NULL,1,1,NULL,NULL,2,0,NULL,'','',1,NULL,NULL,2,NULL,'weight','ASC',1,NULL,NULL,'Gallery','album',UNIX_TIMESTAMP(),0,1,NULL,'1','1');
+DROP TABLE IF EXISTS {items_tags};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {items_tags} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `item_id` int(9) NOT NULL,
+  `tag_id` int(9) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `tag_id` (`tag_id`,`id`),
+  KEY `item_id` (`item_id`,`id`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS {logs};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {logs} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `category` varchar(64) DEFAULT NULL,
+  `html` varchar(255) DEFAULT NULL,
+  `message` text,
+  `referer` varchar(255) DEFAULT NULL,
+  `severity` int(9) DEFAULT '0',
+  `timestamp` int(9) DEFAULT '0',
+  `url` varchar(255) DEFAULT NULL,
+  `user_id` int(9) DEFAULT '0',
+  PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS {messages};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {messages} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `key` varchar(255) DEFAULT NULL,
+  `severity` varchar(32) DEFAULT NULL,
+  `value` text,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `key` (`key`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS {modules};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {modules} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `active` tinyint(1) DEFAULT '0',
+  `name` varchar(64) DEFAULT NULL,
+  `version` int(9) DEFAULT NULL,
+  `weight` int(9) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`),
+  KEY `weight` (`weight`)
+) AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {modules} VALUES (1,1,'gallery',57,1);
+INSERT INTO {modules} VALUES (2,1,'user',4,2);
+INSERT INTO {modules} VALUES (3,1,'comment',7,3);
+INSERT INTO {modules} VALUES (4,1,'organize',4,4);
+INSERT INTO {modules} VALUES (5,1,'info',2,5);
+INSERT INTO {modules} VALUES (6,1,'rss',1,6);
+INSERT INTO {modules} VALUES (7,1,'search',1,7);
+INSERT INTO {modules} VALUES (8,1,'slideshow',2,8);
+INSERT INTO {modules} VALUES (9,1,'tag',3,9);
+DROP TABLE IF EXISTS {outgoing_translations};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {outgoing_translations} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `base_revision` int(9) DEFAULT NULL,
+  `key` char(32) NOT NULL,
+  `locale` char(10) NOT NULL,
+  `message` text NOT NULL,
+  `translation` text,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `key` (`key`,`locale`),
+  KEY `locale_key` (`locale`,`key`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS {permissions};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {permissions} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `display_name` varchar(64) DEFAULT NULL,
+  `name` varchar(64) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+) AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {permissions} VALUES (1,'View','view');
+INSERT INTO {permissions} VALUES (2,'View full size','view_full');
+INSERT INTO {permissions} VALUES (3,'Edit','edit');
+INSERT INTO {permissions} VALUES (4,'Add','add');
+DROP TABLE IF EXISTS {search_records};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {search_records} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `item_id` int(9) DEFAULT NULL,
+  `dirty` tinyint(1) DEFAULT '1',
+  `data` longtext,
+  PRIMARY KEY (`id`),
+  KEY `item_id` (`item_id`),
+  FULLTEXT KEY `data` (`data`)
+) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {search_records} VALUES (1,1,0,'  Gallery');
+DROP TABLE IF EXISTS {sessions};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {sessions} (
+  `session_id` varchar(127) NOT NULL,
+  `data` text NOT NULL,
+  `last_activity` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`session_id`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS {tags};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {tags} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `name` varchar(128) NOT NULL,
+  `count` int(10) unsigned NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS {tasks};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {tasks} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `callback` varchar(128) DEFAULT NULL,
+  `context` text NOT NULL,
+  `done` tinyint(1) DEFAULT '0',
+  `name` varchar(128) DEFAULT NULL,
+  `owner_id` int(9) DEFAULT NULL,
+  `percent_complete` int(9) DEFAULT '0',
+  `state` varchar(32) DEFAULT NULL,
+  `status` varchar(255) DEFAULT NULL,
+  `updated` int(9) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `owner_id` (`owner_id`)
+) DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS {themes};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {themes} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) DEFAULT NULL,
+  `version` int(9) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+) AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {themes} VALUES (1,'wind',1);
+INSERT INTO {themes} VALUES (2,'admin_wind',1);
+DROP TABLE IF EXISTS {users};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {users} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `name` varchar(32) NOT NULL,
+  `full_name` varchar(255) NOT NULL,
+  `password` varchar(64) NOT NULL,
+  `login_count` int(10) unsigned NOT NULL DEFAULT '0',
+  `last_login` int(10) unsigned NOT NULL DEFAULT '0',
+  `email` varchar(64) DEFAULT NULL,
+  `admin` tinyint(1) DEFAULT '0',
+  `guest` tinyint(1) DEFAULT '0',
+  `hash` char(32) DEFAULT NULL,
+  `url` varchar(255) DEFAULT NULL,
+  `locale` char(10) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`),
+  UNIQUE KEY `hash` (`hash`)
+) AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {users} VALUES (1,'guest','Guest User','',0,0,NULL,0,1,NULL,NULL,NULL);
+INSERT INTO {users} VALUES (2,'admin','Gallery Administrator','',0,0,'unknown@unknown.com',1,0,NULL,NULL,NULL);
+DROP TABLE IF EXISTS {vars};
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE {vars} (
+  `id` int(9) NOT NULL AUTO_INCREMENT,
+  `module_name` varchar(64) NOT NULL,
+  `name` varchar(64) NOT NULL,
+  `value` text,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `module_name` (`module_name`,`name`)
+) AUTO_INCREMENT=47 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO {vars} VALUES (NULL,'gallery','active_site_theme','wind');
+INSERT INTO {vars} VALUES (NULL,'gallery','active_admin_theme','admin_wind');
+INSERT INTO {vars} VALUES (NULL,'gallery','page_size','9');
+INSERT INTO {vars} VALUES (NULL,'gallery','thumb_size','200');
+INSERT INTO {vars} VALUES (NULL,'gallery','resize_size','640');
+INSERT INTO {vars} VALUES (NULL,'gallery','default_locale','en_US');
+INSERT INTO {vars} VALUES (NULL,'gallery','image_quality','75');
+INSERT INTO {vars} VALUES (NULL,'gallery','image_sharpen','15');
+INSERT INTO {vars} VALUES (NULL,'gallery','upgrade_checker_auto_enabled','1');
+INSERT INTO {vars} VALUES (NULL,'gallery','blocks_dashboard_sidebar','a:4:{i:2;a:2:{i:0;s:7:\"gallery\";i:1;s:11:\"block_adder\";}i:3;a:2:{i:0;s:7:\"gallery\";i:1;s:5:\"stats\";}i:4;a:2:{i:0;s:7:\"gallery\";i:1;s:13:\"platform_info\";}i:5;a:2:{i:0;s:7:\"gallery\";i:1;s:12:\"project_news\";}}');
+INSERT INTO {vars} VALUES (NULL,'gallery','blocks_dashboard_center','a:4:{i:6;a:2:{i:0;s:7:\"gallery\";i:1;s:7:\"welcome\";}i:7;a:2:{i:0;s:7:\"gallery\";i:1;s:15:\"upgrade_checker\";}i:8;a:2:{i:0;s:7:\"gallery\";i:1;s:12:\"photo_stream\";}i:9;a:2:{i:0;s:7:\"gallery\";i:1;s:11:\"log_entries\";}}');
+INSERT INTO {vars} VALUES (NULL,'gallery','choose_default_tookit','1');
+INSERT INTO {vars} VALUES (NULL,'gallery','date_format','Y-M-d');
+INSERT INTO {vars} VALUES (NULL,'gallery','date_time_format','Y-M-d H:i:s');
+INSERT INTO {vars} VALUES (NULL,'gallery','time_format','H:i:s');
+INSERT INTO {vars} VALUES (NULL,'gallery','show_credits','1');
+INSERT INTO {vars} VALUES (NULL,'gallery','credits','Powered by <a href=\"%url\">%gallery_version</a>');
+INSERT INTO {vars} VALUES (NULL,'gallery','simultaneous_upload_limit','5');
+INSERT INTO {vars} VALUES (NULL,'gallery','admin_area_timeout','5400');
+INSERT INTO {vars} VALUES (NULL,'gallery','maintenance_mode','0');
+INSERT INTO {vars} VALUES (NULL,'gallery','visible_title_length','15');
+INSERT INTO {vars} VALUES (NULL,'gallery','favicon_url','lib/images/favicon.ico');
+INSERT INTO {vars} VALUES (NULL,'gallery','apple_touch_icon_url','lib/images/apple-touch-icon.png');
+INSERT INTO {vars} VALUES (NULL,'gallery','email_from','unknown@unknown.com');
+INSERT INTO {vars} VALUES (NULL,'gallery','email_reply_to','unknown@unknown.com');
+INSERT INTO {vars} VALUES (NULL,'gallery','email_line_length','70');
+INSERT INTO {vars} VALUES (NULL,'gallery','email_header_separator','s:1:\"\n\";');
+INSERT INTO {vars} VALUES (NULL,'gallery','show_user_profiles_to','registered_users');
+INSERT INTO {vars} VALUES (NULL,'gallery','extra_binary_paths','/usr/local/bin:/opt/local/bin:/opt/bin');
+INSERT INTO {vars} VALUES (NULL,'gallery','timezone',NULL);
+INSERT INTO {vars} VALUES (NULL,'gallery','lock_timeout','1');
+INSERT INTO {vars} VALUES (NULL,'gallery','movie_extract_frame_time','3');
+INSERT INTO {vars} VALUES (NULL,'gallery','movie_allow_uploads','autodetect');
+INSERT INTO {vars} VALUES (NULL,'gallery','blocks_site_sidebar','a:4:{i:10;a:2:{i:0;s:7:\"gallery\";i:1;s:8:\"language\";}i:11;a:2:{i:0;s:4:\"info\";i:1;s:8:\"metadata\";}i:12;a:2:{i:0;s:3:\"rss\";i:1;s:9:\"rss_feeds\";}i:13;a:2:{i:0;s:3:\"tag\";i:1;s:3:\"tag\";}}');
+INSERT INTO {vars} VALUES (NULL,'gallery','identity_provider','user');
+INSERT INTO {vars} VALUES (NULL,'user','minimum_password_length','5');
+INSERT INTO {vars} VALUES (NULL,'comment','spam_caught','0');
+INSERT INTO {vars} VALUES (NULL,'comment','access_permissions','everybody');
+INSERT INTO {vars} VALUES (NULL,'comment','rss_visible','all');
+INSERT INTO {vars} VALUES (NULL,'info','show_title','1');
+INSERT INTO {vars} VALUES (NULL,'info','show_description','1');
+INSERT INTO {vars} VALUES (NULL,'info','show_owner','1');
+INSERT INTO {vars} VALUES (NULL,'info','show_name','1');
+INSERT INTO {vars} VALUES (NULL,'info','show_captured','1');
+INSERT INTO {vars} VALUES (NULL,'slideshow','max_scale','0');
+INSERT INTO {vars} VALUES (NULL,'tag','tag_cloud_size','30');
diff --git a/installer/installer.php b/installer/installer.php
new file mode 100644
index 0000000..434d8e5
--- /dev/null
+++ b/installer/installer.php
@@ -0,0 +1,270 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class installer {
+  static $mysqli;
+
+  static function already_installed() {
+    return file_exists(VARPATH . "database.php");
+  }
+
+  static function var_writable() {
+    if (is_writable(VARPATH)) {
+      return true;
+    }
+
+    if (@mkdir(VARPATH)) {
+      return true;
+    }
+
+    return false;
+  }
+
+  static function create_database_config($config) {
+    $db_config_file = VARPATH . "database.php";
+    ob_start();
+    extract($config);
+    include(DOCROOT . "installer/database_config.php");
+    $output = ob_get_clean();
+    return file_put_contents($db_config_file, $output) !== false;
+  }
+
+  static function unpack_var() {
+    if (!file_exists(VARPATH)) {
+      mkdir(VARPATH);
+      chmod(VARPATH, 0777);
+    }
+
+    include(DOCROOT . "installer/init_var.php");
+    return true;
+  }
+
+  static function unpack_sql($config) {
+    $prefix = $config["prefix"];
+    $buf = null;
+    foreach (file(DOCROOT . "installer/install.sql") as $line) {
+      $buf .= trim($line);
+      if (preg_match("/;$/", $buf)) {
+        if (!mysql_query(self::prepend_prefix($prefix, $buf))) {
+          return false;
+        }
+        $buf = "";
+      }
+    }
+    return true;
+  }
+
+  static function connect($config) {
+    // We know that we have either mysql or mysqli.  By default we use mysql functions, so if
+    // they're not defined then do the simplest thing which will work: remap them to their mysqli
+    // counterparts.
+    if (!function_exists("mysql_query")) {
+      function mysql_connect($host, $user, $pass) {
+        list ($host, $port) = explode(":", $host . ":");
+        installer::$mysqli = new mysqli($host, $user, $pass, $port);
+        // http://php.net/manual/en/mysqli.connect.php says to use mysqli_connect_error() instead of
+        // $mysqli->connect_error because of bugs before PHP 5.2.9
+        $error = mysqli_connect_error();
+        return empty($error);
+      }
+      function mysql_query($query) {
+        return installer::$mysqli->query($query);
+      }
+      function mysql_num_rows($result) {
+        return $result->num_rows;
+      }
+      function mysql_error() {
+        return installer::$mysqli->error;
+      }
+      function mysql_select_db($db) {
+        return installer::$mysqli->select_db($db);
+      }
+    }
+
+    $host = empty($config["port"]) ? $config['host'] : "{$config['host']}:{$config['port']}";
+    return @mysql_connect($host, $config["user"], $config["password"]);
+  }
+
+  static function select_db($config) {
+    if (mysql_select_db($config["dbname"])) {
+      return true;
+    }
+
+    return mysql_query("CREATE DATABASE `{$config['dbname']}`") &&
+      mysql_select_db($config["dbname"]);
+  }
+
+  static function verify_mysql_version($config) {
+    return version_compare(installer::mysql_version($config), "5.0.0", ">=");
+  }
+
+  static function mysql_version($config) {
+    $result = mysql_query("SHOW VARIABLES WHERE variable_name = \"version\"");
+    $row = mysql_fetch_object($result);
+    return $row->Value;
+  }
+
+  static function db_empty($config) {
+    $query = "SHOW TABLES LIKE '{$config['prefix']}items'";
+    $results = mysql_query($query);
+    if ($results === false) {
+      $msg = mysql_error();
+      return $msg;
+    }
+    return mysql_num_rows($results) === 0;
+  }
+
+  static function create_admin($config) {
+    $salt = "";
+    for ($i = 0; $i < 4; $i++) {
+      $char = mt_rand(48, 109);
+      $char += ($char > 90) ? 13 : ($char > 57) ? 7 : 0;
+      $salt .= chr($char);
+    }
+    if (!$password = $config["g3_password"]) {
+      $password = substr(md5(time() . mt_rand()), 0, 6);
+    }
+    // Escape backslash in preparation for our UPDATE statement.
+    $hashed_password = str_replace("\\", "\\\\", $salt . md5($salt . $password));
+    $sql = self::prepend_prefix($config["prefix"],
+       "UPDATE {users} SET `password` = '$hashed_password' WHERE `id` = 2");
+    if (mysql_query($sql)) {
+    } else {
+      throw new Exception(mysql_error());
+    }
+
+    return array("admin", $password);
+  }
+
+  static function create_admin_session($config) {
+    $session_id = md5(time() . mt_rand());
+    $user_agent = $_SERVER["HTTP_USER_AGENT"];
+    $user_agent_len = strlen($user_agent);
+    $now = time();
+    $data = "session_id|s:32:\"$session_id\"";
+    $data .= ";user_agent|s:{$user_agent_len}:\"$user_agent\"";
+    $data .= ";user|i:2";
+    $data .= ";after_install|i:1";
+    $data .= ";last_activity|i:$now";
+    $data = base64_encode($data);
+    $sql = "INSERT INTO {sessions}(`session_id`, `last_activity`, `data`) " .
+      "VALUES('$session_id', $now, '$data')";
+    $sql = self::prepend_prefix($config["prefix"], $sql);
+    if (mysql_query($sql)) {
+      setcookie("g3sid", $session_id, 0, "/", "", false, false);
+    } else {
+      throw new Exception(mysql_error());
+    }
+  }
+
+  static function create_private_key($config) {
+    $key = md5(uniqid(mt_rand(), true)) . md5(uniqid(mt_rand(), true));
+    $sql = self::prepend_prefix($config["prefix"],
+       "INSERT INTO {vars} VALUES(NULL, 'gallery', 'private_key', '$key')");
+    if (mysql_query($sql)) {
+    } else {
+      throw new Exception(mysql_error());
+    }
+  }
+
+  static function prepend_prefix($prefix, $sql) {
+    return preg_replace("#{([a-zA-Z0-9_]+)}#", "`{$prefix}$1`", $sql);
+  }
+
+  static function check_environment() {
+    if (!function_exists("mysql_query") && !function_exists("mysqli_set_charset")) {
+      $errors[] = "Gallery 3 requires a MySQL database, but PHP doesn't have either the <a href=\"http://php.net/mysql\">MySQL</a> or the  <a href=\"http://php.net/mysqli\">MySQLi</a> extension.";
+    }
+
+    if (!preg_match("/^.$/u", "ñ")) {
+      $errors[] = "PHP is missing <a href=\"http://php.net/pcre\">Perl-Compatible Regular Expression</a> with UTF-8 support.";
+    } else if (!preg_match("/^\pL$/u", "ñ")) {
+      $errors[] = "PHP is missing <a href=\"http://php.net/pcre\">Perl-Compatible Regular Expression</a> with Unicode support.";
+    }
+
+    if (!(function_exists("spl_autoload_register"))) {
+      $errors[] = "PHP is missing <a href=\"http://php.net/spl\">Standard PHP Library (SPL)</a> support";
+    }
+
+    if (!(class_exists("ReflectionClass"))) {
+      $errors[] = "PHP is missing <a href=\"http://php.net/reflection\">reflection</a> support";
+    }
+
+    if (!(function_exists("filter_list"))) {
+      $errors[] = "PHP is missing the <a href=\"http://php.net/filter\">filter extension</a>";
+    }
+
+    if (!(extension_loaded("iconv"))) {
+      $errors[] = "PHP is missing the <a href=\"http://php.net/iconv\">iconv extension</a>";
+    }
+
+    if (!(extension_loaded("xml"))) {
+      $errors[] = "PHP is missing the <a href=\"http://php.net/xml\">XML Parser extension</a>";
+    }
+
+    if (!(extension_loaded("simplexml"))) {
+      $errors[] = "PHP is missing the <a href=\"http://php.net/simplexml\">SimpleXML extension</a>";
+    }
+
+    if (!extension_loaded("mbstring")) {
+      $errors[] = "PHP is missing the <a href=\"http://php.net/mbstring\">mbstring extension</a>";
+    } else if (ini_get("mbstring.func_overload") & MB_OVERLOAD_STRING) {
+      $errors[] = "The <a href=\"http://php.net/mbstring\">mbstring extension</a> is overloading PHP's native string functions.  Please disable it.";
+    }
+
+    if (!function_exists("json_encode")) {
+      $errors[] = "PHP is missing the <a href=\"http://php.net/manual/en/book.json.php\">JavaScript Object Notation (JSON) extension</a>.  Please install it.";
+    }
+
+    if (!ini_get("short_open_tag")) {
+      $errors[] = "Gallery requires <a href=\"http://php.net/manual/en/ini.core.php\">short_open_tag</a> to be on.  Please enable it in your php.ini.";
+    }
+
+    if (!function_exists("ctype_alpha")) {
+      $errors[] = "Gallery requires the <a href=\"http://php.net/manual/en/book.ctype.php\">PHP Ctype</a> extension.  Please install it.";
+    }
+
+    if (self::ini_get_bool("safe_mode")) {
+      $errors[] = "Gallery cannot function when PHP is in <a href=\"http://php.net/manual/en/features.safe-mode.php\">Safe Mode</a>.  Please disable safe mode.";
+    }
+
+    return @$errors;
+  }
+
+  /**
+   * Convert any possible boolean ini value to true/false.
+   *   On = on = 1 = true
+   *   Off = off = 0 = false
+   */
+  static function ini_get_bool($varname) {
+    $value = ini_get($varname);
+
+    if (!strcasecmp("on", $value) || $value == 1 || $value === true) {
+      return true;
+    }
+
+    if (!strcasecmp("off", $value) || $value == 0 || $value === false) {
+      return false;
+    }
+
+    return false;
+  }
+
+}
diff --git a/installer/views/already_installed.html.php b/installer/views/already_installed.html.php
new file mode 100644
index 0000000..f6ac1bf
--- /dev/null
+++ b/installer/views/already_installed.html.php
@@ -0,0 +1,5 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<p class="success">
+  Your Gallery 3 install is complete.
+</p>
+
diff --git a/installer/views/db_not_empty.html.php b/installer/views/db_not_empty.html.php
new file mode 100644
index 0000000..bc45458
--- /dev/null
+++ b/installer/views/db_not_empty.html.php
@@ -0,0 +1,8 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h1> Uh oh! </h1>
+<p class="error">
+  The database you provided already has Gallery 3 tables in it.
+  Continuing with the install would overwrite your existing install.
+  Please either use a different database,  delete the old tables,
+  or choose a different table prefix.
+</p>
diff --git a/installer/views/environment_errors.html.php b/installer/views/environment_errors.html.php
new file mode 100644
index 0000000..318be61
--- /dev/null
+++ b/installer/views/environment_errors.html.php
@@ -0,0 +1,20 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h1> Whoa there! </h1>
+
+<p class="error">
+  There are some problems with your web hosting environment
+  that need to be fixed before you can successfully install
+  Gallery 3.
+</p>
+
+<ul>
+  <?php foreach ($errors as $error): ?>
+  <li>
+    <?php print $error ?>
+  </li>
+  <?php endforeach ?>
+</ul>
+
+<p>
+  <a href="index.php">Check again</a>
+</p>
diff --git a/installer/views/get_db_info.html.php b/installer/views/get_db_info.html.php
new file mode 100644
index 0000000..c9f57e1
--- /dev/null
+++ b/installer/views/get_db_info.html.php
@@ -0,0 +1,89 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h1> Let's get going! </h1>
+<p>
+  Installing Gallery is easy.  We just need a place to put your photos
+  and info about your MySQL database.
+</p>
+
+
+<fieldset class="<?= installer::var_writable() ? 'success' : 'error' ?>">
+  <legend>Photo Storage</legend>
+  <?php if (!installer::var_writable()): ?>
+  <p>
+    We're having trouble creating a place for your photos.  Can you
+    help?  We need you to create a directory called <em>var</em> in
+    your gallery3 directory.  This sample code works for most users.
+    Run it in the gallery3 directory:
+    <code>
+      mkdir var<br>
+      chmod 777 var
+    </code>
+    <a href="index.php">Check again</a>
+  </p>
+  <?php else: ?>
+  <p>
+    We've found a place to store your photos:
+    <code class="location"> <?= htmlspecialchars(VARPATH, ENT_QUOTES, 'UTF-8', true) ?> </code>
+  </p>
+  <?php endif ?>
+</fieldset>
+
+<?php if (installer::var_writable()): ?>
+<form method="post" action="index.php?step=save_db_info">
+  <fieldset>
+    <legend>Database</legend>
+    <p>
+      Gallery 3 needs a MySQL database.  The values provided work for
+      most setups, so if you're confused try clicking <i>continue</i>.
+    </p>
+    <br/>
+    <table id="db_info">
+      <tr>
+        <td>
+          Database name
+        </td>
+        <td>
+          <input name="dbname" value="gallery3"/>
+        </td>
+      </tr>
+      <tr>
+        <td>
+          User
+        </td>
+        <td>
+          <input name="dbuser" value="root"/>
+        </td>
+      </tr>
+      <tr>
+        <td>
+          Password
+        </td>
+        <td>
+          <input name="dbpass" value=""/>
+        </td>
+      </tr>
+      <tr>
+        <td>
+          Host
+        </td>
+        <td>
+          <input name="dbhost" value="localhost"/>
+        </td>
+      </tr>
+      <tr>
+        <td>
+          Table prefix <span class="subtext">(optional)</span>
+        </td>
+        <td>
+          <input name="prefix" value=""/>
+        </td>
+      </tr>
+      <tr>
+        <td colspan="2">
+          <input type="submit" value="Continue"/>
+        </td>
+      </tr>
+    </table>
+  </fieldset>
+</form>
+<?php endif ?>
diff --git a/installer/views/install.html.php b/installer/views/install.html.php
new file mode 100644
index 0000000..7a30561
--- /dev/null
+++ b/installer/views/install.html.php
@@ -0,0 +1,24 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<html>
+  <head>
+    <title>Gallery 3 Installer</title>
+    <link rel="stylesheet" type="text/css" href="install.css"/>
+  </head>
+  <body>
+    <div id="outer">
+      <img src="../modules/gallery/images/gallery.png" />
+      <div id="inner">
+        <?php print $content ?>
+      </div>
+      <div id="footer">
+        <p>
+          <i>Did something go wrong? Try
+          the <a href="http://codex.galleryproject.org/Gallery3:FAQ">FAQ</a>
+          or ask in
+          the <a href="http://galleryproject.org/forum">Gallery
+          forums</a>.</i>
+        </p>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/installer/views/invalid_db_info.html.php b/installer/views/invalid_db_info.html.php
new file mode 100644
index 0000000..242a28a
--- /dev/null
+++ b/installer/views/invalid_db_info.html.php
@@ -0,0 +1,6 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h1> Uh oh! </h1>
+<p class="error">
+  We were unable to connect to your MySQL server with the username and
+  password that you provided.  Please go back and try again!
+</p>
diff --git a/installer/views/invalid_db_version.html.php b/installer/views/invalid_db_version.html.php
new file mode 100644
index 0000000..5b021ba
--- /dev/null
+++ b/installer/views/invalid_db_version.html.php
@@ -0,0 +1,5 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h1> Uh oh! </h1>
+<p class="error">
+  Gallery requires at least MySQL version 5.0.0.  You're using version <?= installer::mysql_version($config) ?>
+</p>
diff --git a/installer/views/missing_db.html.php b/installer/views/missing_db.html.php
new file mode 100644
index 0000000..fa42fde
--- /dev/null
+++ b/installer/views/missing_db.html.php
@@ -0,0 +1,13 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h1> Can't find that database! </h1>
+<p class="error">
+  We were able to connect to your MySQL server, yay!  But the database
+  name you gave us doesn't exist and we don't have permissions to
+  create it for you.  Please create the database manually, then go
+  back and try again.
+</p>
+
+<p>
+  If you're having trouble creating the database, please contact your
+  web host or system administrator for assistance.
+</p>
diff --git a/installer/views/oops.html.php b/installer/views/oops.html.php
new file mode 100644
index 0000000..9c6b165
--- /dev/null
+++ b/installer/views/oops.html.php
@@ -0,0 +1,10 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h1> Oops! </h1>
+<p>
+  Something unexpected happened and we can't finish your install.
+  We'll try to provide some details about the specific problem below.
+</p>
+<p class="error">
+  <?php print $error ?>
+</p>
+
diff --git a/installer/views/success.html.php b/installer/views/success.html.php
new file mode 100644
index 0000000..e9ee981
--- /dev/null
+++ b/installer/views/success.html.php
@@ -0,0 +1,23 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h1> Success! </h1>
+<p class="success">
+  Your Gallery 3 install is complete!
+</p>
+
+<?php if (!empty($user)): ?>
+<h2> Before you start using it... </h2>
+<p>
+  We've created an account for you to use:
+  <br/>
+  username: <b><?php print $user ?></b>
+  <br/>
+  password: <b><?php print $password ?></b>
+  <br/>
+  <br/>
+  Save this information in a safe place, or change your admin password
+  right away!
+</p>
+<?php endif ?>
+
+<h2> <a href="..">Start using Gallery</a> </h2>
+
diff --git a/installer/web.php b/installer/web.php
new file mode 100644
index 0000000..5fa8541
--- /dev/null
+++ b/installer/web.php
@@ -0,0 +1,94 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+if (installer::already_installed()) {
+  $content = render("success.html.php");
+} else {
+  switch (@$_GET["step"]) {
+  default:
+  case "welcome":
+    $errors = installer::check_environment();
+    if ($errors) {
+      $content = render("environment_errors.html.php", array("errors" => $errors));
+    } else {
+      $content = render("get_db_info.html.php");
+    }
+    break;
+
+  case "save_db_info":
+    $config = array("host" => $_POST["dbhost"],
+                    "user" => $_POST["dbuser"],
+                    "password" => $_POST["dbpass"],
+                    "dbname" => $_POST["dbname"],
+                    "prefix" => $_POST["prefix"],
+                    "type" => function_exists("mysqli_set_charset") ? "mysqli" : "mysql");
+    list ($config["host"], $config["port"]) = explode(":", $config["host"] . ":");
+    foreach ($config as $k => $v) {
+      if ($k == "password") {
+        $config[$k] = str_replace(array("'", "\\"), array("\\'", "\\\\"), $v);
+      } else {
+        $config[$k] = strtr($v, "'`\\", "___");
+      }
+    }
+
+    if (!installer::connect($config)) {
+      $content = render("invalid_db_info.html.php");
+    } else if (!installer::verify_mysql_version($config)) {
+      $content = render("invalid_db_version.html.php");
+    } else if (!installer::select_db($config)) {
+      $content = render("missing_db.html.php");
+    } else if (is_string($count = installer::db_empty($config)) || !$count) {
+      if (is_string($count)) {
+        $content = oops($count);
+      } else {
+        $content = render("db_not_empty.html.php");
+      }
+    } else if (!installer::unpack_var()) {
+      $content = oops("Unable to create files inside the <code>var</code> directory");
+    } else if (!installer::unpack_sql($config)) {
+      $content = oops("Failed to create tables in your database:" . mysql_error());
+    } else if (!installer::create_database_config($config)) {
+      $content = oops("Couldn't create var/database.php");
+    } else {
+      try {
+        list ($user, $password) = installer::create_admin($config);
+        installer::create_admin_session($config);
+        $content = render("success.html.php", array("user" => $user, "password" => $password));
+
+        installer::create_private_key($config);
+      } catch (Exception $e) {
+        $content = oops($e->getMessage());
+      }
+    }
+    break;
+  }
+}
+
+include("views/install.html.php");
+
+function render($view, $args=array()) {
+  ob_start();
+  extract($args);
+  include(DOCROOT . "installer/views/" . $view);
+  return ob_get_clean();
+}
+
+function oops($error) {
+  return render("oops.html.php", array("error" => $error));
+}
diff --git a/lib/flowplayer.controls.swf.php b/lib/flowplayer.controls.swf.php
new file mode 100644
index 0000000..0ef7a46
--- /dev/null
+++ b/lib/flowplayer.controls.swf.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+// Redirect to strip off any query parameters
+if (!empty($_GET)) {
+  header("Location: flowplayer.controls.swf.php");
+  exit;
+}
+
+// This is a legitimate request.  Serve it, but disallow caching.
+header("Content-Type: application/x-shockwave-flash");
+header("Cache-Control: no-cache, no-store, must-revalidate");
+setcookie("flowplayer_0_token", "", time() - 3600);
+print base64_decode("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");
\ No newline at end of file
diff --git a/lib/flowplayer.js b/lib/flowplayer.js
new file mode 100644
index 0000000..83cd974
--- /dev/null
+++ b/lib/flowplayer.js
@@ -0,0 +1,228 @@
+!function(){function log(args){console.log("$f.fireEvent",[].slice.call(args));}
+function clone(obj){if(!obj||typeof obj!='object'){return obj;}
+var temp=new obj.constructor();for(var key in obj){if(obj.hasOwnProperty(key)){temp[key]=clone(obj[key]);}}
+return temp;}
+function each(obj,fn){if(!obj){return;}
+var name,i=0,length=obj.length;if(length===undefined){for(name in obj){if(fn.call(obj[name],name,obj[name])===false){break;}}}else{for(var value=obj[0];i<length&&fn.call(value,i,value)!==false;value=obj[++i]){}}
+return obj;}
+function el(id){return document.getElementById(id);}
+function extend(to,from,skipFuncs){if(typeof from!='object'){return to;}
+if(to&&from){each(from,function(name,value){if(!skipFuncs||typeof value!='function'){to[name]=value;}});}
+return to;}
+function select(query){var index=query.indexOf(".");if(index!=-1){var tag=query.slice(0,index)||"*";var klass=query.slice(index+1,query.length);var els=[];each(document.getElementsByTagName(tag),function(){if(this.className&&this.className.indexOf(klass)!=-1){els.push(this);}});return els;}}
+function stopEvent(e){e=e||window.event;if(e.preventDefault){e.stopPropagation();e.preventDefault();}else{e.returnValue=false;e.cancelBubble=true;}
+return false;}
+function bind(to,evt,fn){to[evt]=to[evt]||[];to[evt].push(fn);}
+function queryescape(url){return url.replace(/&amp;/g,'%26').replace(/&/g,'%26').replace(/=/g,'%3D');}
+function makeId(){return"_"+(""+Math.random()).slice(2,10);}
+var Clip=function(json,index,player){var self=this,cuepoints={},listeners={};self.index=index;if(typeof json=='string'){json={url:json};}
+extend(this,json,true);each(("Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop").split(","),function(){var evt="on"+this;if(evt.indexOf("*")!=-1){evt=evt.slice(0,evt.length-1);var before="onBefore"+evt.slice(2);self[before]=function(fn){bind(listeners,before,fn);return self;};}
+self[evt]=function(fn){bind(listeners,evt,fn);return self;};if(index==-1){if(self[before]){player[before]=self[before];}
+if(self[evt]){player[evt]=self[evt];}}});extend(this,{onCuepoint:function(points,fn){if(arguments.length==1){cuepoints.embedded=[null,points];return self;}
+if(typeof points=='number'){points=[points];}
+var fnId=makeId();cuepoints[fnId]=[points,fn];if(player.isLoaded()){player._api().fp_addCuepoints(points,index,fnId);}
+return self;},update:function(json){extend(self,json);if(player.isLoaded()){player._api().fp_updateClip(json,index);}
+var conf=player.getConfig();var clip=(index==-1)?conf.clip:conf.playlist[index];extend(clip,json,true);},_fireEvent:function(evt,arg1,arg2,target){if(evt=='onLoad'){each(cuepoints,function(key,val){if(val[0]){player._api().fp_addCuepoints(val[0],index,key);}});return false;}
+target=target||self;if(evt=='onCuepoint'){var fn=cuepoints[arg1];if(fn){return fn[1].call(player,target,arg2);}}
+if(arg1&&"onBeforeBegin,onMetaData,onStart,onUpdate,onResume".indexOf(evt)!=-1){extend(target,arg1);if(arg1.metaData){if(!target.duration){target.duration=arg1.metaData.duration;}else{target.fullDuration=arg1.metaData.duration;}}}
+var ret=true;each(listeners[evt],function(){ret=this.call(player,target,arg1,arg2);});return ret;}});if(json.onCuepoint){var arg=json.onCuepoint;self.onCuepoint.apply(self,typeof arg=='function'?[arg]:arg);delete json.onCuepoint;}
+each(json,function(key,val){if(typeof val=='function'){bind(listeners,key,val);delete json[key];}});if(index==-1){player.onCuepoint=this.onCuepoint;}};var Plugin=function(name,json,player,fn){var self=this,listeners={},hasMethods=false;if(fn){extend(listeners,fn);}
+each(json,function(key,val){if(typeof val=='function'){listeners[key]=val;delete json[key];}});extend(this,{animate:function(props,speed,fn){if(!props){return self;}
+if(typeof speed=='function'){fn=speed;speed=500;}
+if(typeof props=='string'){var key=props;props={};props[key]=speed;speed=500;}
+if(fn){var fnId=makeId();listeners[fnId]=fn;}
+if(speed===undefined){speed=500;}
+json=player._api().fp_animate(name,props,speed,fnId);return self;},css:function(props,val){if(val!==undefined){var css={};css[props]=val;props=css;}
+json=player._api().fp_css(name,props);extend(self,json);return self;},show:function(){this.display='block';player._api().fp_showPlugin(name);return self;},hide:function(){this.display='none';player._api().fp_hidePlugin(name);return self;},toggle:function(){this.display=player._api().fp_togglePlugin(name);return self;},fadeTo:function(o,speed,fn){if(typeof speed=='function'){fn=speed;speed=500;}
+if(fn){var fnId=makeId();listeners[fnId]=fn;}
+this.display=player._api().fp_fadeTo(name,o,speed,fnId);this.opacity=o;return self;},fadeIn:function(speed,fn){return self.fadeTo(1,speed,fn);},fadeOut:function(speed,fn){return self.fadeTo(0,speed,fn);},getName:function(){return name;},getPlayer:function(){return player;},_fireEvent:function(evt,arg,arg2){if(evt=='onUpdate'){var json=player._api().fp_getPlugin(name);if(!json){return;}
+extend(self,json);delete self.methods;if(!hasMethods){each(json.methods,function(){var method=""+this;self[method]=function(){var a=[].slice.call(arguments);var ret=player._api().fp_invoke(name,method,a);return ret==='undefined'||ret===undefined?self:ret;};});hasMethods=true;}}
+var fn=listeners[evt];if(fn){var ret=fn.apply(self,arg);if(evt.slice(0,1)=="_"){delete listeners[evt];}
+return ret;}
+return self;}});};function Player(wrapper,params,conf){var self=this,api=null,isUnloading=false,html,commonClip,playlist=[],plugins={},listeners={},playerId,apiId,playerIndex,activeIndex,swfHeight,wrapperHeight;extend(self,{id:function(){return playerId;},isLoaded:function(){return(api!==null&&api.fp_play!==undefined&&!isUnloading);},getParent:function(){return wrapper;},hide:function(all){if(all){wrapper.style.height="0px";}
+if(self.isLoaded()){api.style.height="0px";}
+return self;},show:function(){wrapper.style.height=wrapperHeight+"px";if(self.isLoaded()){api.style.height=swfHeight+"px";}
+return self;},isHidden:function(){return self.isLoaded()&&parseInt(api.style.height,10)===0;},load:function(fn){if(!self.isLoaded()&&self._fireEvent("onBeforeLoad")!==false){var onPlayersUnloaded=function(){if(html&&!flashembed.isSupported(params.version)){wrapper.innerHTML="";}
+if(fn){fn.cached=true;bind(listeners,"onLoad",fn);}
+flashembed(wrapper,params,{config:conf});};var unloadedPlayersNb=0;each(players,function(){this.unload(function(wasUnloaded){if(++unloadedPlayersNb==players.length){onPlayersUnloaded();}});});}
+return self;},unload:function(fn){if(html.replace(/\s/g,'')!==''){if(self._fireEvent("onBeforeUnload")===false){if(fn){fn(false);}
+return self;}
+isUnloading=true;try{if(api){if(api.fp_isFullscreen()){api.fp_toggleFullscreen();}
+api.fp_close();self._fireEvent("onUnload");}}catch(error){}
+var clean=function(){api=null;wrapper.innerHTML=html;isUnloading=false;if(fn){fn(true);}};if(/WebKit/i.test(navigator.userAgent)&&!/Chrome/i.test(navigator.userAgent)){setTimeout(clean,0);}else{clean();}}
+else if(fn){fn(false);}
+return self;},getClip:function(index){if(index===undefined){index=activeIndex;}
+return playlist[index];},getCommonClip:function(){return commonClip;},getPlaylist:function(){return playlist;},getPlugin:function(name){var plugin=plugins[name];if(!plugin&&self.isLoaded()){var json=self._api().fp_getPlugin(name);if(json){plugin=new Plugin(name,json,self);plugins[name]=plugin;}}
+return plugin;},getScreen:function(){return self.getPlugin("screen");},getControls:function(){return self.getPlugin("controls")._fireEvent("onUpdate");},getLogo:function(){try{return self.getPlugin("logo")._fireEvent("onUpdate");}catch(ignored){}},getPlay:function(){return self.getPlugin("play")._fireEvent("onUpdate");},getConfig:function(copy){return copy?clone(conf):conf;},getFlashParams:function(){return params;},loadPlugin:function(name,url,props,fn){if(typeof props=='function'){fn=props;props={};}
+var fnId=fn?makeId():"_";self._api().fp_loadPlugin(name,url,props,fnId);var arg={};arg[fnId]=fn;var p=new Plugin(name,null,self,arg);plugins[name]=p;return p;},getState:function(){return self.isLoaded()?api.fp_getState():-1;},play:function(clip,instream){var p=function(){if(clip!==undefined){self._api().fp_play(clip,instream);}else{self._api().fp_play();}};if(self.isLoaded()){p();}else if(isUnloading){setTimeout(function(){self.play(clip,instream);},50);}else{self.load(function(){p();});}
+return self;},getVersion:function(){var js="flowplayer.js 3.2.12";if(self.isLoaded()){var ver=api.fp_getVersion();ver.push(js);return ver;}
+return js;},_api:function(){if(!self.isLoaded()){throw"Flowplayer "+self.id()+" not loaded when calling an API method";}
+return api;},setClip:function(clip){each(clip,function(key,val){if(typeof val=='function'){bind(listeners,key,val);delete clip[key];}else if(key=='onCuepoint'){$f(wrapper).getCommonClip().onCuepoint(clip[key][0],clip[key][1]);}});self.setPlaylist([clip]);return self;},getIndex:function(){return playerIndex;},bufferAnimate:function(enable){api.fp_bufferAnimate(enable===undefined||enable);return self;},_swfHeight:function(){return api.clientHeight;}});each(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,ClipAdd,Fullscreen*,FullscreenExit,Error,MouseOver,MouseOut").split(","),function(){var name="on"+this;if(name.indexOf("*")!=-1){name=name.slice(0,name.length-1);var name2="onBefore"+name.slice(2);self[name2]=function(fn){bind(listeners,name2,fn);return self;};}
+self[name]=function(fn){bind(listeners,name,fn);return self;};});each(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,toggleFullscreen,reset,close,setPlaylist,addClip,playFeed,setKeyboardShortcutsEnabled,isKeyboardShortcutsEnabled").split(","),function(){var name=this;self[name]=function(a1,a2){if(!self.isLoaded()){return self;}
+var ret=null;if(a1!==undefined&&a2!==undefined){ret=api["fp_"+name](a1,a2);}else{ret=(a1===undefined)?api["fp_"+name]():api["fp_"+name](a1);}
+return ret==='undefined'||ret===undefined?self:ret;};});self._fireEvent=function(a){if(typeof a=='string'){a=[a];}
+var evt=a[0],arg0=a[1],arg1=a[2],arg2=a[3],i=0;if(conf.debug){log(a);}
+if(!self.isLoaded()&&evt=='onLoad'&&arg0=='player'){api=api||el(apiId);swfHeight=self._swfHeight();each(playlist,function(){this._fireEvent("onLoad");});each(plugins,function(name,p){p._fireEvent("onUpdate");});commonClip._fireEvent("onLoad");}
+if(evt=='onLoad'&&arg0!='player'){return;}
+if(evt=='onError'){if(typeof arg0=='string'||(typeof arg0=='number'&&typeof arg1=='number')){arg0=arg1;arg1=arg2;}}
+if(evt=='onContextMenu'){each(conf.contextMenu[arg0],function(key,fn){fn.call(self);});return;}
+if(evt=='onPluginEvent'||evt=='onBeforePluginEvent'){var name=arg0.name||arg0;var p=plugins[name];if(p){p._fireEvent("onUpdate",arg0);return p._fireEvent(arg1,a.slice(3));}
+return;}
+if(evt=='onPlaylistReplace'){playlist=[];var index=0;each(arg0,function(){playlist.push(new Clip(this,index++,self));});}
+if(evt=='onClipAdd'){if(arg0.isInStream){return;}
+arg0=new Clip(arg0,arg1,self);playlist.splice(arg1,0,arg0);for(i=arg1+1;i<playlist.length;i++){playlist[i].index++;}}
+var ret=true;if(typeof arg0=='number'&&arg0<playlist.length){activeIndex=arg0;var clip=playlist[arg0];if(clip){ret=clip._fireEvent(evt,arg1,arg2);}
+if(!clip||ret!==false){ret=commonClip._fireEvent(evt,arg1,arg2,clip);}}
+each(listeners[evt],function(){ret=this.call(self,arg0,arg1);if(this.cached){listeners[evt].splice(i,1);}
+if(ret===false){return false;}
+i++;});return ret;};function init(){if($f(wrapper)){$f(wrapper).getParent().innerHTML="";playerIndex=$f(wrapper).getIndex();players[playerIndex]=self;}else{players.push(self);playerIndex=players.length-1;}
+wrapperHeight=parseInt(wrapper.style.height,10)||wrapper.clientHeight;playerId=wrapper.id||"fp"+makeId();apiId=params.id||playerId+"_api";params.id=apiId;html=wrapper.innerHTML;if(typeof conf=='string'){conf={clip:{url:conf}};}
+conf.playerId=playerId;conf.clip=conf.clip||{};if(wrapper.getAttribute("href",2)&&!conf.clip.url){conf.clip.url=wrapper.getAttribute("href",2);}
+if(conf.clip.url){conf.clip.url=queryescape(conf.clip.url);}
+commonClip=new Clip(conf.clip,-1,self);conf.playlist=conf.playlist||[conf.clip];var index=0;each(conf.playlist,function(){var clip=this;if(typeof clip=='object'&&clip.length){clip={url:""+clip};}
+if(clip.url){clip.url=queryescape(clip.url);}
+each(conf.clip,function(key,val){if(val!==undefined&&clip[key]===undefined&&typeof val!='function'){clip[key]=val;}});conf.playlist[index]=clip;clip=new Clip(clip,index,self);playlist.push(clip);index++;});each(conf,function(key,val){if(typeof val=='function'){if(commonClip[key]){commonClip[key](val);}else{bind(listeners,key,val);}
+delete conf[key];}});each(conf.plugins,function(name,val){if(val){plugins[name]=new Plugin(name,val,self);}});if(!conf.plugins||conf.plugins.controls===undefined){plugins.controls=new Plugin("controls",null,self);}
+plugins.canvas=new Plugin("canvas",null,self);html=wrapper.innerHTML;function doClick(e){if(/iPad|iPhone|iPod/i.test(navigator.userAgent)&&!/.flv$/i.test(playlist[0].url)&&!checkForIpadSupport()){return true;}
+if(!self.isLoaded()&&self._fireEvent("onBeforeClick")!==false){self.load();}
+return stopEvent(e);}
+function checkForIpadSupport(){return self.hasiPadSupport&&self.hasiPadSupport();}
+function installPlayer(){if(html.replace(/\s/g,'')!==''){if(wrapper.addEventListener){wrapper.addEventListener("click",doClick,false);}else if(wrapper.attachEvent){wrapper.attachEvent("onclick",doClick);}}else{if(wrapper.addEventListener&&!checkForIpadSupport()){wrapper.addEventListener("click",stopEvent,false);}
+self.load();}}
+setTimeout(installPlayer,0);}
+if(typeof wrapper=='string'){var node=el(wrapper);if(!node){throw"Flowplayer cannot access element: "+wrapper;}
+wrapper=node;init();}else{init();}}
+var players=[];function Iterator(arr){this.length=arr.length;this.each=function(fn){each(arr,fn);};this.size=function(){return arr.length;};var self=this;for(name in Player.prototype){self[name]=function(){var args=arguments;self.each(function(){this[name].apply(this,args);});};}}
+window.flowplayer=window.$f=function(){var instance=null;var arg=arguments[0];if(!arguments.length){each(players,function(){if(this.isLoaded()){instance=this;return false;}});return instance||players[0];}
+if(arguments.length==1){if(typeof arg=='number'){return players[arg];}else{if(arg=='*'){return new Iterator(players);}
+each(players,function(){if(this.id()==arg.id||this.id()==arg||this.getParent()==arg){instance=this;return false;}});return instance;}}
+if(arguments.length>1){var params=arguments[1],conf=(arguments.length==3)?arguments[2]:{};if(typeof params=='string'){params={src:params};}
+params=extend({bgcolor:"#000000",version:[10,1],expressInstall:"http://releases.flowplayer.org/swf/expressinstall.swf",cachebusting:false},params);if(typeof arg=='string'){if(arg.indexOf(".")!=-1){var instances=[];each(select(arg),function(){instances.push(new Player(this,clone(params),clone(conf)));});return new Iterator(instances);}else{var node=el(arg);return new Player(node!==null?node:clone(arg),clone(params),clone(conf));}}else if(arg){return new Player(arg,clone(params),clone(conf));}}
+return null;};extend(window.$f,{fireEvent:function(){var a=[].slice.call(arguments);var p=$f(a[0]);return p?p._fireEvent(a.slice(1)):null;},addPlugin:function(name,fn){Player.prototype[name]=fn;return $f;},each:each,extend:extend});if(typeof jQuery=='function'){jQuery.fn.flowplayer=function(params,conf){if(!arguments.length||typeof arguments[0]=='number'){var arr=[];this.each(function(){var p=$f(this);if(p){arr.push(p);}});return arguments.length?arr[arguments[0]]:new Iterator(arr);}
+return this.each(function(){$f(this,clone(params),conf?clone(conf):{});});};}}();!function(){var IE=document.all,URL='http://get.adobe.com/flashplayer',JQUERY=typeof jQuery=='function',RE=/(\d+)[^\d]+(\d+)[^\d]*(\d*)/,GLOBAL_OPTS={width:'100%',height:'100%',id:"_"+(""+Math.random()).slice(9),allowfullscreen:true,allowscriptaccess:'always',quality:'high',version:[3,0],onFail:null,expressInstall:null,w3c:false,cachebusting:false};if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};});}
+function extend(to,from){if(from){for(var key in from){if(from.hasOwnProperty(key)){to[key]=from[key];}}}
+return to;}
+function map(arr,func){var newArr=[];for(var i in arr){if(arr.hasOwnProperty(i)){newArr[i]=func(arr[i]);}}
+return newArr;}
+window.flashembed=function(root,opts,conf){if(typeof root=='string'){root=document.getElementById(root.replace("#",""));}
+if(!root){return;}
+if(typeof opts=='string'){opts={src:opts};}
+return new Flash(root,extend(extend({},GLOBAL_OPTS),opts),conf);};var f=extend(window.flashembed,{conf:GLOBAL_OPTS,getVersion:function(){var fo,ver;try{ver=navigator.plugins["Shockwave Flash"].description.slice(16);}catch(e){try{fo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");ver=fo&&fo.GetVariable("$version");}catch(err){try{fo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");ver=fo&&fo.GetVariable("$version");}catch(err2){}}}
+ver=RE.exec(ver);return ver?[1*ver[1],1*ver[(ver[1]*1>9?2:3)]*1]:[0,0];},asString:function(obj){if(obj===null||obj===undefined){return null;}
+var type=typeof obj;if(type=='object'&&obj.push){type='array';}
+switch(type){case'string':return string2JsonString(obj);case'array':return'['+map(obj,function(el){return f.asString(el);}).join(',')+']';case'function':return'"function()"';case'object':var str=[];for(var prop in obj){if(obj.hasOwnProperty(prop)){str.push('"'+prop+'":'+f.asString(obj[prop]));}}
+return'{'+str.join(',')+'}';}
+return String(obj).replace(/\s/g," ").replace(/\'/g,"\"");},getHTML:function(opts,conf){opts=extend({},opts);var html='<object width="'+opts.width+'" height="'+opts.height+'" id="'+opts.id+'" name="'+opts.id+'"';if(opts.cachebusting){opts.src+=((opts.src.indexOf("?")!=-1?"&":"?")+Math.random());}
+if(opts.w3c||!IE){html+=' data="'+opts.src+'" type="application/x-shockwave-flash"';}else{html+=' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';}
+html+='>';if(opts.w3c||IE){html+='<param name="movie" value="'+opts.src+'" />';}
+opts.width=opts.height=opts.id=opts.w3c=opts.src=null;opts.onFail=opts.version=opts.expressInstall=null;for(var key in opts){if(opts[key]){html+='<param name="'+key+'" value="'+opts[key]+'" />';}}
+var vars="";if(conf){for(var k in conf){if(conf[k]){var val=conf[k];vars+=encodeURIComponent(k)+'='
++encodeURIComponent(/function|object/.test(typeof val)?f.asString(val):val)
++'&';}}
+vars=vars.slice(0,-1);html+='<param name="flashvars" value="'+vars+'" />';}
+html+="</object>";return html;},isSupported:function(ver){return VERSION[0]>ver[0]||VERSION[0]==ver[0]&&VERSION[1]>=ver[1];}});var VERSION=f.getVersion();function Flash(root,opts,conf){if(f.isSupported(opts.version)){root.innerHTML=f.getHTML(opts,conf);}else if(opts.expressInstall&&f.isSupported([6,65])){root.innerHTML=f.getHTML(extend(opts,{src:opts.expressInstall}),{MMredirectURL:encodeURIComponent(location.href),MMplayerType:'PlugIn',MMdoctitle:document.title});}else{if(!root.innerHTML.replace(/\s/g,'')){root.innerHTML="<h2>Flash version "+opts.version+" or greater is required</h2>"+"<h3>"+
+(VERSION[0]>0?"Your version is "+VERSION:"You have no flash plugin installed")+"</h3>"+
+(root.tagName=='A'?"<p>Click here to download latest version</p>":"<p>Download latest version from <a href='"+URL+"'>here</a></p>");if(root.tagName=='A'||root.tagName=="DIV"){root.onclick=function(){location.href=URL;};}}
+if(opts.onFail){var ret=opts.onFail.call(this);if(typeof ret=='string'){root.innerHTML=ret;}}}
+if(IE){window[opts.id]=document.getElementById(opts.id);}
+extend(this,{getRoot:function(){return root;},getOptions:function(){return opts;},getConf:function(){return conf;},getApi:function(){return root.firstChild;}});}
+var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function string2JsonString(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
+if(JQUERY){jQuery.tools=jQuery.tools||{version:'@VERSION'};jQuery.tools.flashembed={conf:GLOBAL_OPTS};jQuery.fn.flashembed=function(opts,conf){return this.each(function(){$(this).data("flashembed",flashembed(this,opts,conf));});};}}();$f.addPlugin("ipad",function(options){var STATE_UNLOADED=-1;var STATE_LOADED=0;var STATE_UNSTARTED=1;var STATE_BUFFERING=2;var STATE_PLAYING=3;var STATE_PAUSED=4;var STATE_ENDED=5;var self=this;var currentVolume=1;var onStartFired=false;var stopping=false;var playAfterSeek=false;var activeIndex=0;var activePlaylist=[];var lastSecondTimer;var endTime=null;var startTime=0;var clipDefaults={accelerated:false,autoBuffering:false,autoPlay:true,baseUrl:null,bufferLength:3,connectionProvider:null,cuepointMultiplier:1000,cuepoints:[],controls:{},duration:0,extension:'',fadeInSpeed:1000,fadeOutSpeed:1000,image:false,linkUrl:null,linkWindow:'_self',live:false,metaData:{},originalUrl:null,position:0,playlist:[],provider:'http',scaling:'scale',seekableOnBegin:false,start:0,url:null,urlResolvers:[]};var currentState=STATE_UNLOADED;var previousState=STATE_UNLOADED;var isiDevice=/iPad|iPhone|iPod/i.test(navigator.userAgent);var video=null;function extend(to,from,includeFuncs){if(from){for(key in from){if(key){if(from[key]&&typeof from[key]=="function"&&!includeFuncs)
+continue;if(from[key]&&typeof from[key]=="object"&&from[key].length===undefined){var cp={};extend(cp,from[key]);to[key]=cp;}else{to[key]=from[key];}}}}
+return to;}
+var opts={simulateiDevice:false,controlsSizeRatio:1.5,controls:true,debug:false,validExtensions:'mov|m4v|mp4|avi|mp3|m4a|aac|m3u8|m3u|pls',posterExtensions:'png|jpg'};extend(opts,options);var validExtensions=opts.validExtensions?new RegExp('^\.('+opts.validExtensions+')$','i'):null;var posterExtensions=new RegExp('^\.('+opts.posterExtensions+')$','i');function log(){if(opts.debug){if(isiDevice){var str=[].splice.call(arguments,0).join(', ');console.log.apply(console,[str]);}else{console.log.apply(console,arguments);}}}
+function stateDescription(state){switch(state){case-1:return"UNLOADED";case 0:return"LOADED";case 1:return"UNSTARTED";case 2:return"BUFFERING";case 3:return"PLAYING";case 4:return"PAUSED";case 5:return"ENDED";}
+return"UNKOWN";}
+function actionAllowed(eventName){var ret=$f.fireEvent(self.id(),"onBefore"+eventName,activeIndex);return ret!==false;}
+function stopEvent(e){e.stopPropagation();e.preventDefault();return false;}
+function setState(state,force){if(currentState==STATE_UNLOADED&&!force)
+return;previousState=currentState;currentState=state;stopPlayTimeTracker();if(state==STATE_PLAYING)
+startPlayTimeTracker();log(stateDescription(state));}
+function resetState(){video.fp_stop();onStartFired=false;stopping=false;playAfterSeek=false;setState(STATE_UNSTARTED);setState(STATE_UNSTARTED);}
+var _playTimeTracker=null;function startPlayTimeTracker(){if(_playTimeTracker)
+return;console.log("starting tracker");_playTimeTracker=setInterval(onTimeTracked,100);onTimeTracked();}
+function stopPlayTimeTracker(){clearInterval(_playTimeTracker);_playTimeTracker=null;}
+function onTimeTracked(){var currentTime=Math.floor(video.fp_getTime()*10)*100;var duration=Math.floor(video.duration*10)*100;var fireTime=(new Date()).time;function fireCuePointsIfNeeded(time,cues){time=time>=0?time:duration-Math.abs(time);for(var i=0;i<cues.length;i++){if(cues[i].lastTimeFired>fireTime){cues[i].lastTimeFired=-1;}else if(cues[i].lastTimeFired+500>fireTime){continue;}else{if(time==currentTime||(currentTime-500<time&&currentTime>time)){cues[i].lastTimeFired=fireTime;$f.fireEvent(self.id(),'onCuepoint',activeIndex,cues[i].fnId,cues[i].parameters);}}}}
+$f.each(self.getCommonClip().cuepoints,fireCuePointsIfNeeded);$f.each(activePlaylist[activeIndex].cuepoints,fireCuePointsIfNeeded);}
+function replay(){resetState();playAfterSeek=true;video.fp_seek(0);}
+function scaleVideo(clip){}
+function addAPI(){console.log(video);function fixClip(clip){var extendedClip={};extend(extendedClip,clipDefaults);extend(extendedClip,self.getCommonClip());extend(extendedClip,clip);if(extendedClip.ipadUrl)
+url=decodeURIComponent(extendedClip.ipadUrl);else if(extendedClip.url)
+url=extendedClip.url;if(url&&url.indexOf('://')==-1&&extendedClip.ipadBaseUrl)
+url=extendedClip.ipadBaseUrl+'/'+url;else if(url&&url.indexOf('://')==-1&&extendedClip.baseUrl)
+url=extendedClip.baseUrl+'/'+url;extendedClip.originalUrl=extendedClip.url;extendedClip.completeUrl=url;extendedClip.extension=extendedClip.completeUrl.substr(extendedClip.completeUrl.lastIndexOf('.'));var queryIndex=extendedClip.extension.indexOf('?');if(queryIndex>-1)
+extendedClip.extension=extendedClip.extension.substr(0,queryIndex);extendedClip.type='video';delete extendedClip.index;log("fixed clip",extendedClip);return extendedClip;}
+video.fp_play=function(clip,inStream,forcePlay,poster){var url=null;var autoBuffering=true;var autoPlay=true;log("Calling play() "+clip,clip);if(inStream){log("ERROR: inStream clips not yet supported");return;}
+if(clip!==undefined){if(typeof clip=="number"){if(activeIndex>=activePlaylist.length)
+return;activeIndex=clip;clip=activePlaylist[activeIndex];}else{if(typeof clip=="string"){clip={url:clip};}
+video.fp_setPlaylist(clip.length!==undefined?clip:[clip]);}
+if(activeIndex==0&&activePlaylist.length>1&&posterExtensions.test(activePlaylist[activeIndex].extension)){var poster=activePlaylist[activeIndex].url;console.log("Poster image available with url "+poster);++activeIndex;console.log("Not last clip in the playlist, moving to next one");video.fp_play(activeIndex,false,true,poster);return;}
+if(validExtensions&&!validExtensions.test(activePlaylist[activeIndex].extension)){return;}
+clip=activePlaylist[activeIndex];url=clip.completeUrl;if(clip.autoBuffering!==undefined&&clip.autoBuffering===false)
+autoBuffering=false;if(clip.autoPlay===undefined||clip.autoPlay===true||forcePlay===true){autoBuffering=true;autoPlay=true;}else{autoPlay=false;}}else{log("clip was not given, simply calling video.play, if not already buffering");if(currentState!=STATE_BUFFERING){video.play();}
+return;}
+log("about to play "+url,autoBuffering,autoPlay);resetState();if(url){log("Changing SRC attribute"+url);video.setAttribute('src',url);}
+if(autoBuffering){if(!actionAllowed('Begin'))
+return false;if(poster){autoPlay=clip.autoPlay;video.setAttribute('poster',poster);video.setAttribute('preload',"none");}
+$f.fireEvent(self.id(),'onBegin',activeIndex);log("calling video.load()");video.load();}
+if(autoPlay){log("calling video.play()");video.play();}}
+video.fp_pause=function(){log("pause called");if(!actionAllowed('Pause'))
+return false;video.pause();};video.fp_resume=function(){log("resume called");if(!actionAllowed('Resume'))
+return false;video.play();};video.fp_stop=function(){log("stop called");if(!actionAllowed('Stop'))
+return false;stopping=true;video.pause();try{video.currentTime=0;}catch(ignored){}};video.fp_seek=function(position){log("seek called "+position);if(!actionAllowed('Seek'))
+return false;var seconds=0;var position=position+"";if(position.charAt(position.length-1)=='%'){var percentage=parseInt(position.substr(0,position.length-1))/100;var duration=video.duration;seconds=duration*percentage;}else{seconds=position;}
+try{video.currentTime=seconds;}catch(e){log("Wrong seek time");}};video.fp_getTime=function(){return video.currentTime;};video.fp_mute=function(){log("mute called");if(!actionAllowed('Mute'))
+return false;currentVolume=video.volume;video.volume=0;};video.fp_unmute=function(){if(!actionAllowed('Unmute'))
+return false;video.volume=currentVolume;};video.fp_getVolume=function(){return video.volume*100;};video.fp_setVolume=function(volume){if(!actionAllowed('Volume'))
+return false;video.volume=volume/100;};video.fp_toggle=function(){log('toggle called');if(self.getState()==STATE_ENDED){replay();return;}
+if(video.paused)
+video.fp_play();else
+video.fp_pause();};video.fp_isPaused=function(){return video.paused;};video.fp_isPlaying=function(){return!video.paused;};video.fp_getPlugin=function(name){if(name=='canvas'||name=='controls'){var config=self.getConfig();return config['plugins']&&config['plugins'][name]?config['plugins'][name]:null;}
+log("ERROR: no support for "+name+" plugin on iDevices");return null;};video.fp_close=function(){setState(STATE_UNLOADED);video.parentNode.removeChild(video);video=null;};video.fp_getStatus=function(){var bufferStart=0;var bufferEnd=0;try{bufferStart=video.buffered.start();bufferEnd=video.buffered.end();}catch(ignored){}
+return{bufferStart:bufferStart,bufferEnd:bufferEnd,state:currentState,time:video.fp_getTime(),muted:video.muted,volume:video.fp_getVolume()};};video.fp_getState=function(){return currentState;};video.fp_startBuffering=function(){if(currentState==STATE_UNSTARTED)
+video.load();};video.fp_setPlaylist=function(playlist){log("Setting playlist");activeIndex=0;for(var i=0;i<playlist.length;i++)
+playlist[i]=fixClip(playlist[i]);activePlaylist=playlist;$f.fireEvent(self.id(),'onPlaylistReplace',playlist);};video.fp_addClip=function(clip,index){clip=fixClip(clip);activePlaylist.splice(index,0,clip);$f.fireEvent(self.id(),'onClipAdd',clip,index);};video.fp_updateClip=function(clip,index){extend(activePlaylist[index],clip);return activePlaylist[index];};video.fp_getVersion=function(){return'3.2.3';}
+video.fp_isFullscreen=function(){var isfullscreen=video.webkitDisplayingFullscreen;if(isfullscreen!==undefined)
+return isfullscreen;return false;}
+video.fp_toggleFullscreen=function(){if(video.fp_isFullscreen())
+video.webkitExitFullscreen();else
+video.webkitEnterFullscreen();}
+video.fp_addCuepoints=function(points,index,fnId){var clip=index==-1?self.getCommonClip():activePlaylist[index];clip.cuepoints=clip.cuepoints||{};points=points instanceof Array?points:[points];for(var i=0;i<points.length;i++){var time=typeof points[i]=="object"?(points[i]['time']||null):points[i];if(time==null)continue;time=Math.floor(time/100)*100;var parameters=time;if(typeof points[i]=="object"){parameters=extend({},points[i],false);if(parameters['time']===undefined)delete parameters['time'];if(parameters['parameters']!==undefined){extend(parameters,parameters['parameters'],false);delete parameters['parameters'];}}
+clip.cuepoints[time]=clip.cuepoints[time]||[];clip.cuepoints[time].push({fnId:fnId,lastTimeFired:-1,parameters:parameters});}}
+$f.each(("toggleFullscreen,stopBuffering,reset,playFeed,setKeyboardShortcutsEnabled,isKeyboardShortcutsEnabled,css,animate,showPlugin,hidePlugin,togglePlugin,fadeTo,invoke,loadPlugin").split(","),function(){var name=this;video["fp_"+name]=function(){log("ERROR: unsupported API on iDevices "+name);return false;};});}
+function addListeners(){var events=['abort','canplay','canplaythrough','durationchange','emptied','ended','error','loadeddata','loadedmetadata','loadstart','pause','play','playing','progress','ratechange','seeked','seeking','stalled','suspend','volumechange','waiting'];var eventsLogger=function(e){log("Got event "+e.type,e);}
+for(var i=0;i<events.length;i++)
+video.addEventListener(events[i],eventsLogger,false);var onBufferEmpty=function(e){log("got onBufferEmpty event "+e.type)
+setState(STATE_BUFFERING);$f.fireEvent(self.id(),'onBufferEmpty',activeIndex);};video.addEventListener('emptied',onBufferEmpty,false);video.addEventListener('waiting',onBufferEmpty,false);var onBufferFull=function(e){if(previousState==STATE_UNSTARTED||previousState==STATE_BUFFERING){}else{log("Restoring old state "+stateDescription(previousState));setState(previousState);}
+$f.fireEvent(self.id(),'onBufferFull',activeIndex);};video.addEventListener('canplay',onBufferFull,false);video.addEventListener('canplaythrough',onBufferFull,false);var onMetaData=function(e){var clipDuration;startTime=activePlaylist[activeIndex].start;if(activePlaylist[activeIndex].duration>0){clipDuration=activePlaylist[activeIndex].duration;endTime=clipDuration+startTime;}else{clipDuration=video.duration;endTime=null;}
+video.fp_updateClip({duration:clipDuration,metaData:{duration:video.duration}},activeIndex);activePlaylist[activeIndex].duration=video.duration;activePlaylist[activeIndex].metaData={duration:video.duration};$f.fireEvent(self.id(),'onMetaData',activeIndex,activePlaylist[activeIndex]);};video.addEventListener('loadedmetadata',onMetaData,false);video.addEventListener('durationchange',onMetaData,false);var onTimeUpdate=function(e){if(endTime&&video.currentTime>endTime){video.fp_seek(startTime);resetState();return stopEvent(e);}};video.addEventListener("timeupdate",onTimeUpdate,false);var onStart=function(e){if(currentState==STATE_PAUSED){if(!actionAllowed('Resume')){log("Resume disallowed, pausing");video.fp_pause();return stopEvent(e);}
+$f.fireEvent(self.id(),'onResume',activeIndex);}
+setState(STATE_PLAYING);if(!onStartFired){onStartFired=true;$f.fireEvent(self.id(),'onStart',activeIndex);}};video.addEventListener('playing',onStart,false);var onPlay=function(e){startLastSecondTimer();}
+video.addEventListener('play',onPlay,false);var onFinish=function(e){if(!actionAllowed('Finish')){if(activePlaylist.length==1){log("Active playlist only has one clip, onBeforeFinish returned false. Replaying");replay();}else if(activeIndex!=(activePlaylist.length-1)){log("Not the last clip in the playlist, but onBeforeFinish returned false. Returning to the beginning of current clip");video.fp_seek(0);}else{log("Last clip in playlist, but onBeforeFinish returned false, start again from the beginning");video.fp_play(0);}
+return stopEvent(e);}
+setState(STATE_ENDED);$f.fireEvent(self.id(),'onFinish',activeIndex);if(activePlaylist.length>1&&activeIndex<(activePlaylist.length-1)){log("Not last clip in the playlist, moving to next one");video.fp_play(++activeIndex,false,true);}};video.addEventListener('ended',onFinish,false);var onError=function(e){setState(STATE_LOADED,true);$f.fireEvent(self.id(),'onError',activeIndex,201);if(opts.onFail&&opts.onFail instanceof Function)
+opts.onFail.apply(self,[]);};video.addEventListener('error',onError,false);var onPause=function(e){log("got pause event from player"+self.id());if(stopping)
+return;if(currentState==STATE_BUFFERING&&previousState==STATE_UNSTARTED){log("forcing play");setTimeout(function(){video.play();},0);return;}
+if(!actionAllowed('Pause')){video.fp_resume();return stopEvent(e);}
+stopLastSecondTimer();setState(STATE_PAUSED);$f.fireEvent(self.id(),'onPause',activeIndex);}
+video.addEventListener('pause',onPause,false);var onSeek=function(e){$f.fireEvent(self.id(),'onBeforeSeek',activeIndex);};video.addEventListener('seeking',onSeek,false);var onSeekDone=function(e){if(stopping){stopping=false;$f.fireEvent(self.id(),'onStop',activeIndex);}
+else
+$f.fireEvent(self.id(),'onSeek',activeIndex);log("seek done, currentState",stateDescription(currentState));if(playAfterSeek){playAfterSeek=false;video.fp_play();}else if(currentState!=STATE_PLAYING)
+video.fp_pause();};video.addEventListener('seeked',onSeekDone,false);var onVolumeChange=function(e){$f.fireEvent(self.id(),'onVolume',video.fp_getVolume());};video.addEventListener('volumechange',onVolumeChange,false);}
+function startLastSecondTimer(){lastSecondTimer=setInterval(function(){if(video.fp_getTime()>=video.duration-1){$f.fireEvent(self.id(),'onLastSecond',activeIndex);stopLastSecondTimer();}},100);}
+function stopLastSecondTimer(){clearInterval(lastSecondTimer);}
+function onPlayerLoaded(){video.fp_play(0);}
+function installControlbar(){}
+if(isiDevice||opts.simulateiDevice){if(!window.flashembed.__replaced){var realFlashembed=window.flashembed;window.flashembed=function(root,opts,conf){if(typeof root=='string'){root=document.getElementById(root.replace("#",""));}
+if(!root){return;}
+var style=window.getComputedStyle(root,null);var width=parseInt(style.width);var height=parseInt(style.height);while(root.firstChild)
+root.removeChild(root.firstChild);var container=document.createElement('div');var api=document.createElement('video');container.appendChild(api);root.appendChild(container);container.style.height=height+'px';container.style.width=width+'px';container.style.display='block';container.style.position='relative';container.style.background='-webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.7)))';container.style.cursor='default';container.style.webkitUserDrag='none';api.style.height='100%';api.style.width='100%';api.style.display='block';api.id=opts.id;api.name=opts.id;api.style.cursor='pointer';api.style.webkitUserDrag='none';api.type="video/mp4";api.playerConfig=conf.config;$f.fireEvent(conf.config.playerId,'onLoad','player');};flashembed.getVersion=realFlashembed.getVersion;flashembed.asString=realFlashembed.asString;flashembed.isSupported=function(){return true;}
+flashembed.__replaced=true;}
+var __fireEvent=self._fireEvent;self._fireEvent=function(a){if(a[0]=='onLoad'&&a[1]=='player'){video=self.getParent().querySelector('video');if(opts.controls)
+video.controls="controls";addAPI();addListeners();setState(STATE_LOADED,true);video.fp_setPlaylist(video.playerConfig.playlist);onPlayerLoaded();__fireEvent.apply(self,[a]);}
+var shouldFireEvent=currentState!=STATE_UNLOADED;if(currentState==STATE_UNLOADED&&typeof a=='string')
+shouldFireEvent=true;if(shouldFireEvent)
+return __fireEvent.apply(self,[a]);}
+self._swfHeight=function(){return parseInt(video.style.height);}
+self.hasiPadSupport=function(){return true;}}
+return self;});
\ No newline at end of file
diff --git a/lib/flowplayer.pseudostreaming-byterange.swf.php b/lib/flowplayer.pseudostreaming-byterange.swf.php
new file mode 100644
index 0000000..8fc591a
--- /dev/null
+++ b/lib/flowplayer.pseudostreaming-byterange.swf.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+// Redirect to strip off any query parameters
+if (!empty($_GET)) {
+  header("Location: flowplayer.pseudostreaming-byterange.swf.php");
+  exit;
+}
+
+// This is a legitimate request.  Serve it, but disallow caching.
+header("Content-Type: application/x-shockwave-flash");
+header("Cache-Control: no-cache, no-store, must-revalidate");
+setcookie("flowplayer_1_token", "", time() - 3600);
+print base64_decode("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");
\ No newline at end of file
diff --git a/lib/flowplayer.pseudostreaming.swf.php b/lib/flowplayer.pseudostreaming.swf.php
new file mode 100644
index 0000000..3aa0e50
--- /dev/null
+++ b/lib/flowplayer.pseudostreaming.swf.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+// Redirect to strip off any query parameters
+if (!empty($_GET)) {
+  header("Location: flowplayer.pseudostreaming.swf.php");
+  exit;
+}
+
+// This is a legitimate request.  Serve it, but disallow caching.
+header("Content-Type: application/x-shockwave-flash");
+header("Cache-Control: no-cache, no-store, must-revalidate");
+setcookie("flowplayer_2_token", "", time() - 3600);
+print base64_decode("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");
\ No newline at end of file
diff --git a/lib/flowplayer.swf.php b/lib/flowplayer.swf.php
new file mode 100644
index 0000000..4564e56
--- /dev/null
+++ b/lib/flowplayer.swf.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+// Redirect the initial request to strip off any query parameters or URL fragments
+// We know it's an initial request if the token is missing
+if (empty($_GET["token"])) {
+  // We have not yet redirected
+  $rand = md5(rand());
+  setcookie("flowplayer_3_token", $rand);
+  header("Location: flowplayer.swf.php?token=$rand#.");
+  exit;
+}
+
+// If the token exists but there's no cookie, then this is a bogus token
+// or the user does not support cookies.  Ignore this request.
+if (empty($_COOKIE["flowplayer_3_token"])) {
+  exit;
+}
+
+// If the token exists but it doesn't match our cookie, then this is a bogus
+// request.  Ignore this request.
+if ($_GET["token"] != $_COOKIE["flowplayer_3_token"]) {
+  exit;
+}
+
+// This is a legitimate request.  Serve it, but disallow caching.
+header("Content-Type: application/x-shockwave-flash");
+header("Cache-Control: no-cache, no-store, must-revalidate");
+setcookie("flowplayer_3_token", "", time() - 3600);
+print base64_decode("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");
\ No newline at end of file
diff --git a/lib/gallery.ajax.js b/lib/gallery.ajax.js
new file mode 100644
index 0000000..0cdd8f2
--- /dev/null
+++ b/lib/gallery.ajax.js
@@ -0,0 +1,15 @@
+(function($) {
+  $.widget("ui.gallery_ajax",  {
+    _init: function() {
+      this.element.click(function(event) {
+        eval("var ajax_handler = " + $(event.currentTarget).attr("ajax_handler"));
+        $.get($(event.currentTarget).attr("href"), function(data) {
+          eval("var data = " + data);
+          ajax_handler(data);
+	});
+        event.preventDefault();
+        return false;
+      });
+    }
+  });
+})(jQuery);
diff --git a/lib/gallery.common.js b/lib/gallery.common.js
new file mode 100644
index 0000000..061ffed
--- /dev/null
+++ b/lib/gallery.common.js
@@ -0,0 +1,253 @@
+(function ($) {
+
+  // Fade in action status message background color
+  $.fn.gallery_show_message = function() {
+    return this.each(function(i){
+      $(this).hide().fadeIn(3000)
+    });
+  };
+
+  // Make the height of all items the same as the tallest item  within the set
+  $.fn.equal_heights = function() {
+    var tallest_height = 0;
+    $(this).each(function(){
+      if ($(this).height() > tallest_height) {
+        tallest_height = $(this).height();
+      }
+    });
+    return $(this).height(tallest_height);
+  };
+
+  // Vertically align a block element's content
+  $.fn.gallery_valign = function(container) {
+    return this.each(function(i){
+      if (container == null) {
+        container = 'div';
+      }
+      var el = $(this).find(".g-valign");
+      if (!el.length) {
+	$(this).html("<" + container + " class=\"g-valign\">" + $(this).html() +
+		     "</" + container + ">");
+	el = $(this).children(container + ".g-valign");
+      }
+      var elh = $(el).height();
+      var ph = $(this).height();
+      var nh = (ph - elh) / 2;
+      if (nh < 1) { var nh = 0; }
+      $(el).css('margin-top', nh);
+    });
+  };
+
+  // Get the viewport size
+  $.gallery_get_viewport_size = function() {
+    return {
+      width : function() {
+        return $(window).width();
+      },
+      height : function() {
+        return $(window).height();
+      }
+    };
+  };
+
+  /**
+   * Toggle the processing indicator, both large and small
+   * @param elementID Target ID, including #, to apply .g-loading-size
+   */
+  $.fn.gallery_show_loading = function() {
+    return this.each(function(i){
+      var size;
+      switch ($(this).attr("id")) {
+      case "#g-dialog":
+        case "#g-panel":
+          size = "large";
+        break;
+      default:
+        size = "small";
+        break;
+      }
+      $(this).toggleClass("g-loading-" + size);
+    });
+  };
+
+  /**
+   * Reduce the width of an image if it's wider than its parent container
+   * @param elementID The image container's ID
+   */
+  $.fn.gallery_fit_photo = function() {
+    return this.each(function(i) {
+      var container_width = $(this).width();
+      var photo = $(this).gallery_get_photo();
+      var photo_width = photo.width();
+      if (container_width < photo_width) {
+        var proportion = container_width / photo_width;
+        photo.width(container_width);
+        photo.height(proportion * photo.height());
+      }
+    });
+  };
+
+  /**
+   * Get a thumbnail or resize photo within a container
+   * @param elementID The image container's ID
+   * @return object
+   */
+  $.fn.gallery_get_photo = function() {
+    var photo = $(this).find("img,object").filter(function() {
+      return this.id.match(/g-(photo|movie)-id-\d+/);
+    });
+    return photo;
+  };
+
+  /**
+   * Get the sum of an element's height, margin-top, and margin-bottom
+   * @param elementID the element's ID
+   * @return int
+   */
+  $.fn.gallery_height = function() {
+    var ht = $(this).height();
+    var mt = parseInt($(this).css("margin-top"));
+    var mb = parseInt($(this).css("margin-bottom"));
+    return ht + parseInt(mt) + parseInt(mb);
+  };
+
+  // Add hover state to buttons
+  $.fn.gallery_hover_init = function() {
+    $(".ui-state-default").hover(
+      function(){
+        $(this).addClass("ui-state-hover");
+      },
+      function(){
+        $(this).removeClass("ui-state-hover");
+      }
+    );
+  };
+
+  // Ajax handler for replacing an image, used in Ajax thumbnail rotation
+  $.gallery_replace_image = function(data, img_selector) {
+    $(img_selector).attr({src: data.src, width: data.width, height: data.height});
+    $(img_selector).trigger("gallery.change");
+  };
+
+  // Initialize context menus
+  $.fn.gallery_context_menu = function() {
+    if ($(".g-context-menu li").length) {
+      var hover_target = $(this).find(".g-context-menu");
+      if (hover_target.attr("context_menu_initialized")) {
+	return;
+      }
+      var list = $(hover_target).find("ul");
+      hover_target.find("*").removeAttr('title');
+      list.hide();
+      hover_target.hover(
+        function() {
+          list.stop(false, true).slideDown("fast");
+          $(this).find(".g-dialog-link").gallery_dialog();
+          $(this).find(".g-ajax-link").gallery_ajax();
+        },
+        function() {
+          list.stop(true, true).slideUp("slow");
+        }
+      );
+      hover_target.attr("context_menu_initialized", 1);
+    }
+  };
+
+  // Size a container to fit within the browser window
+  $.gallery_auto_fit_window = function(imageWidth, imageHeight) {
+    var size = $.gallery_get_viewport_size();
+    var width = size.width() - 6,
+        height = size.height() - 6;
+
+    var ratio = width / imageWidth;
+        imageWidth *= ratio;
+        imageHeight *= ratio;
+
+    /* after scaling the width, check that the height fits */
+    if (imageHeight > height) {
+      ratio = height / imageHeight;
+      imageWidth *= ratio;
+      imageHeight *= ratio;
+    }
+
+    // handle the case where the calculation is almost zero (2.14e-14)
+    return {
+      top: Math.round((height - imageHeight) / 2),
+      left: Math.round((width - imageWidth) / 2),
+      width: Math.round(imageWidth),
+      height: Math.round(imageHeight)
+    };
+  };
+
+  // Initialize a short form. Short forms may contain only one text input.
+  $.fn.gallery_short_form = function() {
+    return this.each(function(i){
+      var label = $(this).find("label:first");
+      var input = $(this).find("input[type=text]:first");
+      var button = $(this).find("input[type=submit]");
+
+      $(".g-short-form").addClass("ui-helper-clearfix");
+
+      // Place button's on the left for RTL languages
+      if ($(".rtl").length) {
+        $(".g-short-form input[type=text]").addClass("ui-corner-right");
+        $(".g-short-form input[type=submit]").addClass("ui-state-default ui-corner-left");
+      } else {
+        $(".g-short-form input[type=text]").addClass("ui-corner-left");
+        $(".g-short-form input[type=submit]").addClass("ui-state-default ui-corner-right");
+      }
+
+      // Set the input value equal to label text
+      if (input.val() == "") {
+        input.val(label.html());
+        button.enable(false);
+      }
+
+      // Attach event listeners to the input
+      input.bind("focus", function(e) {
+        // Empty input value if it equals it's label
+        if ($(this).val() == label.html()) {
+          $(this).val("");
+        }
+        button.enable(true);
+      });
+
+      input.bind("blur", function(e){
+        // Reset the input value if it's empty
+        if ($(this).val() == "") {
+          $(this).val(label.html());
+          button.enable(false);
+        }
+      });
+    });
+  };
+
+  // Augment jQuery autocomplete to expect the first response line to
+  // be a <meta> tag that protects against UTF-7 attacks.
+  $.fn.gallery_autocomplete = function(url, options) {
+    // Drop the first response - it should be a meta tag
+    options.parse = function(data) {
+      var parsed = [];
+      var rows = data.split("\n");
+      if (rows[0].indexOf("<meta") == -1) {
+        throw 'Missing <meta> tag in first line of autocomplete response';
+      }
+      rows.shift();  // drop <META> tag
+      for (var i=0; i < rows.length; i++) {
+        var row = $.trim(rows[i]);
+        if (row) {
+          row = row.split("|");
+          parsed[parsed.length] = {
+            data: row,
+            value: row[0],
+            result: row[0]
+          };
+        }
+      }
+      return parsed;
+    };
+
+    $(this).autocomplete(url, options);
+  };
+
+})(jQuery);
diff --git a/lib/gallery.dialog.js b/lib/gallery.dialog.js
new file mode 100644
index 0000000..3115532
--- /dev/null
+++ b/lib/gallery.dialog.js
@@ -0,0 +1,221 @@
+
+(function($) {
+   $.widget("ui.gallery_dialog",  {
+     _init: function() {
+       var self = this;
+       if (!self.options.immediate) {
+         this.element.click(function(event) {
+           event.preventDefault();
+           self._show($(event.currentTarget).attr("href"));
+           return false;
+         });
+       } else {
+         self._show(this.element.attr("href"));
+       }
+     },
+
+     _show: function(sHref) {
+       var self = this;
+       var eDialog = '<div id="g-dialog"></div>';
+
+       if ($("#g-dialog").length) {
+         $("#g-dialog").dialog("close");
+       }
+       $("body").append(eDialog);
+
+       if (!self.options.close) {
+         self.options.close = self.close_dialog;
+       }
+       $("#g-dialog").dialog(self.options);
+
+       $("#g-dialog").gallery_show_loading();
+
+       $.ajax({
+         url: sHref,
+         type: "GET",
+         beforeSend: function(xhr) {
+           // Until we convert to jquery 1.4, we need to save the XMLHttpRequest object so that we
+           // can detect the mime type of the reply
+           this.xhrData = xhr;
+         },
+         success: function(data, textStatus, xhr) {
+           // Pre jquery 1.4, get the saved XMLHttpRequest object
+           if (xhr == undefined) {
+             xhr = this.xhrData;
+           }
+           var mimeType = /^(\w+\/\w+)\;?/.exec(xhr.getResponseHeader("Content-Type"));
+
+           var content = "";
+           if (mimeType[1] == "application/json") {
+             data = JSON.parse(data);
+	     content = data.html;
+           } else {
+             content = data;
+           }
+
+           $("#g-dialog").html(content).gallery_show_loading();
+
+           if ($("#g-dialog form").length) {
+             self.form_loaded(null, $("#g-dialog form"));
+           }
+           self._layout();
+
+           $("#g-dialog").dialog("open");
+           self._set_title();
+
+           if ($("#g-dialog form").length) {
+             self._ajaxify_dialog();
+           }
+         }
+       });
+       $("#g-dialog").dialog("option", "self", self);
+     },
+
+     error: function(xhr, textStatus, errorThrown) {
+	 $("#g-dialog").html(xhr.responseText);
+	 self._set_title();
+	 self._layout();
+     },
+
+     _layout: function() {
+       var dialogWidth;
+       var dialogHeight = $("#g-dialog").height();
+       var cssWidth = new String($("#g-dialog form").css("width"));
+       var childWidth = cssWidth.replace(/[^0-9]/g,"");
+       var size = $.gallery_get_viewport_size();
+       if ($("#g-dialog iframe").length) {
+         dialogWidth = size.width() - 100;
+         // Set the iframe width and height
+         $("#g-dialog iframe").width("100%").height(size.height() - 100);
+       } else if ($("#g-dialog .g-dialog-panel").length) {
+         dialogWidth = size.width() - 100;
+         $("#g-dialog").dialog("option", "height", size.height() - 100);
+       } else if (childWidth == "" || childWidth > 300) {
+         dialogWidth = 500;
+       }
+       $("#g-dialog").dialog('option', 'width', dialogWidth);
+     },
+
+     form_loaded: function(event, ui) {
+       // Should be defined (and localized) in the theme
+       MSG_CANCEL = MSG_CANCEL || 'Cancel';
+       var eCancel = '<a href="#" class="g-cancel g-left">' + MSG_CANCEL + '</a>';
+       if ($("#g-dialog .submit").length) {
+         $("#g-dialog .submit").addClass("ui-state-default ui-corner-all");
+         $.fn.gallery_hover_init();
+         $("#g-dialog .submit").parent().append(eCancel);
+         $("#g-dialog .g-cancel").click(function(event) {
+           $("#g-dialog").dialog("close");
+           event.preventDefault();
+         });
+        }
+       $("#g-dialog .ui-state-default").hover(
+         function() {
+           $(this).addClass("ui-state-hover");
+         },
+         function() {
+           $(this).removeClass("ui-state-hover");
+         }
+       );
+     },
+
+     close_dialog: function(event, ui) {
+       var self = $("#g-dialog").dialog("option", "self");
+       if ($("#g-dialog form").length) {
+         self._trigger("form_closing", null, $("#g-dialog form"));
+       }
+       self._trigger("dialog_closing", null, $("#g-dialog"));
+       $("#g-dialog").dialog("destroy").remove();
+     },
+
+     _ajaxify_dialog: function() {
+       var self = this;
+       $("#g-dialog form").ajaxForm({
+         beforeSubmit: function(formData, form, options) {
+           form.find(":submit")
+             .addClass("ui-state-disabled")
+             .attr("disabled", "disabled");
+           return true;
+         },
+         beforeSend: function(xhr) {
+           // Until we convert to jquery 1.4, we need to save the XMLHttpRequest object so that we
+           // can detect the mime type of the reply
+           this.xhrData = xhr;
+         },
+         success: function(data) {
+           // Pre jquery 1.4, get the saved XMLHttpRequest object
+           xhr = this.xhrData;
+           if (xhr) {
+             var mimeType = /^(\w+\/\w+)\;?/.exec(xhr.getResponseHeader("Content-Type"));
+
+             var content = "";
+             if (mimeType[1] == "application/json") {
+               data = JSON.parse(data);
+             } else {
+               data = {"html": escape(data)};
+             }
+           } else {
+             // Uploading files (eg: watermark) uses a fake xhr in jquery.form.js so
+             // all we have is in the data field, which should be some very simple JSON.
+             // Weirdly enough in Chrome the result gets wrapped in a <pre> element and
+             // looks like this:
+             //   <pre style="word-wrap: break-word; white-space: pre-wrap;">{"result":"success",
+             //   "location":"\/~bharat\/gallery3\/index.php\/admin\/watermarks"}</pre>
+             // bizarre.  Strip that off before parsing.
+             data = JSON.parse(data.match("({.*})")[0]);
+           }
+
+           if (data.html) {
+             $("#g-dialog").html(data.html);
+             $("#g-dialog").dialog("option", "position", "center");
+             $("#g-dialog form :submit").removeClass("ui-state-disabled")
+               .attr("disabled", null);
+             self._set_title();
+             self._ajaxify_dialog();
+             self.form_loaded(null, $("#g-dialog form"));
+             if (typeof data.reset == 'function') {
+               eval(data.reset + '()');
+             }
+           }
+           if (data.result == "success") {
+             if (data.location) {
+               window.location = data.location;
+             } else {
+               window.location.reload();
+             }
+           }
+         },
+	 error: function(xhr, textStatus, errorThrown) {
+	     $("#g-dialog").html(xhr.responseText);
+	     self._set_title();
+	     self._layout();
+	 }
+       });
+     },
+
+     _set_title: function() {
+       // Remove titlebar for progress dialogs or set title
+       if ($("#g-dialog #g-progress").length) {
+         $(".ui-dialog-titlebar").remove();
+       } else if ($("#g-dialog h1").length) {
+         $("#g-dialog").dialog('option', 'title', $("#g-dialog h1:eq(0)").html());
+         $("#g-dialog h1:eq(0)").hide();
+       } else if ($("#g-dialog fieldset legend").length) {
+         $("#g-dialog").dialog('option', 'title', $("#g-dialog fieldset legend:eq(0)").html());
+       }
+     },
+
+     form_closing: function(event, ui) {},
+     dialog_closing: function(event, ui) {}
+   });
+
+   $.extend($.ui.gallery_dialog,  {
+     defaults: {
+       autoOpen: false,
+       autoResize: true,
+       modal: true,
+       resizable: false,
+       position: "center"
+     }
+   });
+})(jQuery);
diff --git a/lib/gallery.in_place_edit.js b/lib/gallery.in_place_edit.js
new file mode 100644
index 0000000..5a815da
--- /dev/null
+++ b/lib/gallery.in_place_edit.js
@@ -0,0 +1,75 @@
+(function($) {
+   $.widget("ui.gallery_in_place_edit",  {
+     _init: function() {
+       var self = this;
+       this.element.click(function(event) {
+         event.preventDefault();
+         self._show(event.currentTarget);
+         return false;
+       });
+     },
+
+     _show: function(target) {
+       if ($(target).data("gallery_in_place_edit") == true) {
+         return;
+       }
+       $(target).data("gallery_in_place_edit", true);
+       var self = this;
+       var tag_width = $(target).width();
+       $(self).data("tag_width", tag_width);
+
+       var form = $("#g-in-place-edit-form");
+       if (form.length > 0) {
+         self._cancel();
+       }
+
+       $.get(self.options.form_url.replace("__ID__", $(target).attr('rel')), function(data) {
+         var parent = $(target).parent();
+         parent.children().hide();
+         parent.append(data);
+         self._setup_form(parent.find("form"));
+       });
+     },
+
+     _setup_form: function(form) {
+       var self = this;
+       var width = $(self).data("tag_width");
+       form.find(":text").width(width).focus();
+       form.find(".g-cancel").click(function(event) {
+         self._cancel();
+         event.preventDefault();
+         return false;
+       });
+       $(".g-short-form").gallery_short_form();
+       this._ajaxify_edit();
+     },
+
+     _cancel: function() {
+       var parent = $("#g-in-place-edit-form").parent();
+       $("#g-in-place-edit-form").remove();
+       $(parent).children().show();
+       $(parent).find(".g-editable").data("gallery_in_place_edit", false);
+     },
+
+     _ajaxify_edit: function() {
+       var self = this;
+       var form = $("#g-in-place-edit-form");
+       $(form).ajaxForm({
+         dataType: "json",
+         success: function(data) {
+           if (data.result == "success") {
+             window.location.reload();
+           } else {
+             var parent = $(form).parent();
+             $(form).replaceWith(data.form);
+             self._setup_form(parent.find("form"));
+           }
+         }
+       });
+     }
+   });
+
+   $.extend($.ui.gallery_in_place_edit,  {
+     defaults: {}
+   });
+})(jQuery);
diff --git a/lib/gallery.panel.js b/lib/gallery.panel.js
new file mode 100644
index 0000000..0683c53
--- /dev/null
+++ b/lib/gallery.panel.js
@@ -0,0 +1,100 @@
+(function($) {
+   $.widget("ui.gallery_panel", {
+     _init: function() {
+       var self = this;
+       this.element.click(function(event) {
+         event.preventDefault();
+         var element = event.currentTarget;
+         var parent = $(element).parent().parent();
+         var sHref = $(element).attr("href");
+         var parentClass = $(parent).attr("class");
+         var ePanel = "<tr id=\"g-panel\"><td colspan=\"6\"></td></tr>";
+
+	 // We keep track of the open vs. closed state by looking to see if there'
+	 // an orig_text attr.  If that attr is missing, then the panel is closed
+	 // and we want to open it
+	 var should_open = !$(element).attr("orig_text");
+
+	 // Close any open panels and reset their button text
+         if ($("#g-panel").length) {
+           $("#g-panel").slideUp("slow").remove();
+	   $.each($(".g-panel-link"),
+		  function() {
+		    if ($(this).attr("orig_text")) {
+		      $(this).children(".g-button-text").text($(this).attr("orig_text"));
+		      $(this).attr("orig_text", "");
+		    }
+		  }
+	   );
+         }
+
+	 if (should_open) {
+	   $(parent).after(ePanel);
+	   $("#g-panel td").html(sHref);
+	   $.ajax({
+             url: sHref,
+             type: "GET",
+             beforeSend: function(xhr) {
+               // Until we convert to jquery 1.4, we need to save the
+               // XMLHttpRequest object
+               this.xhrData = xhr;
+             },
+             success: function(data, textStatus, xhr) {
+	       // Pre jquery 1.4, get the saved XMLHttpRequest object
+               if (xhr == undefined) {
+                 xhr = this.xhrData;
+               }
+               var mimeType = /^(\w+\/\w+)\;?/.exec(xhr.getResponseHeader("Content-Type"));
+               var content = "";
+               if (mimeType[1] == "application/json") {
+                 data = JSON.parse(data);
+                 content = data.html;
+               } else {
+                 content = data;
+               }
+
+	       $("#g-panel td").html(content);
+	       self._ajaxify_panel();
+	       if ($(element).attr("open_text")) {
+	         $(element).attr("orig_text", $(element).children(".g-button-text").text());
+	         $(element).children(".g-button-text").text($(element).attr("open_text"));
+	       }
+	       $("#g-panel").addClass(parentClass).show().slideDown("slow");
+	     }
+           });
+	 }
+
+         return false;
+       });
+     },
+
+     _ajaxify_panel: function () {
+       var self = this;
+       $("#g-panel td form").ajaxForm({
+         dataType: "json",
+         beforeSubmit: function(formData, form, options) {
+           form.find(":submit")
+             .addClass("ui-state-disabled")
+             .attr("disabled", "disabled");
+           return true;
+         },
+         success: function(data) {
+           if (data.html) {
+             $("#g-panel td").html(data.html);
+             self._ajaxify_panel();
+           }
+           if (data.result == "success") {
+             self._trigger("success", null, {});
+             if (data.location) {
+               window.location = data.location;
+             } else {
+               window.location.reload();
+             }
+           }
+         }
+       });
+     },
+
+     success: function(event, ui) {}
+   });
+ })(jQuery);
diff --git a/lib/gallery.show_full_size.js b/lib/gallery.show_full_size.js
new file mode 100644
index 0000000..0baee88
--- /dev/null
+++ b/lib/gallery.show_full_size.js
@@ -0,0 +1,58 @@
+(function($) {
+  /**
+   * @todo Move inline CSS out to external style sheet (theme style sheet)
+   */
+  $.gallery_show_full_size = function(image_url, image_width, image_height) {
+    var width = $(document).width();
+    var height = $(document).height();
+    var size = $.gallery_get_viewport_size();
+
+    $("body").append('<div id="g-fullsize-overlay" class="ui-dialog-overlay" ' +
+		     'style="border: none; margin: 0; padding: 0; background-color: #000; ' +
+		     'position: fixed; top: 0px; left: 0px; ' +
+		     'width: 100%; height: 100%; ' +
+		     'opacity: 0.7; filter: alpha(opacity=70); ' +
+		     '-moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; ' +
+		     '-moz-background-inline-policy: -moz-initial; z-index: 1001;"> </div>');
+
+    var image_size;
+    if (image_width >= size.width() - 6 || image_height >= size.height() - 6) {
+      image_size = $.gallery_auto_fit_window(image_width, image_height);
+    } else {
+      image_size = {
+         top: 12,
+	 left: Math.round((width - image_width) / 2),
+         width: Math.round(image_width),
+	 height: Math.round(image_height)
+      };
+    }
+
+    $("body").append('<div id="g-fullsize" class="ui-dialog ui-widget" ' +
+		     'style="overflow: hidden; display: block; ' +
+		     'position: absolute; z-index: 1002; outline-color: -moz-use-text-color; ' +
+		     'outline-style: none; outline-width: 0px; ' +
+		     'height: ' + image_size.height + 'px; ' +
+		     'width: ' + image_size.width + 'px; ' +
+		     'top: ' + image_size.top + 'px; left: ' + image_size.left + 'px;">' +
+		     '<img id="g-fullsize-image" src="' + image_url + '"' +
+		     'height="' + image_size.height + '" width="' + image_size.width + '"/></div>');
+
+    $().click(function() {
+      $("#g-fullsize-overlay*").remove();
+      $("#g-fullsize").remove();
+    });
+    $().bind("keypress", function() {
+      $("#g-fullsize-overlay*").remove();
+      $("#g-fullsize").remove();
+    });
+    $(window).resize(function() {
+      $("#g-fullsize-overlay").width($(document).width()).height($(document).height());
+      image_size = $.gallery_auto_fit_window(image_width, image_height);
+      $("#g-fullsize").height(image_size.height)
+        .width(image_size.width)
+        .css("top", image_size.top)
+        .css("left", image_size.left);
+      $("#g-fullsize-image").height(image_size.height).width(image_size.width);
+    });
+  };
+})(jQuery);
diff --git a/lib/images/Galerie-Logo.png b/lib/images/Galerie-Logo.png
new file mode 100644
index 0000000..95c7007
Binary files /dev/null and b/lib/images/Galerie-Logo.png differ
diff --git a/lib/images/apple-touch-icon.png b/lib/images/apple-touch-icon.png
new file mode 100644
index 0000000..d15ce1a
Binary files /dev/null and b/lib/images/apple-touch-icon.png differ
diff --git a/lib/images/favicon.ico b/lib/images/favicon.ico
new file mode 100644
index 0000000..66531d8
Binary files /dev/null and b/lib/images/favicon.ico differ
diff --git a/lib/images/logo.png b/lib/images/logo.png
new file mode 100644
index 0000000..7d7b9b9
Binary files /dev/null and b/lib/images/logo.png differ
diff --git a/lib/jquery-ui.js b/lib/jquery-ui.js
new file mode 100644
index 0000000..74515a5
--- /dev/null
+++ b/lib/jquery-ui.js
@@ -0,0 +1,328 @@
+;jQuery.ui||(function($){var _remove=$.fn.remove,isFF2=$.browser.mozilla&&(parseFloat($.browser.version)<1.9);$.ui={version:"1.7.2",plugin:{add:function(module,option,set){var proto=$.ui[module].prototype;for(var i in set){proto.plugins[i]=proto.plugins[i]||[];proto.plugins[i].push([option,set[i]]);}},call:function(instance,name,args){var set=instance.plugins[name];if(!set||!instance.element[0].parentNode){return;}
+for(var i=0;i<set.length;i++){if(instance.options[set[i][0]]){set[i][1].apply(instance.element,args);}}}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b);},hasScroll:function(el,a){if($(el).css('overflow')=='hidden'){return false;}
+var scroll=(a&&a=='left')?'scrollLeft':'scrollTop',has=false;if(el[scroll]>0){return true;}
+el[scroll]=1;has=(el[scroll]>0);el[scroll]=0;return has;},isOverAxis:function(x,reference,size){return(x>reference)&&(x<(reference+size));},isOver:function(y,x,top,left,height,width){return $.ui.isOverAxis(y,top,height)&&$.ui.isOverAxis(x,left,width);},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(isFF2){var attr=$.attr,removeAttr=$.fn.removeAttr,ariaNS="http://www.w3.org/2005/07/aaa",ariaState=/^aria-/,ariaRole=/^wairole:/;$.attr=function(elem,name,value){var set=value!==undefined;return(name=='role'?(set?attr.call(this,elem,name,"wairole:"+value):(attr.apply(this,arguments)||"").replace(ariaRole,"")):(ariaState.test(name)?(set?elem.setAttributeNS(ariaNS,name.replace(ariaState,"aaa:"),value):attr.call(this,elem,name.replace(ariaState,"aaa:"))):attr.apply(this,arguments)));};$.fn.removeAttr=function(name){return(ariaState.test(name)?this.each(function(){this.removeAttributeNS(ariaNS,name.replace(ariaState,""));}):removeAttr.call(this,name));};}
+$.fn.extend({remove:function(){$("*",this).add(this).each(function(){$(this).triggerHandler("remove");});return _remove.apply(this,arguments);},enableSelection:function(){return this.attr('unselectable','off').css('MozUserSelect','').unbind('selectstart.ui');},disableSelection:function(){return this.attr('unselectable','on').css('MozUserSelect','none').bind('selectstart.ui',function(){return false;});},scrollParent:function(){var scrollParent;if(($.browser.msie&&(/(static|relative)/).test(this.css('position')))||(/absolute/).test(this.css('position'))){scrollParent=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test($.curCSS(this,'position',1))&&(/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));}).eq(0);}else{scrollParent=this.parents().filter(function(){return(/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));}).eq(0);}
+return(/fixed/).test(this.css('position'))||!scrollParent.length?$(document):scrollParent;}});$.extend($.expr[':'],{data:function(elem,i,match){return!!$.data(elem,match[3]);},focusable:function(element){var nodeName=element.nodeName.toLowerCase(),tabIndex=$.attr(element,'tabindex');return(/input|select|textarea|button|object/.test(nodeName)?!element.disabled:'a'==nodeName||'area'==nodeName?element.href||!isNaN(tabIndex):!isNaN(tabIndex))&&!$(element)['area'==nodeName?'parents':'closest'](':hidden').length;},tabbable:function(element){var tabIndex=$.attr(element,'tabindex');return(isNaN(tabIndex)||tabIndex>=0)&&$(element).is(':focusable');}});function getter(namespace,plugin,method,args){function getMethods(type){var methods=$[namespace][plugin][type]||[];return(typeof methods=='string'?methods.split(/,?\s+/):methods);}
+var methods=getMethods('getter');if(args.length==1&&typeof args[0]=='string'){methods=methods.concat(getMethods('getterSetter'));}
+return($.inArray(method,methods)!=-1);}
+$.widget=function(name,prototype){var namespace=name.split(".")[0];name=name.split(".")[1];$.fn[name]=function(options){var isMethodCall=(typeof options=='string'),args=Array.prototype.slice.call(arguments,1);if(isMethodCall&&options.substring(0,1)=='_'){return this;}
+if(isMethodCall&&getter(namespace,name,options,args)){var instance=$.data(this[0],name);return(instance?instance[options].apply(instance,args):undefined);}
+return this.each(function(){var instance=$.data(this,name);(!instance&&!isMethodCall&&$.data(this,name,new $[namespace][name](this,options))._init());(instance&&isMethodCall&&$.isFunction(instance[options])&&instance[options].apply(instance,args));});};$[namespace]=$[namespace]||{};$[namespace][name]=function(element,options){var self=this;this.namespace=namespace;this.widgetName=name;this.widgetEventPrefix=$[namespace][name].eventPrefix||name;this.widgetBaseClass=namespace+'-'+name;this.options=$.extend({},$.widget.defaults,$[namespace][name].defaults,$.metadata&&$.metadata.get(element)[name],options);this.element=$(element).bind('setData.'+name,function(event,key,value){if(event.target==element){return self._setData(key,value);}}).bind('getData.'+name,function(event,key){if(event.target==element){return self._getData(key);}}).bind('remove',function(){return self.destroy();});};$[namespace][name].prototype=$.extend({},$.widget.prototype,prototype);$[namespace][name].getterSetter='option';};$.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+'-disabled'+' '+this.namespace+'-state-disabled').removeAttr('aria-disabled');},option:function(key,value){var options=key,self=this;if(typeof key=="string"){if(value===undefined){return this._getData(key);}
+options={};options[key]=value;}
+$.each(options,function(key,value){self._setData(key,value);});},_getData:function(key){return this.options[key];},_setData:function(key,value){this.options[key]=value;if(key=='disabled'){this.element
+[value?'addClass':'removeClass'](this.widgetBaseClass+'-disabled'+' '+
+this.namespace+'-state-disabled').attr("aria-disabled",value);}},enable:function(){this._setData('disabled',false);},disable:function(){this._setData('disabled',true);},_trigger:function(type,event,data){var callback=this.options[type],eventName=(type==this.widgetEventPrefix?type:this.widgetEventPrefix+type);event=$.Event(event);event.type=eventName;if(event.originalEvent){for(var i=$.event.props.length,prop;i;){prop=$.event.props[--i];event[prop]=event.originalEvent[prop];}}
+this.element.trigger(event,data);return!($.isFunction(callback)&&callback.call(this.element[0],event,data)===false||event.isDefaultPrevented());}};$.widget.defaults={disabled:false};$.ui.mouse={_mouseInit:function(){var self=this;this.element.bind('mousedown.'+this.widgetName,function(event){return self._mouseDown(event);}).bind('click.'+this.widgetName,function(event){if(self._preventClickEvent){self._preventClickEvent=false;event.stopImmediatePropagation();return false;}});if($.browser.msie){this._mouseUnselectable=this.element.attr('unselectable');this.element.attr('unselectable','on');}
+this.started=false;},_mouseDestroy:function(){this.element.unbind('.'+this.widgetName);($.browser.msie&&this.element.attr('unselectable',this._mouseUnselectable));},_mouseDown:function(event){event.originalEvent=event.originalEvent||{};if(event.originalEvent.mouseHandled){return;}
+(this._mouseStarted&&this._mouseUp(event));this._mouseDownEvent=event;var self=this,btnIsLeft=(event.which==1),elIsCancel=(typeof this.options.cancel=="string"?$(event.target).parents().add(event.target).filter(this.options.cancel).length:false);if(!btnIsLeft||elIsCancel||!this._mouseCapture(event)){return true;}
+this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){self.mouseDelayMet=true;},this.options.delay);}
+if(this._mouseDistanceMet(event)&&this._mouseDelayMet(event)){this._mouseStarted=(this._mouseStart(event)!==false);if(!this._mouseStarted){event.preventDefault();return true;}}
+this._mouseMoveDelegate=function(event){return self._mouseMove(event);};this._mouseUpDelegate=function(event){return self._mouseUp(event);};$(document).bind('mousemove.'+this.widgetName,this._mouseMoveDelegate).bind('mouseup.'+this.widgetName,this._mouseUpDelegate);($.browser.safari||event.preventDefault());event.originalEvent.mouseHandled=true;return true;},_mouseMove:function(event){if($.browser.msie&&!(document.documentMode>=9)&&!event.button){return this._mouseUp(event);}
+if(this._mouseStarted){this._mouseDrag(event);return event.preventDefault();}
+if(this._mouseDistanceMet(event)&&this._mouseDelayMet(event)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,event)!==false);(this._mouseStarted?this._mouseDrag(event):this._mouseUp(event));}
+return!this._mouseStarted;},_mouseUp:function(event){$(document).unbind('mousemove.'+this.widgetName,this._mouseMoveDelegate).unbind('mouseup.'+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(event.target==this._mouseDownEvent.target);this._mouseStop(event);}
+return false;},_mouseDistanceMet:function(event){return(Math.max(Math.abs(this._mouseDownEvent.pageX-event.pageX),Math.abs(this._mouseDownEvent.pageY-event.pageY))>=this.options.distance);},_mouseDelayMet:function(event){return this.mouseDelayMet;},_mouseStart:function(event){},_mouseDrag:function(event){},_mouseStop:function(event){},_mouseCapture:function(event){return true;}};$.ui.mouse.defaults={cancel:null,distance:1,delay:0};})(jQuery);(function($){$.widget("ui.draggable",$.extend({},$.ui.mouse,{_init:function(){if(this.options.helper=='original'&&!(/^(?:r|a|f)/).test(this.element.css("position")))
+this.element[0].style.position='relative';(this.options.addClasses&&this.element.addClass("ui-draggable"));(this.options.disabled&&this.element.addClass("ui-draggable-disabled"));this._mouseInit();},destroy:function(){if(!this.element.data('draggable'))return;this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable"
++" ui-draggable-dragging"
++" ui-draggable-disabled");this._mouseDestroy();},_mouseCapture:function(event){var o=this.options;if(this.helper||o.disabled||$(event.target).is('.ui-resizable-handle'))
+return false;this.handle=this._getHandle(event);if(!this.handle)
+return false;return true;},_mouseStart:function(event){var o=this.options;this.helper=this._createHelper(event);this._cacheHelperProportions();if($.ui.ddmanager)
+$.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};$.extend(this.offset,{click:{left:event.pageX-this.offset.left,top:event.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(event);this.originalPageX=event.pageX;this.originalPageY=event.pageY;if(o.cursorAt)
+this._adjustOffsetFromHelper(o.cursorAt);if(o.containment)
+this._setContainment();this._trigger("start",event);this._cacheHelperProportions();if($.ui.ddmanager&&!o.dropBehaviour)
+$.ui.ddmanager.prepareOffsets(this,event);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(event,true);return true;},_mouseDrag:function(event,noPropagation){this.position=this._generatePosition(event);this.positionAbs=this._convertPositionTo("absolute");if(!noPropagation){var ui=this._uiHash();this._trigger('drag',event,ui);this.position=ui.position;}
+if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+'px';if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+'px';if($.ui.ddmanager)$.ui.ddmanager.drag(this,event);return false;},_mouseStop:function(event){var dropped=false;if($.ui.ddmanager&&!this.options.dropBehaviour)
+dropped=$.ui.ddmanager.drop(this,event);if(this.dropped){dropped=this.dropped;this.dropped=false;}
+if((this.options.revert=="invalid"&&!dropped)||(this.options.revert=="valid"&&dropped)||this.options.revert===true||($.isFunction(this.options.revert)&&this.options.revert.call(this.element,dropped))){var self=this;$(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){self._trigger("stop",event);self._clear();});}else{this._trigger("stop",event);this._clear();}
+return false;},_getHandle:function(event){var handle=!this.options.handle||!$(this.options.handle,this.element).length?true:false;$(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==event.target)handle=true;});return handle;},_createHelper:function(event){var o=this.options;var helper=$.isFunction(o.helper)?$(o.helper.apply(this.element[0],[event])):(o.helper=='clone'?this.element.clone():this.element);if(!helper.parents('body').length)
+helper.appendTo((o.appendTo=='parent'?this.element[0].parentNode:o.appendTo));if(helper[0]!=this.element[0]&&!(/(fixed|absolute)/).test(helper.css("position")))
+helper.css("position","absolute");return helper;},_adjustOffsetFromHelper:function(obj){if(obj.left!=undefined)this.offset.click.left=obj.left+this.margins.left;if(obj.right!=undefined)this.offset.click.left=this.helperProportions.width-obj.right+this.margins.left;if(obj.top!=undefined)this.offset.click.top=obj.top+this.margins.top;if(obj.bottom!=undefined)this.offset.click.top=this.helperProportions.height-obj.bottom+this.margins.top;},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var po=this.offsetParent.offset();if(this.cssPosition=='absolute'&&this.scrollParent[0]!=document&&$.ui.contains(this.scrollParent[0],this.offsetParent[0])){po.left+=this.scrollParent.scrollLeft();po.top+=this.scrollParent.scrollTop();}
+if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=='html'&&$.browser.msie))
+po={top:0,left:0};return{top:po.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:po.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)};},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var p=this.element.position();return{top:p.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:p.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()};}else{return{top:0,left:0};}},_cacheMargins:function(){this.margins={left:(parseInt(this.element.css("marginLeft"),10)||0),top:(parseInt(this.element.css("marginTop"),10)||0)};},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()};},_setContainment:function(){var o=this.options;if(o.containment=='parent')o.containment=this.helper[0].parentNode;if(o.containment=='document'||o.containment=='window')this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,$(o.containment=='document'?document:window).width()-this.helperProportions.width-this.margins.left,($(o.containment=='document'?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!(/^(document|window|parent)$/).test(o.containment)&&o.containment.constructor!=Array){var ce=$(o.containment)[0];if(!ce)return;var co=$(o.containment).offset();var over=($(ce).css("overflow")!='hidden');this.containment=[co.left+(parseInt($(ce).css("borderLeftWidth"),10)||0)+(parseInt($(ce).css("paddingLeft"),10)||0)-this.margins.left,co.top+(parseInt($(ce).css("borderTopWidth"),10)||0)+(parseInt($(ce).css("paddingTop"),10)||0)-this.margins.top,co.left+(over?Math.max(ce.scrollWidth,ce.offsetWidth):ce.offsetWidth)-(parseInt($(ce).css("borderLeftWidth"),10)||0)-(parseInt($(ce).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,co.top+(over?Math.max(ce.scrollHeight,ce.offsetHeight):ce.offsetHeight)-(parseInt($(ce).css("borderTopWidth"),10)||0)-(parseInt($(ce).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top];}else if(o.containment.constructor==Array){this.containment=o.containment;}},_convertPositionTo:function(d,pos){if(!pos)pos=this.position;var mod=d=="absolute"?1:-1;var o=this.options,scroll=this.cssPosition=='absolute'&&!(this.scrollParent[0]!=document&&$.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,scrollIsRootNode=(/(html|body)/i).test(scroll[0].tagName);return{top:(pos.top
++this.offset.relative.top*mod
++this.offset.parent.top*mod
+-($.browser.safari&&this.cssPosition=='fixed'?0:(this.cssPosition=='fixed'?-this.scrollParent.scrollTop():(scrollIsRootNode?0:scroll.scrollTop()))*mod)),left:(pos.left
++this.offset.relative.left*mod
++this.offset.parent.left*mod
+-($.browser.safari&&this.cssPosition=='fixed'?0:(this.cssPosition=='fixed'?-this.scrollParent.scrollLeft():scrollIsRootNode?0:scroll.scrollLeft())*mod))};},_generatePosition:function(event){var o=this.options,scroll=this.cssPosition=='absolute'&&!(this.scrollParent[0]!=document&&$.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,scrollIsRootNode=(/(html|body)/i).test(scroll[0].tagName);if(this.cssPosition=='relative'&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset();}
+var pageX=event.pageX;var pageY=event.pageY;if(this.originalPosition){if(this.containment){if(event.pageX-this.offset.click.left<this.containment[0])pageX=this.containment[0]+this.offset.click.left;if(event.pageY-this.offset.click.top<this.containment[1])pageY=this.containment[1]+this.offset.click.top;if(event.pageX-this.offset.click.left>this.containment[2])pageX=this.containment[2]+this.offset.click.left;if(event.pageY-this.offset.click.top>this.containment[3])pageY=this.containment[3]+this.offset.click.top;}
+if(o.grid){var top=this.originalPageY+Math.round((pageY-this.originalPageY)/o.grid[1])*o.grid[1];pageY=this.containment?(!(top-this.offset.click.top<this.containment[1]||top-this.offset.click.top>this.containment[3])?top:(!(top-this.offset.click.top<this.containment[1])?top-o.grid[1]:top+o.grid[1])):top;var left=this.originalPageX+Math.round((pageX-this.originalPageX)/o.grid[0])*o.grid[0];pageX=this.containment?(!(left-this.offset.click.left<this.containment[0]||left-this.offset.click.left>this.containment[2])?left:(!(left-this.offset.click.left<this.containment[0])?left-o.grid[0]:left+o.grid[0])):left;}}
+return{top:(pageY
+-this.offset.click.top
+-this.offset.relative.top
+-this.offset.parent.top
++($.browser.safari&&this.cssPosition=='fixed'?0:(this.cssPosition=='fixed'?-this.scrollParent.scrollTop():(scrollIsRootNode?0:scroll.scrollTop())))),left:(pageX
+-this.offset.click.left
+-this.offset.relative.left
+-this.offset.parent.left
++($.browser.safari&&this.cssPosition=='fixed'?0:(this.cssPosition=='fixed'?-this.scrollParent.scrollLeft():scrollIsRootNode?0:scroll.scrollLeft())))};},_clear:function(){this.helper.removeClass("ui-draggable-dragging");if(this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval)this.helper.remove();this.helper=null;this.cancelHelperRemoval=false;},_trigger:function(type,event,ui){ui=ui||this._uiHash();$.ui.plugin.call(this,type,[event,ui]);if(type=="drag")this.positionAbs=this._convertPositionTo("absolute");return $.widget.prototype._trigger.call(this,type,event,ui);},plugins:{},_uiHash:function(event){return{helper:this.helper,position:this.position,absolutePosition:this.positionAbs,offset:this.positionAbs};}}));$.extend($.ui.draggable,{version:"1.7.2",eventPrefix:"drag",defaults:{addClasses:true,appendTo:"parent",axis:false,cancel:":input,option",connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false}});$.ui.plugin.add("draggable","connectToSortable",{start:function(event,ui){var inst=$(this).data("draggable"),o=inst.options,uiSortable=$.extend({},ui,{item:inst.element});inst.sortables=[];$(o.connectToSortable).each(function(){var sortable=$.data(this,'sortable');if(sortable&&!sortable.options.disabled){inst.sortables.push({instance:sortable,shouldRevert:sortable.options.revert});sortable._refreshItems();sortable._trigger("activate",event,uiSortable);}});},stop:function(event,ui){var inst=$(this).data("draggable"),uiSortable=$.extend({},ui,{item:inst.element});$.each(inst.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;inst.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(event);this.instance.options.helper=this.instance.options._helper;if(inst.options.helper=='original')
+this.instance.currentItem.css({top:'auto',left:'auto'});}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",event,uiSortable);}});},drag:function(event,ui){var inst=$(this).data("draggable"),self=this;var checkPos=function(o){var dyClick=this.offset.click.top,dxClick=this.offset.click.left;var helperTop=this.positionAbs.top,helperLeft=this.positionAbs.left;var itemHeight=o.height,itemWidth=o.width;var itemTop=o.top,itemLeft=o.left;return $.ui.isOver(helperTop+dyClick,helperLeft+dxClick,itemTop,itemLeft,itemHeight,itemWidth);};$.each(inst.sortables,function(i){this.instance.positionAbs=inst.positionAbs;this.instance.helperProportions=inst.helperProportions;this.instance.offset.click=inst.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=$(self).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return ui.helper[0];};event.target=this.instance.currentItem[0];this.instance._mouseCapture(event,true);this.instance._mouseStart(event,true,true);this.instance.offset.click.top=inst.offset.click.top;this.instance.offset.click.left=inst.offset.click.left;this.instance.offset.parent.left-=inst.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=inst.offset.parent.top-this.instance.offset.parent.top;inst._trigger("toSortable",event);inst.dropped=this.instance.element;inst.currentItem=inst.element;this.instance.fromOutside=inst;}
+if(this.instance.currentItem)this.instance._mouseDrag(event);}else{if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger('out',event,this.instance._uiHash(this.instance));this.instance._mouseStop(event,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();if(this.instance.placeholder)this.instance.placeholder.remove();inst._trigger("fromSortable",event);inst.dropped=false;}};});}});$.ui.plugin.add("draggable","cursor",{start:function(event,ui){var t=$('body'),o=$(this).data('draggable').options;if(t.css("cursor"))o._cursor=t.css("cursor");t.css("cursor",o.cursor);},stop:function(event,ui){var o=$(this).data('draggable').options;if(o._cursor)$('body').css("cursor",o._cursor);}});$.ui.plugin.add("draggable","iframeFix",{start:function(event,ui){var o=$(this).data('draggable').options;$(o.iframeFix===true?"iframe":o.iframeFix).each(function(){$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1000}).css($(this).offset()).appendTo("body");});},stop:function(event,ui){$("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this);});}});$.ui.plugin.add("draggable","opacity",{start:function(event,ui){var t=$(ui.helper),o=$(this).data('draggable').options;if(t.css("opacity"))o._opacity=t.css("opacity");t.css('opacity',o.opacity);},stop:function(event,ui){var o=$(this).data('draggable').options;if(o._opacity)$(ui.helper).css('opacity',o._opacity);}});$.ui.plugin.add("draggable","scroll",{start:function(event,ui){var i=$(this).data("draggable");if(i.scrollParent[0]!=document&&i.scrollParent[0].tagName!='HTML')i.overflowOffset=i.scrollParent.offset();},drag:function(event,ui){var i=$(this).data("draggable"),o=i.options,scrolled=false;if(i.scrollParent[0]!=document&&i.scrollParent[0].tagName!='HTML'){if(!o.axis||o.axis!='x'){if((i.overflowOffset.top+i.scrollParent[0].offsetHeight)-event.pageY<o.scrollSensitivity)
+i.scrollParent[0].scrollTop=scrolled=i.scrollParent[0].scrollTop+o.scrollSpeed;else if(event.pageY-i.overflowOffset.top<o.scrollSensitivity)
+i.scrollParent[0].scrollTop=scrolled=i.scrollParent[0].scrollTop-o.scrollSpeed;}
+if(!o.axis||o.axis!='y'){if((i.overflowOffset.left+i.scrollParent[0].offsetWidth)-event.pageX<o.scrollSensitivity)
+i.scrollParent[0].scrollLeft=scrolled=i.scrollParent[0].scrollLeft+o.scrollSpeed;else if(event.pageX-i.overflowOffset.left<o.scrollSensitivity)
+i.scrollParent[0].scrollLeft=scrolled=i.scrollParent[0].scrollLeft-o.scrollSpeed;}}else{if(!o.axis||o.axis!='x'){if(event.pageY-$(document).scrollTop()<o.scrollSensitivity)
+scrolled=$(document).scrollTop($(document).scrollTop()-o.scrollSpeed);else if($(window).height()-(event.pageY-$(document).scrollTop())<o.scrollSensitivity)
+scrolled=$(document).scrollTop($(document).scrollTop()+o.scrollSpeed);}
+if(!o.axis||o.axis!='y'){if(event.pageX-$(document).scrollLeft()<o.scrollSensitivity)
+scrolled=$(document).scrollLeft($(document).scrollLeft()-o.scrollSpeed);else if($(window).width()-(event.pageX-$(document).scrollLeft())<o.scrollSensitivity)
+scrolled=$(document).scrollLeft($(document).scrollLeft()+o.scrollSpeed);}}
+if(scrolled!==false&&$.ui.ddmanager&&!o.dropBehaviour)
+$.ui.ddmanager.prepareOffsets(i,event);}});$.ui.plugin.add("draggable","snap",{start:function(event,ui){var i=$(this).data("draggable"),o=i.options;i.snapElements=[];$(o.snap.constructor!=String?(o.snap.items||':data(draggable)'):o.snap).each(function(){var $t=$(this);var $o=$t.offset();if(this!=i.element[0])i.snapElements.push({item:this,width:$t.outerWidth(),height:$t.outerHeight(),top:$o.top,left:$o.left});});},drag:function(event,ui){var inst=$(this).data("draggable"),o=inst.options;var d=o.snapTolerance;var x1=ui.offset.left,x2=x1+inst.helperProportions.width,y1=ui.offset.top,y2=y1+inst.helperProportions.height;for(var i=inst.snapElements.length-1;i>=0;i--){var l=inst.snapElements[i].left,r=l+inst.snapElements[i].width,t=inst.snapElements[i].top,b=t+inst.snapElements[i].height;if(!((l-d<x1&&x1<r+d&&t-d<y1&&y1<b+d)||(l-d<x1&&x1<r+d&&t-d<y2&&y2<b+d)||(l-d<x2&&x2<r+d&&t-d<y1&&y1<b+d)||(l-d<x2&&x2<r+d&&t-d<y2&&y2<b+d))){if(inst.snapElements[i].snapping)(inst.options.snap.release&&inst.options.snap.release.call(inst.element,event,$.extend(inst._uiHash(),{snapItem:inst.snapElements[i].item})));inst.snapElements[i].snapping=false;continue;}
+if(o.snapMode!='inner'){var ts=Math.abs(t-y2)<=d;var bs=Math.abs(b-y1)<=d;var ls=Math.abs(l-x2)<=d;var rs=Math.abs(r-x1)<=d;if(ts)ui.position.top=inst._convertPositionTo("relative",{top:t-inst.helperProportions.height,left:0}).top-inst.margins.top;if(bs)ui.position.top=inst._convertPositionTo("relative",{top:b,left:0}).top-inst.margins.top;if(ls)ui.position.left=inst._convertPositionTo("relative",{top:0,left:l-inst.helperProportions.width}).left-inst.margins.left;if(rs)ui.position.left=inst._convertPositionTo("relative",{top:0,left:r}).left-inst.margins.left;}
+var first=(ts||bs||ls||rs);if(o.snapMode!='outer'){var ts=Math.abs(t-y1)<=d;var bs=Math.abs(b-y2)<=d;var ls=Math.abs(l-x1)<=d;var rs=Math.abs(r-x2)<=d;if(ts)ui.position.top=inst._convertPositionTo("relative",{top:t,left:0}).top-inst.margins.top;if(bs)ui.position.top=inst._convertPositionTo("relative",{top:b-inst.helperProportions.height,left:0}).top-inst.margins.top;if(ls)ui.position.left=inst._convertPositionTo("relative",{top:0,left:l}).left-inst.margins.left;if(rs)ui.position.left=inst._convertPositionTo("relative",{top:0,left:r-inst.helperProportions.width}).left-inst.margins.left;}
+if(!inst.snapElements[i].snapping&&(ts||bs||ls||rs||first))
+(inst.options.snap.snap&&inst.options.snap.snap.call(inst.element,event,$.extend(inst._uiHash(),{snapItem:inst.snapElements[i].item})));inst.snapElements[i].snapping=(ts||bs||ls||rs||first);};}});$.ui.plugin.add("draggable","stack",{start:function(event,ui){var o=$(this).data("draggable").options;var group=$.makeArray($(o.stack.group)).sort(function(a,b){return(parseInt($(a).css("zIndex"),10)||o.stack.min)-(parseInt($(b).css("zIndex"),10)||o.stack.min);});$(group).each(function(i){this.style.zIndex=o.stack.min+i;});this[0].style.zIndex=o.stack.min+group.length;}});$.ui.plugin.add("draggable","zIndex",{start:function(event,ui){var t=$(ui.helper),o=$(this).data("draggable").options;if(t.css("zIndex"))o._zIndex=t.css("zIndex");t.css('zIndex',o.zIndex);},stop:function(event,ui){var o=$(this).data("draggable").options;if(o._zIndex)$(ui.helper).css('zIndex',o._zIndex);}});})(jQuery);(function($){$.widget("ui.droppable",{_init:function(){var o=this.options,accept=o.accept;this.isover=0;this.isout=1;this.options.accept=this.options.accept&&$.isFunction(this.options.accept)?this.options.accept:function(d){return d.is(accept);};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};$.ui.ddmanager.droppables[this.options.scope]=$.ui.ddmanager.droppables[this.options.scope]||[];$.ui.ddmanager.droppables[this.options.scope].push(this);(this.options.addClasses&&this.element.addClass("ui-droppable"));},destroy:function(){var drop=$.ui.ddmanager.droppables[this.options.scope];for(var i=0;i<drop.length;i++)
+if(drop[i]==this)
+drop.splice(i,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");},_setData:function(key,value){if(key=='accept'){this.options.accept=value&&$.isFunction(value)?value:function(d){return d.is(value);};}else{$.widget.prototype._setData.apply(this,arguments);}},_activate:function(event){var draggable=$.ui.ddmanager.current;if(this.options.activeClass)this.element.addClass(this.options.activeClass);(draggable&&this._trigger('activate',event,this.ui(draggable)));},_deactivate:function(event){var draggable=$.ui.ddmanager.current;if(this.options.activeClass)this.element.removeClass(this.options.activeClass);(draggable&&this._trigger('deactivate',event,this.ui(draggable)));},_over:function(event){var draggable=$.ui.ddmanager.current;if(!draggable||(draggable.currentItem||draggable.element)[0]==this.element[0])return;if(this.options.accept.call(this.element[0],(draggable.currentItem||draggable.element))){if(this.options.hoverClass)this.element.addClass(this.options.hoverClass);this._trigger('over',event,this.ui(draggable));}},_out:function(event){var draggable=$.ui.ddmanager.current;if(!draggable||(draggable.currentItem||draggable.element)[0]==this.element[0])return;if(this.options.accept.call(this.element[0],(draggable.currentItem||draggable.element))){if(this.options.hoverClass)this.element.removeClass(this.options.hoverClass);this._trigger('out',event,this.ui(draggable));}},_drop:function(event,custom){var draggable=custom||$.ui.ddmanager.current;if(!draggable||(draggable.currentItem||draggable.element)[0]==this.element[0])return false;var childrenIntersection=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var inst=$.data(this,'droppable');if(inst.options.greedy&&$.ui.intersect(draggable,$.extend(inst,{offset:inst.element.offset()}),inst.options.tolerance)){childrenIntersection=true;return false;}});if(childrenIntersection)return false;if(this.options.accept.call(this.element[0],(draggable.currentItem||draggable.element))){if(this.options.activeClass)this.element.removeClass(this.options.activeClass);if(this.options.hoverClass)this.element.removeClass(this.options.hoverClass);this._trigger('drop',event,this.ui(draggable));return this.element;}
+return false;},ui:function(c){return{draggable:(c.currentItem||c.element),helper:c.helper,position:c.position,absolutePosition:c.positionAbs,offset:c.positionAbs};}});$.extend($.ui.droppable,{version:"1.7.2",eventPrefix:'drop',defaults:{accept:'*',activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:'default',tolerance:'intersect'}});$.ui.intersect=function(draggable,droppable,toleranceMode){if(!droppable.offset)return false;var x1=(draggable.positionAbs||draggable.position.absolute).left,x2=x1+draggable.helperProportions.width,y1=(draggable.positionAbs||draggable.position.absolute).top,y2=y1+draggable.helperProportions.height;var l=droppable.offset.left,r=l+droppable.proportions.width,t=droppable.offset.top,b=t+droppable.proportions.height;switch(toleranceMode){case'fit':return(l<x1&&x2<r&&t<y1&&y2<b);break;case'intersect':return(l<x1+(draggable.helperProportions.width/2)&&x2-(draggable.helperProportions.width/2)<r&&t<y1+(draggable.helperProportions.height/2)&&y2-(draggable.helperProportions.height/2)<b);break;case'pointer':var draggableLeft=((draggable.positionAbs||draggable.position.absolute).left+(draggable.clickOffset||draggable.offset.click).left),draggableTop=((draggable.positionAbs||draggable.position.absolute).top+(draggable.clickOffset||draggable.offset.click).top),isOver=$.ui.isOver(draggableTop,draggableLeft,t,l,droppable.proportions.height,droppable.proportions.width);return isOver;break;case'touch':return((y1>=t&&y1<=b)||(y2>=t&&y2<=b)||(y1<t&&y2>b))&&((x1>=l&&x1<=r)||(x2>=l&&x2<=r)||(x1<l&&x2>r));break;default:return false;break;}};$.ui.ddmanager={current:null,droppables:{'default':[]},prepareOffsets:function(t,event){var m=$.ui.ddmanager.droppables[t.options.scope];var type=event?event.type:null;var list=(t.currentItem||t.element).find(":data(droppable)").andSelf();droppablesLoop:for(var i=0;i<m.length;i++){if(m[i].options.disabled||(t&&!m[i].options.accept.call(m[i].element[0],(t.currentItem||t.element))))continue;for(var j=0;j<list.length;j++){if(list[j]==m[i].element[0]){m[i].proportions.height=0;continue droppablesLoop;}};m[i].visible=m[i].element.css("display")!="none";if(!m[i].visible)continue;m[i].offset=m[i].element.offset();m[i].proportions={width:m[i].element[0].offsetWidth,height:m[i].element[0].offsetHeight};if(type=="mousedown")m[i]._activate.call(m[i],event);}},drop:function(draggable,event){var dropped=false;$.each($.ui.ddmanager.droppables[draggable.options.scope],function(){if(!this.options)return;if(!this.options.disabled&&this.visible&&$.ui.intersect(draggable,this,this.options.tolerance))
+dropped=this._drop.call(this,event);if(!this.options.disabled&&this.visible&&this.options.accept.call(this.element[0],(draggable.currentItem||draggable.element))){this.isout=1;this.isover=0;this._deactivate.call(this,event);}});return dropped;},drag:function(draggable,event){if(draggable.options.refreshPositions)$.ui.ddmanager.prepareOffsets(draggable,event);$.each($.ui.ddmanager.droppables[draggable.options.scope],function(){if(this.options.disabled||this.greedyChild||!this.visible)return;var intersects=$.ui.intersect(draggable,this,this.options.tolerance);var c=!intersects&&this.isover==1?'isout':(intersects&&this.isover==0?'isover':null);if(!c)return;var parentInstance;if(this.options.greedy){var parent=this.element.parents(':data(droppable):eq(0)');if(parent.length){parentInstance=$.data(parent[0],'droppable');parentInstance.greedyChild=(c=='isover'?1:0);}}
+if(parentInstance&&c=='isover'){parentInstance['isover']=0;parentInstance['isout']=1;parentInstance._out.call(parentInstance,event);}
+this[c]=1;this[c=='isout'?'isover':'isout']=0;this[c=="isover"?"_over":"_out"].call(this,event);if(parentInstance&&c=='isout'){parentInstance['isout']=0;parentInstance['isover']=1;parentInstance._over.call(parentInstance,event);}});}};})(jQuery);(function($){$.widget("ui.resizable",$.extend({},$.ui.mouse,{_init:function(){var self=this,o=this.options;this.element.addClass("ui-resizable");$.extend(this,{_aspectRatio:!!(o.aspectRatio),aspectRatio:o.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:o.helper||o.ghost||o.animate?o.helper||'ui-resizable-helper':null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){if(/relative/.test(this.element.css('position'))&&$.browser.opera)
+this.element.css({position:'relative',top:'auto',left:'auto'});this.element.wrap($('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css('position'),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css('top'),left:this.element.css('left')}));this.element=this.element.parent().data("resizable",this.element.data('resizable'));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css('resize');this.originalElement.css('resize','none');this._proportionallyResizeElements.push(this.originalElement.css({position:'static',zoom:1,display:'block'}));this.originalElement.css({margin:this.originalElement.css('margin')});this._proportionallyResize();}
+this.handles=o.handles||(!$('.ui-resizable-handle',this.element).length?"e,s,se":{n:'.ui-resizable-n',e:'.ui-resizable-e',s:'.ui-resizable-s',w:'.ui-resizable-w',se:'.ui-resizable-se',sw:'.ui-resizable-sw',ne:'.ui-resizable-ne',nw:'.ui-resizable-nw'});if(this.handles.constructor==String){if(this.handles=='all')this.handles='n,e,s,w,se,sw,ne,nw';var n=this.handles.split(",");this.handles={};for(var i=0;i<n.length;i++){var handle=$.trim(n[i]),hname='ui-resizable-'+handle;var axis=$('<div class="ui-resizable-handle '+hname+'"></div>');if(/sw|se|ne|nw/.test(handle))axis.css({zIndex:++o.zIndex});if('se'==handle){axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');};this.handles[handle]='.ui-resizable-'+handle;this.element.append(axis);}}
+this._renderAxis=function(target){target=target||this.element;for(var i in this.handles){if(this.handles[i].constructor==String)
+this.handles[i]=$(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var axis=$(this.handles[i],this.element),padWrapper=0;padWrapper=/sw|ne|nw|se|n|s/.test(i)?axis.outerHeight():axis.outerWidth();var padPos=['padding',/ne|nw|n/.test(i)?'Top':/se|sw|s/.test(i)?'Bottom':/^e$/.test(i)?'Right':'Left'].join("");target.css(padPos,padWrapper);this._proportionallyResize();}
+if(!$(this.handles[i]).length)
+continue;}};this._renderAxis(this.element);this._handles=$('.ui-resizable-handle',this.element).disableSelection();this._handles.mouseover(function(){if(!self.resizing){if(this.className)
+var axis=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);self.axis=axis&&axis[1]?axis[1]:'se';}});if(o.autoHide){this._handles.hide();$(this.element).addClass("ui-resizable-autohide").hover(function(){$(this).removeClass("ui-resizable-autohide");self._handles.show();},function(){if(!self.resizing){$(this).addClass("ui-resizable-autohide");self._handles.hide();}});}
+this._mouseInit();},destroy:function(){this._mouseDestroy();var _destroy=function(exp){$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();};if(this.elementIsWrapper){_destroy(this.element);var wrapper=this.element;wrapper.parent().append(this.originalElement.css({position:wrapper.css('position'),width:wrapper.outerWidth(),height:wrapper.outerHeight(),top:wrapper.css('top'),left:wrapper.css('left')})).end().remove();}
+this.originalElement.css('resize',this.originalResizeStyle);_destroy(this.originalElement);},_mouseCapture:function(event){var handle=false;for(var i in this.handles){if($(this.handles[i])[0]==event.target)handle=true;}
+return this.options.disabled||!!handle;},_mouseStart:function(event){var o=this.options,iniPos=this.element.position(),el=this.element;this.resizing=true;this.documentScroll={top:$(document).scrollTop(),left:$(document).scrollLeft()};if(el.is('.ui-draggable')||(/absolute/).test(el.css('position'))){el.css({position:'absolute',top:iniPos.top,left:iniPos.left});}
+if($.browser.opera&&(/relative/).test(el.css('position')))
+el.css({position:'relative',top:'auto',left:'auto'});this._renderProxy();var curleft=num(this.helper.css('left')),curtop=num(this.helper.css('top'));if(o.containment){curleft+=$(o.containment).scrollLeft()||0;curtop+=$(o.containment).scrollTop()||0;}
+this.offset=this.helper.offset();this.position={left:curleft,top:curtop};this.size=this._helper?{width:el.outerWidth(),height:el.outerHeight()}:{width:el.width(),height:el.height()};this.originalSize=this._helper?{width:el.outerWidth(),height:el.outerHeight()}:{width:el.width(),height:el.height()};this.originalPosition={left:curleft,top:curtop};this.sizeDiff={width:el.outerWidth()-el.width(),height:el.outerHeight()-el.height()};this.originalMousePosition={left:event.pageX,top:event.pageY};this.aspectRatio=(typeof o.aspectRatio=='number')?o.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var cursor=$('.ui-resizable-'+this.axis).css('cursor');$('body').css('cursor',cursor=='auto'?this.axis+'-resize':cursor);el.addClass("ui-resizable-resizing");this._propagate("start",event);return true;},_mouseDrag:function(event){var el=this.helper,o=this.options,props={},self=this,smp=this.originalMousePosition,a=this.axis;var dx=(event.pageX-smp.left)||0,dy=(event.pageY-smp.top)||0;var trigger=this._change[a];if(!trigger)return false;var data=trigger.apply(this,[event,dx,dy]),ie6=$.browser.msie&&$.browser.version<7,csdif=this.sizeDiff;if(this._aspectRatio||event.shiftKey)
+data=this._updateRatio(data,event);data=this._respectSize(data,event);this._propagate("resize",event);el.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length)
+this._proportionallyResize();this._updateCache(data);this._trigger('resize',event,this.ui());return false;},_mouseStop:function(event){this.resizing=false;var o=this.options,self=this;if(this._helper){var pr=this._proportionallyResizeElements,ista=pr.length&&(/textarea/i).test(pr[0].nodeName),soffseth=ista&&$.ui.hasScroll(pr[0],'left')?0:self.sizeDiff.height,soffsetw=ista?0:self.sizeDiff.width;var s={width:(self.size.width-soffsetw),height:(self.size.height-soffseth)},left=(parseInt(self.element.css('left'),10)+(self.position.left-self.originalPosition.left))||null,top=(parseInt(self.element.css('top'),10)+(self.position.top-self.originalPosition.top))||null;if(!o.animate)
+this.element.css($.extend(s,{top:top,left:left}));self.helper.height(self.size.height);self.helper.width(self.size.width);if(this._helper&&!o.animate)this._proportionallyResize();}
+$('body').css('cursor','auto');this.element.removeClass("ui-resizable-resizing");this._propagate("stop",event);if(this._helper)this.helper.remove();return false;},_updateCache:function(data){var o=this.options;this.offset=this.helper.offset();if(isNumber(data.left))this.position.left=data.left;if(isNumber(data.top))this.position.top=data.top;if(isNumber(data.height))this.size.height=data.height;if(isNumber(data.width))this.size.width=data.width;},_updateRatio:function(data,event){var o=this.options,cpos=this.position,csize=this.size,a=this.axis;if(data.height)data.width=(csize.height*this.aspectRatio);else if(data.width)data.height=(csize.width/this.aspectRatio);if(a=='sw'){data.left=cpos.left+(csize.width-data.width);data.top=null;}
+if(a=='nw'){data.top=cpos.top+(csize.height-data.height);data.left=cpos.left+(csize.width-data.width);}
+return data;},_respectSize:function(data,event){var el=this.helper,o=this.options,pRatio=this._aspectRatio||event.shiftKey,a=this.axis,ismaxw=isNumber(data.width)&&o.maxWidth&&(o.maxWidth<data.width),ismaxh=isNumber(data.height)&&o.maxHeight&&(o.maxHeight<data.height),isminw=isNumber(data.width)&&o.minWidth&&(o.minWidth>data.width),isminh=isNumber(data.height)&&o.minHeight&&(o.minHeight>data.height);if(isminw)data.width=o.minWidth;if(isminh)data.height=o.minHeight;if(ismaxw)data.width=o.maxWidth;if(ismaxh)data.height=o.maxHeight;var dw=this.originalPosition.left+this.originalSize.width,dh=this.position.top+this.size.height;var cw=/sw|nw|w/.test(a),ch=/nw|ne|n/.test(a);if(isminw&&cw)data.left=dw-o.minWidth;if(ismaxw&&cw)data.left=dw-o.maxWidth;if(isminh&&ch)data.top=dh-o.minHeight;if(ismaxh&&ch)data.top=dh-o.maxHeight;var isNotwh=!data.width&&!data.height;if(isNotwh&&!data.left&&data.top)data.top=null;else if(isNotwh&&!data.top&&data.left)data.left=null;return data;},_proportionallyResize:function(){var o=this.options;if(!this._proportionallyResizeElements.length)return;var element=this.helper||this.element;for(var i=0;i<this._proportionallyResizeElements.length;i++){var prel=this._proportionallyResizeElements[i];if(!this.borderDif){var b=[prel.css('borderTopWidth'),prel.css('borderRightWidth'),prel.css('borderBottomWidth'),prel.css('borderLeftWidth')],p=[prel.css('paddingTop'),prel.css('paddingRight'),prel.css('paddingBottom'),prel.css('paddingLeft')];this.borderDif=$.map(b,function(v,i){var border=parseInt(v,10)||0,padding=parseInt(p[i],10)||0;return border+padding;});}
+if($.browser.msie&&!(!($(element).is(':hidden')||$(element).parents(':hidden').length)))
+continue;prel.css({height:(element.height()-this.borderDif[0]-this.borderDif[2])||0,width:(element.width()-this.borderDif[1]-this.borderDif[3])||0});};},_renderProxy:function(){var el=this.element,o=this.options;this.elementOffset=el.offset();if(this._helper){this.helper=this.helper||$('<div style="overflow:hidden;"></div>');var ie6=$.browser.msie&&$.browser.version<7,ie6offset=(ie6?1:0),pxyoffset=(ie6?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+pxyoffset,height:this.element.outerHeight()+pxyoffset,position:'absolute',left:this.elementOffset.left-ie6offset+'px',top:this.elementOffset.top-ie6offset+'px',zIndex:++o.zIndex});this.helper.appendTo("body").disableSelection();}else{this.helper=this.element;}},_change:{e:function(event,dx,dy){return{width:this.originalSize.width+dx};},w:function(event,dx,dy){var o=this.options,cs=this.originalSize,sp=this.originalPosition;return{left:sp.left+dx,width:cs.width-dx};},n:function(event,dx,dy){var o=this.options,cs=this.originalSize,sp=this.originalPosition;return{top:sp.top+dy,height:cs.height-dy};},s:function(event,dx,dy){return{height:this.originalSize.height+dy};},se:function(event,dx,dy){return $.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[event,dx,dy]));},sw:function(event,dx,dy){return $.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[event,dx,dy]));},ne:function(event,dx,dy){return $.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[event,dx,dy]));},nw:function(event,dx,dy){return $.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[event,dx,dy]));}},_propagate:function(n,event){$.ui.plugin.call(this,n,[event,this.ui()]);(n!="resize"&&this._trigger(n,event,this.ui()));},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition};}}));$.extend($.ui.resizable,{version:"1.7.2",eventPrefix:"resize",defaults:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,cancel:":input,option",containment:false,delay:0,distance:1,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000}});$.ui.plugin.add("resizable","alsoResize",{start:function(event,ui){var self=$(this).data("resizable"),o=self.options;_store=function(exp){$(exp).each(function(){$(this).data("resizable-alsoresize",{width:parseInt($(this).width(),10),height:parseInt($(this).height(),10),left:parseInt($(this).css('left'),10),top:parseInt($(this).css('top'),10)});});};if(typeof(o.alsoResize)=='object'&&!o.alsoResize.parentNode){if(o.alsoResize.length){o.alsoResize=o.alsoResize[0];_store(o.alsoResize);}
+else{$.each(o.alsoResize,function(exp,c){_store(exp);});}}else{_store(o.alsoResize);}},resize:function(event,ui){var self=$(this).data("resizable"),o=self.options,os=self.originalSize,op=self.originalPosition;var delta={height:(self.size.height-os.height)||0,width:(self.size.width-os.width)||0,top:(self.position.top-op.top)||0,left:(self.position.left-op.left)||0},_alsoResize=function(exp,c){$(exp).each(function(){var el=$(this),start=$(this).data("resizable-alsoresize"),style={},css=c&&c.length?c:['width','height','top','left'];$.each(css||['width','height','top','left'],function(i,prop){var sum=(start[prop]||0)+(delta[prop]||0);if(sum&&sum>=0)
+style[prop]=sum||null;});if(/relative/.test(el.css('position'))&&$.browser.opera){self._revertToRelativePosition=true;el.css({position:'absolute',top:'auto',left:'auto'});}
+el.css(style);});};if(typeof(o.alsoResize)=='object'&&!o.alsoResize.nodeType){$.each(o.alsoResize,function(exp,c){_alsoResize(exp,c);});}else{_alsoResize(o.alsoResize);}},stop:function(event,ui){var self=$(this).data("resizable");if(self._revertToRelativePosition&&$.browser.opera){self._revertToRelativePosition=false;el.css({position:'relative'});}
+$(this).removeData("resizable-alsoresize-start");}});$.ui.plugin.add("resizable","animate",{stop:function(event,ui){var self=$(this).data("resizable"),o=self.options;var pr=self._proportionallyResizeElements,ista=pr.length&&(/textarea/i).test(pr[0].nodeName),soffseth=ista&&$.ui.hasScroll(pr[0],'left')?0:self.sizeDiff.height,soffsetw=ista?0:self.sizeDiff.width;var style={width:(self.size.width-soffsetw),height:(self.size.height-soffseth)},left=(parseInt(self.element.css('left'),10)+(self.position.left-self.originalPosition.left))||null,top=(parseInt(self.element.css('top'),10)+(self.position.top-self.originalPosition.top))||null;self.element.animate($.extend(style,top&&left?{top:top,left:left}:{}),{duration:o.animateDuration,easing:o.animateEasing,step:function(){var data={width:parseInt(self.element.css('width'),10),height:parseInt(self.element.css('height'),10),top:parseInt(self.element.css('top'),10),left:parseInt(self.element.css('left'),10)};if(pr&&pr.length)$(pr[0]).css({width:data.width,height:data.height});self._updateCache(data);self._propagate("resize",event);}});}});$.ui.plugin.add("resizable","containment",{start:function(event,ui){var self=$(this).data("resizable"),o=self.options,el=self.element;var oc=o.containment,ce=(oc instanceof $)?oc.get(0):(/parent/.test(oc))?el.parent().get(0):oc;if(!ce)return;self.containerElement=$(ce);if(/document/.test(oc)||oc==document){self.containerOffset={left:0,top:0};self.containerPosition={left:0,top:0};self.parentData={element:$(document),left:0,top:0,width:$(document).width(),height:$(document).height()||document.body.parentNode.scrollHeight};}
+else{var element=$(ce),p=[];$(["Top","Right","Left","Bottom"]).each(function(i,name){p[i]=num(element.css("padding"+name));});self.containerOffset=element.offset();self.containerPosition=element.position();self.containerSize={height:(element.innerHeight()-p[3]),width:(element.innerWidth()-p[1])};var co=self.containerOffset,ch=self.containerSize.height,cw=self.containerSize.width,width=($.ui.hasScroll(ce,"left")?ce.scrollWidth:cw),height=($.ui.hasScroll(ce)?ce.scrollHeight:ch);self.parentData={element:ce,left:co.left,top:co.top,width:width,height:height};}},resize:function(event,ui){var self=$(this).data("resizable"),o=self.options,ps=self.containerSize,co=self.containerOffset,cs=self.size,cp=self.position,pRatio=self._aspectRatio||event.shiftKey,cop={top:0,left:0},ce=self.containerElement;if(ce[0]!=document&&(/static/).test(ce.css('position')))cop=co;if(cp.left<(self._helper?co.left:0)){self.size.width=self.size.width+(self._helper?(self.position.left-co.left):(self.position.left-cop.left));if(pRatio)self.size.height=self.size.width/o.aspectRatio;self.position.left=o.helper?co.left:0;}
+if(cp.top<(self._helper?co.top:0)){self.size.height=self.size.height+(self._helper?(self.position.top-co.top):self.position.top);if(pRatio)self.size.width=self.size.height*o.aspectRatio;self.position.top=self._helper?co.top:0;}
+self.offset.left=self.parentData.left+self.position.left;self.offset.top=self.parentData.top+self.position.top;var woset=Math.abs((self._helper?self.offset.left-cop.left:(self.offset.left-cop.left))+self.sizeDiff.width),hoset=Math.abs((self._helper?self.offset.top-cop.top:(self.offset.top-co.top))+self.sizeDiff.height);var isParent=self.containerElement.get(0)==self.element.parent().get(0),isOffsetRelative=/relative|absolute/.test(self.containerElement.css('position'));if(isParent&&isOffsetRelative)woset-=self.parentData.left;if(woset+self.size.width>=self.parentData.width){self.size.width=self.parentData.width-woset;if(pRatio)self.size.height=self.size.width/self.aspectRatio;}
+if(hoset+self.size.height>=self.parentData.height){self.size.height=self.parentData.height-hoset;if(pRatio)self.size.width=self.size.height*self.aspectRatio;}},stop:function(event,ui){var self=$(this).data("resizable"),o=self.options,cp=self.position,co=self.containerOffset,cop=self.containerPosition,ce=self.containerElement;var helper=$(self.helper),ho=helper.offset(),w=helper.outerWidth()-self.sizeDiff.width,h=helper.outerHeight()-self.sizeDiff.height;if(self._helper&&!o.animate&&(/relative/).test(ce.css('position')))
+$(this).css({left:ho.left-cop.left-co.left,width:w,height:h});if(self._helper&&!o.animate&&(/static/).test(ce.css('position')))
+$(this).css({left:ho.left-cop.left-co.left,width:w,height:h});}});$.ui.plugin.add("resizable","ghost",{start:function(event,ui){var self=$(this).data("resizable"),o=self.options,cs=self.size;self.ghost=self.originalElement.clone();self.ghost.css({opacity:.25,display:'block',position:'relative',height:cs.height,width:cs.width,margin:0,left:0,top:0}).addClass('ui-resizable-ghost').addClass(typeof o.ghost=='string'?o.ghost:'');self.ghost.appendTo(self.helper);},resize:function(event,ui){var self=$(this).data("resizable"),o=self.options;if(self.ghost)self.ghost.css({position:'relative',height:self.size.height,width:self.size.width});},stop:function(event,ui){var self=$(this).data("resizable"),o=self.options;if(self.ghost&&self.helper)self.helper.get(0).removeChild(self.ghost.get(0));}});$.ui.plugin.add("resizable","grid",{resize:function(event,ui){var self=$(this).data("resizable"),o=self.options,cs=self.size,os=self.originalSize,op=self.originalPosition,a=self.axis,ratio=o._aspectRatio||event.shiftKey;o.grid=typeof o.grid=="number"?[o.grid,o.grid]:o.grid;var ox=Math.round((cs.width-os.width)/(o.grid[0]||1))*(o.grid[0]||1),oy=Math.round((cs.height-os.height)/(o.grid[1]||1))*(o.grid[1]||1);if(/^(se|s|e)$/.test(a)){self.size.width=os.width+ox;self.size.height=os.height+oy;}
+else if(/^(ne)$/.test(a)){self.size.width=os.width+ox;self.size.height=os.height+oy;self.position.top=op.top-oy;}
+else if(/^(sw)$/.test(a)){self.size.width=os.width+ox;self.size.height=os.height+oy;self.position.left=op.left-ox;}
+else{self.size.width=os.width+ox;self.size.height=os.height+oy;self.position.top=op.top-oy;self.position.left=op.left-ox;}}});var num=function(v){return parseInt(v,10)||0;};var isNumber=function(value){return!isNaN(parseInt(value,10));};})(jQuery);(function($){$.widget("ui.selectable",$.extend({},$.ui.mouse,{_init:function(){var self=this;this.element.addClass("ui-selectable");this.dragged=false;var selectees;this.refresh=function(){selectees=$(self.options.filter,self.element[0]);selectees.each(function(){var $this=$(this);var pos=$this.offset();$.data(this,"selectable-item",{element:this,$element:$this,left:pos.left,top:pos.top,right:pos.left+$this.outerWidth(),bottom:pos.top+$this.outerHeight(),startselected:false,selected:$this.hasClass('ui-selected'),selecting:$this.hasClass('ui-selecting'),unselecting:$this.hasClass('ui-unselecting')});});};this.refresh();this.selectees=selectees.addClass("ui-selectee");this._mouseInit();this.helper=$(document.createElement('div')).css({border:'1px dotted black'}).addClass("ui-selectable-helper");this.element.bind("mousedown.selectable",function(event){if(event.pageX>self.element[0].scrollWidth+self.element.offset().left){return;}
+var selectee=self._targetIsSelectable(event.target);if(!selectee){return;}
+var test=$(".ui-selected").length;if(!event.ctrlKey&&$(".ui-selected").length>1&&$(selectee).hasClass("ui-selected")){return(self._listenForMouseUp=1);}
+if(!event.ctrlKey){$(".ui-selected").each(function(){self._removeSelection(this,event);});}
+self._toggleSelection(selectee,event);event.preventDefault();}).bind("mouseup.selectable",function(event){if(self._listenForMouseUp){self._listenForMouseUp=0;var selectee=self._targetIsSelectable(event.target);if(!selectee){return;}
+self._addSelection(selectee,event);event.preventDefault();}})},_addSelection:function(selectee,event){$(selectee).addClass("ui-selecting");this._trigger("selecting",event,{selecting:selectee});$(selectee).removeClass('ui-selecting').addClass('ui-selected');this._trigger("selected",event,{selected:selectee});},_removeSelection:function(selected,event){$(selected).removeClass('ui-selected').addClass('ui-unselecting');this._trigger("unselecting",event,{unselecting:selected});$(selected).removeClass('ui-unselecting');this._trigger("unselected",event,{unselected:selected});},_toggleSelection:function(selectee,event){if($(selectee).hasClass("ui-selected")){this._removeSelection(selectee,event);}else{this._addSelection(selectee,event);}},_targetIsSelectable:function(target){var found=$(target).parents().andSelf().filter(".ui-selectee");return found.length&&found;},destroy:function(){this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();},_mouseStart:function(event){var self=this;if(event.pageX>this.element[0].scrollWidth+this.element.offset().left){this.opos=null;return;}
+this.opos=[event.pageX,event.pageY];if(this.options.disabled)
+return;var options=this.options,appendTo=$(options.appendTo),parentOffset=appendTo.css('position')=='static'?appendTo.offsetParent().offset():appendTo.offset();this.selectees=$(options.filter,this.element[0]);this._trigger("start",event);appendTo.append(this.helper);this.helper.css({"z-index":100,"position":"absolute","left":event.clientX-parentOffset.left,"top":event.clientY-parentOffset.top,"width":0,"height":0});if(options.autoRefresh){this.refresh();}
+this.selectees.filter('.ui-selected').each(function(){var selectee=$.data(this,"selectable-item");selectee.startselected=true;if(!event.metaKey){selectee.$element.removeClass('ui-selected');selectee.selected=false;selectee.$element.addClass('ui-unselecting');selectee.unselecting=true;self._trigger("unselecting",event,{unselecting:selectee.element});}});$(event.target).parents().andSelf().each(function(){var selectee=$.data(this,"selectable-item");if(selectee){selectee.$element.removeClass("ui-unselecting").addClass('ui-selecting');selectee.unselecting=false;selectee.selecting=true;selectee.selected=true;self._trigger("selecting",event,{selecting:selectee.element});return false;}});},_mouseDrag:function(event){var self=this;if(!this.opos){return;}
+this.dragged=true;if(this.options.disabled)
+return;var options=this.options;var x1=this.opos[0],y1=this.opos[1],x2=event.pageX,y2=event.pageY,appendTo=$(options.appendTo),parentOffset=appendTo.css('position')=='static'?appendTo.offsetParent().offset():appendTo.offset();if(x1>x2){var tmp=x2;x2=x1;x1=tmp;}
+if(y1>y2){var tmp=y2;y2=y1;y1=tmp;}
+this.helper.css({left:x1-parentOffset.left,top:y1-parentOffset.top,width:x2-x1,height:y2-y1});this.selectees.each(function(){var selectee=$.data(this,"selectable-item");if(!selectee||selectee.element==self.element[0])
+return;var hit=false;if(options.tolerance=='touch'){hit=(!(selectee.left>x2||selectee.right<x1||selectee.top>y2||selectee.bottom<y1));}else if(options.tolerance=='fit'){hit=(selectee.left>x1&&selectee.right<x2&&selectee.top>y1&&selectee.bottom<y2);}
+if(hit){if(selectee.selected){selectee.$element.removeClass('ui-selected');selectee.selected=false;}
+if(selectee.unselecting){selectee.$element.removeClass('ui-unselecting');selectee.unselecting=false;}
+if(!selectee.selecting){selectee.$element.addClass('ui-selecting');selectee.selecting=true;self._trigger("selecting",event,{selecting:selectee.element});}}else{if(selectee.selecting){if(event.metaKey&&selectee.startselected){selectee.$element.removeClass('ui-selecting');selectee.selecting=false;selectee.$element.addClass('ui-selected');selectee.selected=true;}else{selectee.$element.removeClass('ui-selecting');selectee.selecting=false;if(selectee.startselected){selectee.$element.addClass('ui-unselecting');selectee.unselecting=true;}
+self._trigger("unselecting",event,{unselecting:selectee.element});}}
+if(selectee.selected){if(!event.metaKey&&!selectee.startselected){selectee.$element.removeClass('ui-selected');selectee.selected=false;selectee.$element.addClass('ui-unselecting');selectee.unselecting=true;self._trigger("unselecting",event,{unselecting:selectee.element});}}}});return false;},_mouseStop:function(event){var self=this;if(!this.opos){return;}
+this.dragged=false;var options=this.options;$('.ui-unselecting',this.element[0]).each(function(){var selectee=$.data(this,"selectable-item");selectee.$element.removeClass('ui-unselecting');selectee.unselecting=false;selectee.startselected=false;self._trigger("unselected",event,{unselected:selectee.element});});$('.ui-selecting',this.element[0]).each(function(){var selectee=$.data(this,"selectable-item");selectee.$element.removeClass('ui-selecting').addClass('ui-selected');selectee.selecting=false;selectee.selected=true;selectee.startselected=true;self._trigger("selected",event,{selected:selectee.element});});this._trigger("stop",event);this.helper.remove();return false;}}));$.extend($.ui.selectable,{version:"1.7.2",defaults:{appendTo:'body',autoRefresh:true,cancel:":input,option",delay:0,distance:0,filter:'*',tolerance:'touch'}});})(jQuery);(function($){$.widget("ui.sortable",$.extend({},$.ui.mouse,{_init:function(){var o=this.options;this.containerCache={};this.element.addClass("ui-sortable");this.refresh();this.floating=this.items.length?(/left|right/).test(this.items[0].item.css('float')):false;this.offset=this.element.offset();this._mouseInit();},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var i=this.items.length-1;i>=0;i--)
+this.items[i].item.removeData("sortable-item");},_mouseCapture:function(event,overrideHandle){if(this.reverting){return false;}
+if(this.options.disabled||this.options.type=='static')return false;this._refreshItems(event);var currentItem=null,self=this,nodes=$(event.target).parents().each(function(){if($.data(this,'sortable-item')==self){currentItem=$(this);return false;}});if($.data(event.target,'sortable-item')==self)currentItem=$(event.target);if(!currentItem)return false;if(this.options.handle&&!overrideHandle){var validHandle=false;$(this.options.handle,currentItem).find("*").andSelf().each(function(){if(this==event.target)validHandle=true;});if(!validHandle)return false;}
+this.currentItem=currentItem;this._removeCurrentsFromItems();return true;},_mouseStart:function(event,overrideHandle,noActivation){var o=this.options,self=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(event);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");$.extend(this.offset,{click:{left:event.pageX-this.offset.left,top:event.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(event);this.originalPageX=event.pageX;this.originalPageY=event.pageY;if(o.cursorAt)
+this._adjustOffsetFromHelper(o.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};if(this.helper[0]!=this.currentItem[0]){this.currentItem.hide();}
+this._createPlaceholder();if(o.containment)
+this._setContainment();if(o.cursor){if($('body').css("cursor"))this._storedCursor=$('body').css("cursor");$('body').css("cursor",o.cursor);}
+if(o.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",o.opacity);}
+if(o.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",o.zIndex);}
+if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!='HTML')
+this.overflowOffset=this.scrollParent.offset();this._trigger("start",event,this._uiHash());if(!this._preserveHelperProportions)
+this._cacheHelperProportions();if(!noActivation){for(var i=this.containers.length-1;i>=0;i--){this.containers[i]._trigger("activate",event,self._uiHash(this));}}
+if($.ui.ddmanager)
+$.ui.ddmanager.current=this;if($.ui.ddmanager&&!o.dropBehaviour)
+$.ui.ddmanager.prepareOffsets(this,event);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(event);return true;},_mouseDrag:function(event){this.position=this._generatePosition(event);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs){this.lastPositionAbs=this.positionAbs;}
+if(this.options.scroll){var o=this.options,scrolled=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!='HTML'){if((this.overflowOffset.top+this.scrollParent[0].offsetHeight)-event.pageY<o.scrollSensitivity)
+this.scrollParent[0].scrollTop=scrolled=this.scrollParent[0].scrollTop+o.scrollSpeed;else if(event.pageY-this.overflowOffset.top<o.scrollSensitivity)
+this.scrollParent[0].scrollTop=scrolled=this.scrollParent[0].scrollTop-o.scrollSpeed;if((this.overflowOffset.left+this.scrollParent[0].offsetWidth)-event.pageX<o.scrollSensitivity)
+this.scrollParent[0].scrollLeft=scrolled=this.scrollParent[0].scrollLeft+o.scrollSpeed;else if(event.pageX-this.overflowOffset.left<o.scrollSensitivity)
+this.scrollParent[0].scrollLeft=scrolled=this.scrollParent[0].scrollLeft-o.scrollSpeed;}else{if(event.pageY-$(document).scrollTop()<o.scrollSensitivity)
+scrolled=$(document).scrollTop($(document).scrollTop()-o.scrollSpeed);else if($(window).height()-(event.pageY-$(document).scrollTop())<o.scrollSensitivity)
+scrolled=$(document).scrollTop($(document).scrollTop()+o.scrollSpeed);if(event.pageX-$(document).scrollLeft()<o.scrollSensitivity)
+scrolled=$(document).scrollLeft($(document).scrollLeft()-o.scrollSpeed);else if($(window).width()-(event.pageX-$(document).scrollLeft())<o.scrollSensitivity)
+scrolled=$(document).scrollLeft($(document).scrollLeft()+o.scrollSpeed);}
+if(scrolled!==false&&$.ui.ddmanager&&!o.dropBehaviour)
+$.ui.ddmanager.prepareOffsets(this,event);}
+this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+'px';if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+'px';for(var i=this.items.length-1;i>=0;i--){var item=this.items[i],itemElement=item.item[0],intersection=this._intersectsWithPointer(item);if(!intersection)continue;if(itemElement!=this.currentItem[0]&&this.placeholder[intersection==1?"next":"prev"]()[0]!=itemElement&&!$.ui.contains(this.placeholder[0],itemElement)&&(this.options.type=='semi-dynamic'?!$.ui.contains(this.element[0],itemElement):true)){this.direction=intersection==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(item)){this._rearrange(event,item);}else{break;}
+this._trigger("change",event,this._uiHash());break;}}
+this._contactContainers(event);if($.ui.ddmanager)$.ui.ddmanager.drag(this,event);this._trigger('sort',event,this._uiHash());this.lastPositionAbs=this.positionAbs;return false;},_mouseStop:function(event,noPropagation){if(!event)return;if($.ui.ddmanager&&!this.options.dropBehaviour)
+$.ui.ddmanager.drop(this,event);if(this.options.revert){var self=this;var cur=self.placeholder.offset();self.reverting=true;$(this.helper).animate({left:cur.left-this.offset.parent.left-self.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:cur.top-this.offset.parent.top-self.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){self._clear(event);});}else{this._clear(event,noPropagation);}
+return false;},cancel:function(){var self=this;if(this.dragging){this._mouseUp();if(this.options.helper=="original")
+this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");else
+this.currentItem.show();for(var i=this.containers.length-1;i>=0;i--){this.containers[i]._trigger("deactivate",null,self._uiHash(this));if(this.containers[i].containerCache.over){this.containers[i]._trigger("out",null,self._uiHash(this));this.containers[i].containerCache.over=0;}}}
+if(this.placeholder[0].parentNode)this.placeholder[0].parentNode.removeChild(this.placeholder[0]);if(this.options.helper!="original"&&this.helper&&this.helper[0].parentNode)this.helper.remove();$.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});if(this.domPosition.prev){$(this.domPosition.prev).after(this.currentItem);}else{$(this.domPosition.parent).prepend(this.currentItem);}
+return true;},serialize:function(o){var items=this._getItemsAsjQuery(o&&o.connected);var str=[];o=o||{};$(items).each(function(){var res=($(o.item||this).attr(o.attribute||'id')||'').match(o.expression||(/(.+)[-=_](.+)/));if(res)str.push((o.key||res[1]+'[]')+'='+(o.key&&o.expression?res[1]:res[2]));});return str.join('&');},toArray:function(o){var items=this._getItemsAsjQuery(o&&o.connected);var ret=[];o=o||{};items.each(function(){ret.push($(o.item||this).attr(o.attribute||'id')||'');});return ret;},_intersectsWith:function(item){var x1=this.positionAbs.left,x2=x1+this.helperProportions.width,y1=this.positionAbs.top,y2=y1+this.helperProportions.height;var l=item.left,r=l+item.width,t=item.top,b=t+item.height;var dyClick=this.offset.click.top,dxClick=this.offset.click.left;var isOverElement=(y1+dyClick)>t&&(y1+dyClick)<b&&(x1+dxClick)>l&&(x1+dxClick)<r;if(this.options.tolerance=="pointer"||this.options.forcePointerForContainers||(this.options.tolerance!="pointer"&&this.helperProportions[this.floating?'width':'height']>item[this.floating?'width':'height'])){return isOverElement;}else{return(l<x1+(this.helperProportions.width/2)&&x2-(this.helperProportions.width/2)<r&&t<y1+(this.helperProportions.height/2)&&y2-(this.helperProportions.height/2)<b);}},_intersectsWithPointer:function(item){var isOverElementHeight=$.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,item.top,item.height),isOverElementWidth=$.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,item.left,item.width),isOverElement=isOverElementHeight&&isOverElementWidth,verticalDirection=this._getDragVerticalDirection(),horizontalDirection=this._getDragHorizontalDirection();if(!isOverElement)
+return false;return this.floating?(((horizontalDirection&&horizontalDirection=="right")||verticalDirection=="down")?2:1):(verticalDirection&&(verticalDirection=="down"?2:1));},_intersectsWithSides:function(item){var isOverBottomHalf=$.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,item.top+(item.height/2),item.height),isOverRightHalf=$.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,item.left+(item.width/2),item.width),verticalDirection=this._getDragVerticalDirection(),horizontalDirection=this._getDragHorizontalDirection();if(this.floating&&horizontalDirection){return((horizontalDirection=="right"&&isOverRightHalf)||(horizontalDirection=="left"&&!isOverRightHalf));}else{return verticalDirection&&((verticalDirection=="down"&&isOverBottomHalf)||(verticalDirection=="up"&&!isOverBottomHalf));}},_getDragVerticalDirection:function(){var delta=this.positionAbs.top-this.lastPositionAbs.top;return delta!=0&&(delta>0?"down":"up");},_getDragHorizontalDirection:function(){var delta=this.positionAbs.left-this.lastPositionAbs.left;return delta!=0&&(delta>0?"right":"left");},refresh:function(event){this._refreshItems(event);this.refreshPositions();},_connectWith:function(){var options=this.options;return options.connectWith.constructor==String?[options.connectWith]:options.connectWith;},_getItemsAsjQuery:function(connected){var self=this;var items=[];var queries=[];var connectWith=this._connectWith();if(connectWith&&connected){for(var i=connectWith.length-1;i>=0;i--){var cur=$(connectWith[i]);for(var j=cur.length-1;j>=0;j--){var inst=$.data(cur[j],'sortable');if(inst&&inst!=this&&!inst.options.disabled){queries.push([$.isFunction(inst.options.items)?inst.options.items.call(inst.element):$(inst.options.items,inst.element).not(".ui-sortable-helper"),inst]);}};};}
+queries.push([$.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):$(this.options.items,this.element).not(".ui-sortable-helper"),this]);for(var i=queries.length-1;i>=0;i--){queries[i][0].each(function(){items.push(this);});};return $(items);},_removeCurrentsFromItems:function(){var list=this.currentItem.find(":data(sortable-item)");for(var i=0;i<this.items.length;i++){for(var j=0;j<list.length;j++){if(list[j]==this.items[i].item[0])
+this.items.splice(i,1);};};},_refreshItems:function(event){this.items=[];this.containers=[this];var items=this.items;var self=this;var queries=[[$.isFunction(this.options.items)?this.options.items.call(this.element[0],event,{item:this.currentItem}):$(this.options.items,this.element),this]];var connectWith=this._connectWith();if(connectWith){for(var i=connectWith.length-1;i>=0;i--){var cur=$(connectWith[i]);for(var j=cur.length-1;j>=0;j--){var inst=$.data(cur[j],'sortable');if(inst&&inst!=this&&!inst.options.disabled){queries.push([$.isFunction(inst.options.items)?inst.options.items.call(inst.element[0],event,{item:this.currentItem}):$(inst.options.items,inst.element),inst]);this.containers.push(inst);}};};}
+for(var i=queries.length-1;i>=0;i--){var targetData=queries[i][1];var _queries=queries[i][0];for(var j=0,queriesLength=_queries.length;j<queriesLength;j++){var item=$(_queries[j]);item.data('sortable-item',targetData);items.push({item:item,instance:targetData,width:0,height:0,left:0,top:0});};};},refreshPositions:function(fast){if(this.offsetParent&&this.helper){this.offset.parent=this._getParentOffset();}
+for(var i=this.items.length-1;i>=0;i--){var item=this.items[i];if(item.instance!=this.currentContainer&&this.currentContainer&&item.item[0]!=this.currentItem[0])
+continue;var t=this.options.toleranceElement?$(this.options.toleranceElement,item.item):item.item;if(!fast){item.width=t.outerWidth();item.height=t.outerHeight();}
+var p=t.offset();item.left=p.left;item.top=p.top;};if(this.options.custom&&this.options.custom.refreshContainers){this.options.custom.refreshContainers.call(this);}else{for(var i=this.containers.length-1;i>=0;i--){var p=this.containers[i].element.offset();this.containers[i].containerCache.left=p.left;this.containers[i].containerCache.top=p.top;this.containers[i].containerCache.width=this.containers[i].element.outerWidth();this.containers[i].containerCache.height=this.containers[i].element.outerHeight();};}},_createPlaceholder:function(that){var self=that||this,o=self.options;if(!o.placeholder||o.placeholder.constructor==String){var className=o.placeholder;o.placeholder={element:function(){var el=$(document.createElement(self.currentItem[0].nodeName)).addClass(className||self.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!className)
+el.style.visibility="hidden";return el;},update:function(container,p){if(className&&!o.forcePlaceholderSize)return;if(!p.height()){p.height(self.currentItem.innerHeight()-parseInt(self.currentItem.css('paddingTop')||0,10)-parseInt(self.currentItem.css('paddingBottom')||0,10));};if(!p.width()){p.width(self.currentItem.innerWidth()-parseInt(self.currentItem.css('paddingLeft')||0,10)-parseInt(self.currentItem.css('paddingRight')||0,10));};}};}
+self.placeholder=$(o.placeholder.element.call(self.element,self.currentItem));self.currentItem.after(self.placeholder);o.placeholder.update(self,self.placeholder);},_contactContainers:function(event){for(var i=this.containers.length-1;i>=0;i--){if(this._intersectsWith(this.containers[i].containerCache)){if(!this.containers[i].containerCache.over){if(this.currentContainer!=this.containers[i]){var dist=10000;var itemWithLeastDistance=null;var base=this.positionAbs[this.containers[i].floating?'left':'top'];for(var j=this.items.length-1;j>=0;j--){if(!$.ui.contains(this.containers[i].element[0],this.items[j].item[0]))continue;var cur=this.items[j][this.containers[i].floating?'left':'top'];if(Math.abs(cur-base)<dist){dist=Math.abs(cur-base);itemWithLeastDistance=this.items[j];}}
+if(!itemWithLeastDistance&&!this.options.dropOnEmpty)
+continue;this.currentContainer=this.containers[i];itemWithLeastDistance?this._rearrange(event,itemWithLeastDistance,null,true):this._rearrange(event,null,this.containers[i].element,true);this._trigger("change",event,this._uiHash());this.containers[i]._trigger("change",event,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);}
+this.containers[i]._trigger("over",event,this._uiHash(this));this.containers[i].containerCache.over=1;}}else{if(this.containers[i].containerCache.over){this.containers[i]._trigger("out",event,this._uiHash(this));this.containers[i].containerCache.over=0;}}};},_createHelper:function(event){var o=this.options;var helper=$.isFunction(o.helper)?$(o.helper.apply(this.element[0],[event,this.currentItem])):(o.helper=='clone'?this.currentItem.clone():this.currentItem);if(!helper.parents('body').length)
+$(o.appendTo!='parent'?o.appendTo:this.currentItem[0].parentNode)[0].appendChild(helper[0]);if(helper[0]==this.currentItem[0])
+this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(helper[0].style.width==''||o.forceHelperSize)helper.width(this.currentItem.width());if(helper[0].style.height==''||o.forceHelperSize)helper.height(this.currentItem.height());return helper;},_adjustOffsetFromHelper:function(obj){if(obj.left!=undefined)this.offset.click.left=obj.left+this.margins.left;if(obj.right!=undefined)this.offset.click.left=this.helperProportions.width-obj.right+this.margins.left;if(obj.top!=undefined)this.offset.click.top=obj.top+this.margins.top;if(obj.bottom!=undefined)this.offset.click.top=this.helperProportions.height-obj.bottom+this.margins.top;},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var po=this.offsetParent.offset();if(this.cssPosition=='absolute'&&this.scrollParent[0]!=document&&$.ui.contains(this.scrollParent[0],this.offsetParent[0])){po.left+=this.scrollParent.scrollLeft();po.top+=this.scrollParent.scrollTop();}
+if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=='html'&&$.browser.msie))
+po={top:0,left:0};return{top:po.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:po.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)};},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var p=this.currentItem.position();return{top:p.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:p.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()};}else{return{top:0,left:0};}},_cacheMargins:function(){this.margins={left:(parseInt(this.currentItem.css("marginLeft"),10)||0),top:(parseInt(this.currentItem.css("marginTop"),10)||0)};},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()};},_setContainment:function(){var o=this.options;if(o.containment=='parent')o.containment=this.helper[0].parentNode;if(o.containment=='document'||o.containment=='window')this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,$(o.containment=='document'?document:window).width()-this.helperProportions.width-this.margins.left,($(o.containment=='document'?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!(/^(document|window|parent)$/).test(o.containment)){var ce=$(o.containment)[0];var co=$(o.containment).offset();var over=($(ce).css("overflow")!='hidden');this.containment=[co.left+(parseInt($(ce).css("borderLeftWidth"),10)||0)+(parseInt($(ce).css("paddingLeft"),10)||0)-this.margins.left,co.top+(parseInt($(ce).css("borderTopWidth"),10)||0)+(parseInt($(ce).css("paddingTop"),10)||0)-this.margins.top,co.left+(over?Math.max(ce.scrollWidth,ce.offsetWidth):ce.offsetWidth)-(parseInt($(ce).css("borderLeftWidth"),10)||0)-(parseInt($(ce).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,co.top+(over?Math.max(ce.scrollHeight,ce.offsetHeight):ce.offsetHeight)-(parseInt($(ce).css("borderTopWidth"),10)||0)-(parseInt($(ce).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top];}},_convertPositionTo:function(d,pos){if(!pos)pos=this.position;var mod=d=="absolute"?1:-1;var o=this.options,scroll=this.cssPosition=='absolute'&&!(this.scrollParent[0]!=document&&$.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,scrollIsRootNode=(/(html|body)/i).test(scroll[0].tagName);return{top:(pos.top
++this.offset.relative.top*mod
++this.offset.parent.top*mod
+-($.browser.safari&&this.cssPosition=='fixed'?0:(this.cssPosition=='fixed'?-this.scrollParent.scrollTop():(scrollIsRootNode?0:scroll.scrollTop()))*mod)),left:(pos.left
++this.offset.relative.left*mod
++this.offset.parent.left*mod
+-($.browser.safari&&this.cssPosition=='fixed'?0:(this.cssPosition=='fixed'?-this.scrollParent.scrollLeft():scrollIsRootNode?0:scroll.scrollLeft())*mod))};},_generatePosition:function(event){var o=this.options,scroll=this.cssPosition=='absolute'&&!(this.scrollParent[0]!=document&&$.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,scrollIsRootNode=(/(html|body)/i).test(scroll[0].tagName);if(this.cssPosition=='relative'&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset();}
+var pageX=event.pageX;var pageY=event.pageY;if(this.originalPosition){if(this.containment){if(event.pageX-this.offset.click.left<this.containment[0])pageX=this.containment[0]+this.offset.click.left;if(event.pageY-this.offset.click.top<this.containment[1])pageY=this.containment[1]+this.offset.click.top;if(event.pageX-this.offset.click.left>this.containment[2])pageX=this.containment[2]+this.offset.click.left;if(event.pageY-this.offset.click.top>this.containment[3])pageY=this.containment[3]+this.offset.click.top;}
+if(o.grid){var top=this.originalPageY+Math.round((pageY-this.originalPageY)/o.grid[1])*o.grid[1];pageY=this.containment?(!(top-this.offset.click.top<this.containment[1]||top-this.offset.click.top>this.containment[3])?top:(!(top-this.offset.click.top<this.containment[1])?top-o.grid[1]:top+o.grid[1])):top;var left=this.originalPageX+Math.round((pageX-this.originalPageX)/o.grid[0])*o.grid[0];pageX=this.containment?(!(left-this.offset.click.left<this.containment[0]||left-this.offset.click.left>this.containment[2])?left:(!(left-this.offset.click.left<this.containment[0])?left-o.grid[0]:left+o.grid[0])):left;}}
+return{top:(pageY
+-this.offset.click.top
+-this.offset.relative.top
+-this.offset.parent.top
++($.browser.safari&&this.cssPosition=='fixed'?0:(this.cssPosition=='fixed'?-this.scrollParent.scrollTop():(scrollIsRootNode?0:scroll.scrollTop())))),left:(pageX
+-this.offset.click.left
+-this.offset.relative.left
+-this.offset.parent.left
++($.browser.safari&&this.cssPosition=='fixed'?0:(this.cssPosition=='fixed'?-this.scrollParent.scrollLeft():scrollIsRootNode?0:scroll.scrollLeft())))};},_rearrange:function(event,i,a,hardRefresh){a?a[0].appendChild(this.placeholder[0]):i.item[0].parentNode.insertBefore(this.placeholder[0],(this.direction=='down'?i.item[0]:i.item[0].nextSibling));this.counter=this.counter?++this.counter:1;var self=this,counter=this.counter;window.setTimeout(function(){if(counter==self.counter)self.refreshPositions(!hardRefresh);},0);},_clear:function(event,noPropagation){this.reverting=false;var delayedTriggers=[],self=this;if(!this._noFinalSort&&this.currentItem[0].parentNode)this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var i in this._storedCSS){if(this._storedCSS[i]=='auto'||this._storedCSS[i]=='static')this._storedCSS[i]='';}
+this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");}else{this.currentItem.show();}
+if(this.fromOutside&&!noPropagation)delayedTriggers.push(function(event){this._trigger("receive",event,this._uiHash(this.fromOutside));});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!noPropagation)delayedTriggers.push(function(event){this._trigger("update",event,this._uiHash());});if(!$.ui.contains(this.element[0],this.currentItem[0])){if(!noPropagation)delayedTriggers.push(function(event){this._trigger("remove",event,this._uiHash());});for(var i=this.containers.length-1;i>=0;i--){if($.ui.contains(this.containers[i].element[0],this.currentItem[0])&&!noPropagation){delayedTriggers.push((function(c){return function(event){c._trigger("receive",event,this._uiHash(this));};}).call(this,this.containers[i]));delayedTriggers.push((function(c){return function(event){c._trigger("update",event,this._uiHash(this));};}).call(this,this.containers[i]));}};};for(var i=this.containers.length-1;i>=0;i--){if(!noPropagation)delayedTriggers.push((function(c){return function(event){c._trigger("deactivate",event,this._uiHash(this));};}).call(this,this.containers[i]));if(this.containers[i].containerCache.over){delayedTriggers.push((function(c){return function(event){c._trigger("out",event,this._uiHash(this));};}).call(this,this.containers[i]));this.containers[i].containerCache.over=0;}}
+if(this._storedCursor)$('body').css("cursor",this._storedCursor);if(this._storedOpacity)this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=='auto'?'':this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!noPropagation){this._trigger("beforeStop",event,this._uiHash());for(var i=0;i<delayedTriggers.length;i++){delayedTriggers[i].call(this,event);};this._trigger("stop",event,this._uiHash());}
+return false;}
+if(!noPropagation)this._trigger("beforeStop",event,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);if(this.helper[0]!=this.currentItem[0])this.helper.remove();this.helper=null;if(!noPropagation){for(var i=0;i<delayedTriggers.length;i++){delayedTriggers[i].call(this,event);};this._trigger("stop",event,this._uiHash());}
+this.fromOutside=false;return true;},_trigger:function(){if($.widget.prototype._trigger.apply(this,arguments)===false){this.cancel();}},_uiHash:function(inst){var self=inst||this;return{helper:self.helper,placeholder:self.placeholder||$([]),position:self.position,absolutePosition:self.positionAbs,offset:self.positionAbs,item:self.currentItem,sender:inst?inst.element:null};}}));$.extend($.ui.sortable,{getter:"serialize toArray",version:"1.7.2",eventPrefix:"sort",defaults:{appendTo:"parent",axis:false,cancel:":input,option",connectWith:false,containment:false,cursor:'auto',cursorAt:false,delay:0,distance:1,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:'> *',opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1000}});})(jQuery);(function($){$.widget("ui.accordion",{_init:function(){var o=this.options,self=this;this.running=0;if(o.collapsible==$.ui.accordion.defaults.collapsible&&o.alwaysOpen!=$.ui.accordion.defaults.alwaysOpen){o.collapsible=!o.alwaysOpen;}
+if(o.navigation){var current=this.element.find("a").filter(o.navigationFilter);if(current.length){if(current.filter(o.header).length){this.active=current;}else{this.active=current.parent().parent().prev();current.addClass("ui-accordion-content-active");}}}
+this.element.addClass("ui-accordion ui-widget ui-helper-reset");if(this.element[0].nodeName=="UL"){this.element.children("li").addClass("ui-accordion-li-fix");}
+this.headers=this.element.find(o.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){$(this).addClass('ui-state-hover');}).bind("mouseleave.accordion",function(){$(this).removeClass('ui-state-hover');}).bind("focus.accordion",function(){$(this).addClass('ui-state-focus');}).bind("blur.accordion",function(){$(this).removeClass('ui-state-focus');});this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");this.active=this._findActive(this.active||o.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass('ui-accordion-content-active');$("<span/>").addClass("ui-icon "+o.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected);if($.browser.msie){this.element.find('a').css('zoom','1');}
+this.resize();this.element.attr('role','tablist');this.headers.attr('role','tab').bind('keydown',function(event){return self._keydown(event);}).next().attr('role','tabpanel');this.headers.not(this.active||"").attr('aria-expanded','false').attr("tabIndex","-1").next().hide();if(!this.active.length){this.headers.eq(0).attr('tabIndex','0');}else{this.active.attr('aria-expanded','true').attr('tabIndex','0');}
+if(!$.browser.safari)
+this.headers.find('a').attr('tabIndex','-1');if(o.event){this.headers.bind((o.event)+".accordion",function(event){return self._clickHandler.call(self,event,this);});}},destroy:function(){var o=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind('.accordion').removeData('accordion');this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");this.headers.find("a").removeAttr("tabindex");this.headers.children(".ui-icon").remove();var contents=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(o.autoHeight||o.fillHeight){contents.css("height","");}},_setData:function(key,value){if(key=='alwaysOpen'){key='collapsible';value=!value;}
+$.widget.prototype._setData.apply(this,arguments);},_keydown:function(event){var o=this.options,keyCode=$.ui.keyCode;if(o.disabled||event.altKey||event.ctrlKey)
+return;var length=this.headers.length;var currentIndex=this.headers.index(event.target);var toFocus=false;switch(event.keyCode){case keyCode.RIGHT:case keyCode.DOWN:toFocus=this.headers[(currentIndex+1)%length];break;case keyCode.LEFT:case keyCode.UP:toFocus=this.headers[(currentIndex-1+length)%length];break;case keyCode.SPACE:case keyCode.ENTER:return this._clickHandler({target:event.target},event.target);}
+if(toFocus){$(event.target).attr('tabIndex','-1');$(toFocus).attr('tabIndex','0');toFocus.focus();return false;}
+return true;},resize:function(){var o=this.options,maxHeight;if(o.fillSpace){if($.browser.msie){var defOverflow=this.element.parent().css('overflow');this.element.parent().css('overflow','hidden');}
+maxHeight=this.element.parent().height();if($.browser.msie){this.element.parent().css('overflow',defOverflow);}
+this.headers.each(function(){maxHeight-=$(this).outerHeight();});var maxPadding=0;this.headers.next().each(function(){maxPadding=Math.max(maxPadding,$(this).innerHeight()-$(this).height());}).height(Math.max(0,maxHeight-maxPadding)).css('overflow','auto');}else if(o.autoHeight){maxHeight=0;this.headers.next().each(function(){maxHeight=Math.max(maxHeight,$(this).outerHeight());}).height(maxHeight);}},activate:function(index){var active=this._findActive(index)[0];this._clickHandler({target:active},active);},_findActive:function(selector){return selector?typeof selector=="number"?this.headers.filter(":eq("+selector+")"):this.headers.not(this.headers.not(selector)):selector===false?$([]):this.headers.filter(":eq(0)");},_clickHandler:function(event,target){var o=this.options;if(o.disabled)return false;if(!event.target&&o.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);this.active.next().addClass('ui-accordion-content-active');var toHide=this.active.next(),data={options:o,newHeader:$([]),oldHeader:o.active,newContent:$([]),oldContent:toHide},toShow=(this.active=$([]));this._toggle(toShow,toHide,data);return false;}
+var clicked=$(event.currentTarget||target);var clickedIsActive=clicked[0]==this.active[0];if(this.running||(!o.collapsible&&clickedIsActive)){return false;}
+this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);this.active.next().addClass('ui-accordion-content-active');if(!clickedIsActive){clicked.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(o.icons.header).addClass(o.icons.headerSelected);clicked.next().addClass('ui-accordion-content-active');}
+var toShow=clicked.next(),toHide=this.active.next(),data={options:o,newHeader:clickedIsActive&&o.collapsible?$([]):clicked,oldHeader:this.active,newContent:clickedIsActive&&o.collapsible?$([]):toShow.find('> *'),oldContent:toHide.find('> *')},down=this.headers.index(this.active[0])>this.headers.index(clicked[0]);this.active=clickedIsActive?$([]):clicked;this._toggle(toShow,toHide,data,clickedIsActive,down);return false;},_toggle:function(toShow,toHide,data,clickedIsActive,down){var o=this.options,self=this;this.toShow=toShow;this.toHide=toHide;this.data=data;var complete=function(){if(!self)return;return self._completed.apply(self,arguments);};this._trigger("changestart",null,this.data);this.running=toHide.size()===0?toShow.size():toHide.size();if(o.animated){var animOptions={};if(o.collapsible&&clickedIsActive){animOptions={toShow:$([]),toHide:toHide,complete:complete,down:down,autoHeight:o.autoHeight||o.fillSpace};}else{animOptions={toShow:toShow,toHide:toHide,complete:complete,down:down,autoHeight:o.autoHeight||o.fillSpace};}
+if(!o.proxied){o.proxied=o.animated;}
+if(!o.proxiedDuration){o.proxiedDuration=o.duration;}
+o.animated=$.isFunction(o.proxied)?o.proxied(animOptions):o.proxied;o.duration=$.isFunction(o.proxiedDuration)?o.proxiedDuration(animOptions):o.proxiedDuration;var animations=$.ui.accordion.animations,duration=o.duration,easing=o.animated;if(!animations[easing]){animations[easing]=function(options){this.slide(options,{easing:easing,duration:duration||700});};}
+animations[easing](animOptions);}else{if(o.collapsible&&clickedIsActive){toShow.toggle();}else{toHide.hide();toShow.show();}
+complete(true);}
+toHide.prev().attr('aria-expanded','false').attr("tabIndex","-1").blur();toShow.prev().attr('aria-expanded','true').attr("tabIndex","0").focus();},_completed:function(cancel){var o=this.options;this.running=cancel?0:--this.running;if(this.running)return;if(o.clearStyle){this.toShow.add(this.toHide).css({height:"",overflow:""});}
+this._trigger('change',null,this.data);}});$.extend($.ui.accordion,{version:"1.7.2",defaults:{active:null,alwaysOpen:true,animated:'slide',autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase();}},animations:{slide:function(options,additions){options=$.extend({easing:"swing",duration:300},options,additions);if(!options.toHide.size()){options.toShow.animate({height:"show"},options);return;}
+if(!options.toShow.size()){options.toHide.animate({height:"hide"},options);return;}
+var overflow=options.toShow.css('overflow'),percentDone,showProps={},hideProps={},fxAttrs=["height","paddingTop","paddingBottom"],originalWidth;var s=options.toShow;originalWidth=s[0].style.width;s.width(parseInt(s.parent().width(),10)-parseInt(s.css("paddingLeft"),10)-parseInt(s.css("paddingRight"),10)-(parseInt(s.css("borderLeftWidth"),10)||0)-(parseInt(s.css("borderRightWidth"),10)||0));$.each(fxAttrs,function(i,prop){hideProps[prop]='hide';var parts=(''+$.css(options.toShow[0],prop)).match(/^([\d+-.]+)(.*)$/);showProps[prop]={value:parts[1],unit:parts[2]||'px'};});options.toShow.css({height:0,overflow:'hidden'}).show();options.toHide.filter(":hidden").each(options.complete).end().filter(":visible").animate(hideProps,{step:function(now,settings){if(settings.prop=='height'){percentDone=(settings.now-settings.start)/(settings.end-settings.start);}
+options.toShow[0].style[settings.prop]=(percentDone*showProps[settings.prop].value)+showProps[settings.prop].unit;},duration:options.duration,easing:options.easing,complete:function(){if(!options.autoHeight){options.toShow.css("height","");}
+options.toShow.css("width",originalWidth);options.toShow.css({overflow:overflow});options.complete();}});},bounceslide:function(options){this.slide(options,{easing:options.down?"easeOutBounce":"swing",duration:options.down?1000:200});},easeslide:function(options){this.slide(options,{easing:"easeinout",duration:700});}}});})(jQuery);(function($){var setDataSwitch={dragStart:"start.draggable",drag:"drag.draggable",dragStop:"stop.draggable",maxHeight:"maxHeight.resizable",minHeight:"minHeight.resizable",maxWidth:"maxWidth.resizable",minWidth:"minWidth.resizable",resizeStart:"start.resizable",resize:"drag.resizable",resizeStop:"stop.resizable"},uiDialogClasses='ui-dialog '+'ui-widget '+'ui-widget-content '+'ui-corner-all ';$.widget("ui.dialog",{_init:function(){this.originalTitle=this.element.attr('title');var self=this,options=this.options,title=options.title||this.originalTitle||'&nbsp;',titleId=$.ui.dialog.getTitleId(this.element),uiDialog=(this.uiDialog=$('<div/>')).appendTo(document.body).hide().addClass(uiDialogClasses+options.dialogClass).css({position:'absolute',overflow:'hidden',zIndex:options.zIndex}).attr('tabIndex',-1).css('outline',0).keydown(function(event){(options.closeOnEscape&&event.keyCode&&event.keyCode==$.ui.keyCode.ESCAPE&&self.close(event));}).attr({role:'dialog','aria-labelledby':titleId}).mousedown(function(event){self.moveToTop(false,event);}),uiDialogContent=this.element.show().removeAttr('title').addClass('ui-dialog-content '+'ui-widget-content').appendTo(uiDialog),uiDialogTitlebar=(this.uiDialogTitlebar=$('<div></div>')).addClass('ui-dialog-titlebar '+'ui-widget-header '+'ui-corner-all '+'ui-helper-clearfix').prependTo(uiDialog),uiDialogTitlebarClose=$('<a href="#"/>').addClass('ui-dialog-titlebar-close '+'ui-corner-all').attr('role','button').hover(function(){uiDialogTitlebarClose.addClass('ui-state-hover');},function(){uiDialogTitlebarClose.removeClass('ui-state-hover');}).focus(function(){uiDialogTitlebarClose.addClass('ui-state-focus');}).blur(function(){uiDialogTitlebarClose.removeClass('ui-state-focus');}).mousedown(function(ev){ev.stopPropagation();}).click(function(event){self.close(event);return false;}).appendTo(uiDialogTitlebar),uiDialogTitlebarCloseText=(this.uiDialogTitlebarCloseText=$('<span/>')).addClass('ui-icon '+'ui-icon-closethick').text(options.closeText).appendTo(uiDialogTitlebarClose),uiDialogTitle=$('<span/>').addClass('ui-dialog-title').attr('id',titleId).html(title).prependTo(uiDialogTitlebar);uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();(options.draggable&&$.fn.draggable&&this._makeDraggable());(options.resizable&&$.fn.resizable&&this._makeResizable());this._createButtons(options.buttons);this._isOpen=false;(options.bgiframe&&$.fn.bgiframe&&uiDialog.bgiframe());(options.autoOpen&&this.open());},destroy:function(){(this.overlay&&this.overlay.destroy());this.uiDialog.hide();this.element.unbind('.dialog').removeData('dialog').removeClass('ui-dialog-content ui-widget-content').hide().appendTo('body');this.uiDialog.remove();(this.originalTitle&&this.element.attr('title',this.originalTitle));},close:function(event){var self=this;if(false===self._trigger('beforeclose',event)){return;}
+(self.overlay&&self.overlay.destroy());self.uiDialog.unbind('keypress.ui-dialog');(self.options.hide?self.uiDialog.hide(self.options.hide,function(){self._trigger('close',event);}):self.uiDialog.hide()&&self._trigger('close',event));$.ui.dialog.overlay.resize();self._isOpen=false;if(self.options.modal){var maxZ=0;$('.ui-dialog').each(function(){if(this!=self.uiDialog[0]){maxZ=Math.max(maxZ,$(this).css('z-index'));}});$.ui.dialog.maxZ=maxZ;}},isOpen:function(){return this._isOpen;},moveToTop:function(force,event){if((this.options.modal&&!force)||(!this.options.stack&&!this.options.modal)){return this._trigger('focus',event);}
+if(this.options.zIndex>$.ui.dialog.maxZ){$.ui.dialog.maxZ=this.options.zIndex;}
+(this.overlay&&this.overlay.$el.css('z-index',$.ui.dialog.overlay.maxZ=++$.ui.dialog.maxZ));var saveScroll={scrollTop:this.element.attr('scrollTop'),scrollLeft:this.element.attr('scrollLeft')};this.uiDialog.css('z-index',++$.ui.dialog.maxZ);this.element.attr(saveScroll);this._trigger('focus',event);},open:function(){if(this._isOpen){return;}
+var options=this.options,uiDialog=this.uiDialog;this.overlay=options.modal?new $.ui.dialog.overlay(this):null;(uiDialog.next().length&&uiDialog.appendTo('body'));this._size();this._position(options.position);uiDialog.show(options.show);this.moveToTop(true);(options.modal&&uiDialog.bind('keypress.ui-dialog',function(event){if(event.keyCode!=$.ui.keyCode.TAB){return;}
+var tabbables=$(':tabbable',this),first=tabbables.filter(':first')[0],last=tabbables.filter(':last')[0];if(event.target==last&&!event.shiftKey){setTimeout(function(){first.focus();},1);}else if(event.target==first&&event.shiftKey){setTimeout(function(){last.focus();},1);}}));$([]).add(uiDialog.find('.ui-dialog-content :tabbable:first')).add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first')).add(uiDialog).filter(':first').focus();this._trigger('open');this._isOpen=true;},_createButtons:function(buttons){var self=this,hasButtons=false,uiDialogButtonPane=$('<div></div>').addClass('ui-dialog-buttonpane '+'ui-widget-content '+'ui-helper-clearfix');this.uiDialog.find('.ui-dialog-buttonpane').remove();(typeof buttons=='object'&&buttons!==null&&$.each(buttons,function(){return!(hasButtons=true);}));if(hasButtons){$.each(buttons,function(name,fn){$('<button type="button"></button>').addClass('ui-state-default '+'ui-corner-all').text(name).click(function(){fn.apply(self.element[0],arguments);}).hover(function(){$(this).addClass('ui-state-hover');},function(){$(this).removeClass('ui-state-hover');}).focus(function(){$(this).addClass('ui-state-focus');}).blur(function(){$(this).removeClass('ui-state-focus');}).appendTo(uiDialogButtonPane);});uiDialogButtonPane.appendTo(this.uiDialog);}},_makeDraggable:function(){var self=this,options=this.options,heightBeforeDrag;this.uiDialog.draggable({cancel:'.ui-dialog-content',handle:'.ui-dialog-titlebar',containment:'document',start:function(){heightBeforeDrag=options.height;$(this).height($(this).height()).addClass("ui-dialog-dragging");(options.dragStart&&options.dragStart.apply(self.element[0],arguments));},drag:function(){(options.drag&&options.drag.apply(self.element[0],arguments));},stop:function(){$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);(options.dragStop&&options.dragStop.apply(self.element[0],arguments));$.ui.dialog.overlay.resize();}});},_makeResizable:function(handles){handles=(handles===undefined?this.options.resizable:handles);var self=this,options=this.options,resizeHandles=typeof handles=='string'?handles:'n,e,s,w,se,sw,ne,nw';this.uiDialog.resizable({cancel:'.ui-dialog-content',alsoResize:this.element,maxWidth:options.maxWidth,maxHeight:options.maxHeight,minWidth:options.minWidth,minHeight:options.minHeight,start:function(){$(this).addClass("ui-dialog-resizing");(options.resizeStart&&options.resizeStart.apply(self.element[0],arguments));},resize:function(){(options.resize&&options.resize.apply(self.element[0],arguments));},handles:resizeHandles,stop:function(){$(this).removeClass("ui-dialog-resizing");options.height=$(this).height();options.width=$(this).width();(options.resizeStop&&options.resizeStop.apply(self.element[0],arguments));$.ui.dialog.overlay.resize();}}).find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');},_position:function(pos){var wnd=$(window),doc=$(document),pTop=doc.scrollTop(),pLeft=doc.scrollLeft(),minTop=pTop;if($.inArray(pos,['center','top','right','bottom','left'])>=0){pos=[pos=='right'||pos=='left'?pos:'center',pos=='top'||pos=='bottom'?pos:'middle'];}
+if(pos.constructor!=Array){pos=['center','middle'];}
+if(pos[0].constructor==Number){pLeft+=pos[0];}else{switch(pos[0]){case'left':pLeft+=0;break;case'right':pLeft+=wnd.width()-this.uiDialog.outerWidth();break;default:case'center':pLeft+=(wnd.width()-this.uiDialog.outerWidth())/2;}}
+if(pos[1].constructor==Number){pTop+=pos[1];}else{switch(pos[1]){case'top':pTop+=0;break;case'bottom':pTop+=wnd.height()-this.uiDialog.outerHeight();break;default:case'middle':pTop+=(wnd.height()-this.uiDialog.outerHeight())/2;}}
+pTop=Math.max(pTop,minTop);this.uiDialog.css({top:pTop,left:pLeft});},_setData:function(key,value){(setDataSwitch[key]&&this.uiDialog.data(setDataSwitch[key],value));switch(key){case"buttons":this._createButtons(value);break;case"closeText":this.uiDialogTitlebarCloseText.text(value);break;case"dialogClass":this.uiDialog.removeClass(this.options.dialogClass).addClass(uiDialogClasses+value);break;case"draggable":(value?this._makeDraggable():this.uiDialog.draggable('destroy'));break;case"height":this.uiDialog.height(value);break;case"position":this._position(value);break;case"resizable":var uiDialog=this.uiDialog,isResizable=this.uiDialog.is(':data(resizable)');(isResizable&&!value&&uiDialog.resizable('destroy'));(isResizable&&typeof value=='string'&&uiDialog.resizable('option','handles',value));(isResizable||this._makeResizable(value));break;case"title":$(".ui-dialog-title",this.uiDialogTitlebar).html(value||'&nbsp;');break;case"width":this.uiDialog.width(value);break;}
+$.widget.prototype._setData.apply(this,arguments);},_size:function(){var options=this.options;this.element.css({height:0,minHeight:0,width:'auto'});var nonContentHeight=this.uiDialog.css({height:'auto',width:options.width}).height();this.element.css({minHeight:Math.max(options.minHeight-nonContentHeight,0),height:options.height=='auto'?'auto':Math.max(options.height-nonContentHeight,0)});}});$.extend($.ui.dialog,{version:"1.7.2",defaults:{autoOpen:true,bgiframe:false,buttons:{},closeOnEscape:true,closeText:'close',dialogClass:'',draggable:true,hide:null,height:'auto',maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:'center',resizable:true,show:null,stack:true,title:'',width:300,zIndex:1000},getter:'isOpen',uuid:0,maxZ:0,getTitleId:function($el){return'ui-dialog-title-'+($el.attr('id')||++this.uuid);},overlay:function(dialog){this.$el=$.ui.dialog.overlay.create(dialog);}});$.extend($.ui.dialog.overlay,{instances:[],maxZ:0,events:$.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),function(event){return event+'.dialog-overlay';}).join(' '),create:function(dialog){if(this.instances.length===0){setTimeout(function(){if($.ui.dialog.overlay.instances.length){$(document).bind($.ui.dialog.overlay.events,function(event){var dialogZ=$(event.target).parents('.ui-dialog').css('zIndex')||0;return(dialogZ>$.ui.dialog.overlay.maxZ);});}},1);$(document).bind('keydown.dialog-overlay',function(event){(dialog.options.closeOnEscape&&event.keyCode&&event.keyCode==$.ui.keyCode.ESCAPE&&dialog.close(event));});$(window).bind('resize.dialog-overlay',$.ui.dialog.overlay.resize);}
+var $el=$('<div></div>').appendTo(document.body).addClass('ui-widget-overlay').css({width:this.width(),height:this.height()});(dialog.options.bgiframe&&$.fn.bgiframe&&$el.bgiframe());this.instances.push($el);return $el;},destroy:function($el){this.instances.splice($.inArray(this.instances,$el),1);if(this.instances.length===0){$([document,window]).unbind('.dialog-overlay');}
+$el.remove();var maxZ=0;$.each(this.instances,function(){maxZ=Math.max(maxZ,this.css('z-index'));});this.maxZ=maxZ;},height:function(){if($.browser.msie&&$.browser.version<7){var scrollHeight=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);var offsetHeight=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);if(scrollHeight<offsetHeight){return $(window).height()+'px';}else{return scrollHeight+'px';}}else{return $(document).height()+'px';}},width:function(){if($.browser.msie&&$.browser.version<7){var scrollWidth=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);var offsetWidth=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);if(scrollWidth<offsetWidth){return $(window).width()+'px';}else{return scrollWidth+'px';}}else{return $(document).width()+'px';}},resize:function(){var $overlays=$([]);$.each($.ui.dialog.overlay.instances,function(){$overlays=$overlays.add(this);});$overlays.css({width:0,height:0}).css({width:$.ui.dialog.overlay.width(),height:$.ui.dialog.overlay.height()});}});$.extend($.ui.dialog.overlay.prototype,{destroy:function(){$.ui.dialog.overlay.destroy(this.$el);}});})(jQuery);(function($){$.widget("ui.tabs",{_init:function(){if(this.options.deselectable!==undefined){this.options.collapsible=this.options.deselectable;}
+this._tabify(true);},_setData:function(key,value){if(key=='selected'){if(this.options.collapsible&&value==this.options.selected){return;}
+this.select(value);}
+else{this.options[key]=value;if(key=='deselectable'){this.options.collapsible=value;}
+this._tabify();}},_tabId:function(a){return a.title&&a.title.replace(/\s/g,'_').replace(/[^A-Za-z0-9\-_:\.]/g,'')||this.options.idPrefix+$.data(a);},_sanitizeSelector:function(hash){return hash.replace(/:/g,'\\:');},_cookie:function(){var cookie=this.cookie||(this.cookie=this.options.cookie.name||'ui-tabs-'+$.data(this.list[0]));return $.cookie.apply(null,[cookie].concat($.makeArray(arguments)));},_ui:function(tab,panel){return{tab:tab,panel:panel,index:this.anchors.index(tab)};},_cleanup:function(){this.lis.filter('.ui-state-processing').removeClass('ui-state-processing').find('span:data(label.tabs)').each(function(){var el=$(this);el.html(el.data('label.tabs')).removeData('label.tabs');});},_tabify:function(init){this.list=this.element.children('ul:first');this.lis=$('li:has(a[href])',this.list);this.anchors=this.lis.map(function(){return $('a',this)[0];});this.panels=$([]);var self=this,o=this.options;var fragmentId=/^#.+/;this.anchors.each(function(i,a){var href=$(a).attr('href');var hrefBase=href.split('#')[0],baseEl;if(hrefBase&&(hrefBase===location.toString().split('#')[0]||(baseEl=$('base')[0])&&hrefBase===baseEl.href)){href=a.hash;a.href=href;}
+if(fragmentId.test(href)){self.panels=self.panels.add(self._sanitizeSelector(href));}
+else if(href!='#'){$.data(a,'href.tabs',href);$.data(a,'load.tabs',href.replace(/#.*$/,''));var id=self._tabId(a);a.href='#'+id;var $panel=$('#'+id);if(!$panel.length){$panel=$(o.panelTemplate).attr('id',id).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom').insertAfter(self.panels[i-1]||self.list);$panel.data('destroy.tabs',true);}
+self.panels=self.panels.add($panel);}
+else{o.disabled.push(i);}});if(init){this.element.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all');this.list.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');this.lis.addClass('ui-state-default ui-corner-top');this.panels.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom');if(o.selected===undefined){if(location.hash){this.anchors.each(function(i,a){if(a.hash==location.hash){o.selected=i;return false;}});}
+if(typeof o.selected!='number'&&o.cookie){o.selected=parseInt(self._cookie(),10);}
+if(typeof o.selected!='number'&&this.lis.filter('.ui-tabs-selected').length){o.selected=this.lis.index(this.lis.filter('.ui-tabs-selected'));}
+o.selected=o.selected||0;}
+else if(o.selected===null){o.selected=-1;}
+o.selected=((o.selected>=0&&this.anchors[o.selected])||o.selected<0)?o.selected:0;o.disabled=$.unique(o.disabled.concat($.map(this.lis.filter('.ui-state-disabled'),function(n,i){return self.lis.index(n);}))).sort();if($.inArray(o.selected,o.disabled)!=-1){o.disabled.splice($.inArray(o.selected,o.disabled),1);}
+this.panels.addClass('ui-tabs-hide');this.lis.removeClass('ui-tabs-selected ui-state-active');if(o.selected>=0&&this.anchors.length){this.panels.eq(o.selected).removeClass('ui-tabs-hide');this.lis.eq(o.selected).addClass('ui-tabs-selected ui-state-active');self.element.queue("tabs",function(){self._trigger('show',null,self._ui(self.anchors[o.selected],self.panels[o.selected]));});this.load(o.selected);}
+$(window).bind('unload',function(){self.lis.add(self.anchors).unbind('.tabs');self.lis=self.anchors=self.panels=null;});}
+else{o.selected=this.lis.index(this.lis.filter('.ui-tabs-selected'));}
+this.element[o.collapsible?'addClass':'removeClass']('ui-tabs-collapsible');if(o.cookie){this._cookie(o.selected,o.cookie);}
+for(var i=0,li;(li=this.lis[i]);i++){$(li)[$.inArray(i,o.disabled)!=-1&&!$(li).hasClass('ui-tabs-selected')?'addClass':'removeClass']('ui-state-disabled');}
+if(o.cache===false){this.anchors.removeData('cache.tabs');}
+this.lis.add(this.anchors).unbind('.tabs');if(o.event!='mouseover'){var addState=function(state,el){if(el.is(':not(.ui-state-disabled)')){el.addClass('ui-state-'+state);}};var removeState=function(state,el){el.removeClass('ui-state-'+state);};this.lis.bind('mouseover.tabs',function(){addState('hover',$(this));});this.lis.bind('mouseout.tabs',function(){removeState('hover',$(this));});this.anchors.bind('focus.tabs',function(){addState('focus',$(this).closest('li'));});this.anchors.bind('blur.tabs',function(){removeState('focus',$(this).closest('li'));});}
+var hideFx,showFx;if(o.fx){if($.isArray(o.fx)){hideFx=o.fx[0];showFx=o.fx[1];}
+else{hideFx=showFx=o.fx;}}
+function resetStyle($el,fx){$el.css({display:''});if($.browser.msie&&fx.opacity){$el[0].style.removeAttribute('filter');}}
+var showTab=showFx?function(clicked,$show){$(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');$show.hide().removeClass('ui-tabs-hide').animate(showFx,showFx.duration||'normal',function(){resetStyle($show,showFx);self._trigger('show',null,self._ui(clicked,$show[0]));});}:function(clicked,$show){$(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');$show.removeClass('ui-tabs-hide');self._trigger('show',null,self._ui(clicked,$show[0]));};var hideTab=hideFx?function(clicked,$hide){$hide.animate(hideFx,hideFx.duration||'normal',function(){self.lis.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default');$hide.addClass('ui-tabs-hide');resetStyle($hide,hideFx);self.element.dequeue("tabs");});}:function(clicked,$hide,$show){self.lis.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default');$hide.addClass('ui-tabs-hide');self.element.dequeue("tabs");};this.anchors.bind(o.event+'.tabs',function(){var el=this,$li=$(this).closest('li'),$hide=self.panels.filter(':not(.ui-tabs-hide)'),$show=$(self._sanitizeSelector(this.hash));if(($li.hasClass('ui-tabs-selected')&&!o.collapsible)||$li.hasClass('ui-state-disabled')||$li.hasClass('ui-state-processing')||self._trigger('select',null,self._ui(this,$show[0]))===false){this.blur();return false;}
+o.selected=self.anchors.index(this);self.abort();if(o.collapsible){if($li.hasClass('ui-tabs-selected')){o.selected=-1;if(o.cookie){self._cookie(o.selected,o.cookie);}
+self.element.queue("tabs",function(){hideTab(el,$hide);}).dequeue("tabs");this.blur();return false;}
+else if(!$hide.length){if(o.cookie){self._cookie(o.selected,o.cookie);}
+self.element.queue("tabs",function(){showTab(el,$show);});self.load(self.anchors.index(this));this.blur();return false;}}
+if(o.cookie){self._cookie(o.selected,o.cookie);}
+if($show.length){if($hide.length){self.element.queue("tabs",function(){hideTab(el,$hide);});}
+self.element.queue("tabs",function(){showTab(el,$show);});self.load(self.anchors.index(this));}
+else{throw'jQuery UI Tabs: Mismatching fragment identifier.';}
+if($.browser.msie){this.blur();}});this.anchors.bind('click.tabs',function(){return false;});},destroy:function(){var o=this.options;this.abort();this.element.unbind('.tabs').removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible').removeData('tabs');this.list.removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');this.anchors.each(function(){var href=$.data(this,'href.tabs');if(href){this.href=href;}
+var $this=$(this).unbind('.tabs');$.each(['href','load','cache'],function(i,prefix){$this.removeData(prefix+'.tabs');});});this.lis.unbind('.tabs').add(this.panels).each(function(){if($.data(this,'destroy.tabs')){$(this).remove();}
+else{$(this).removeClass(['ui-state-default','ui-corner-top','ui-tabs-selected','ui-state-active','ui-state-hover','ui-state-focus','ui-state-disabled','ui-tabs-panel','ui-widget-content','ui-corner-bottom','ui-tabs-hide'].join(' '));}});if(o.cookie){this._cookie(null,o.cookie);}},add:function(url,label,index){if(index===undefined){index=this.anchors.length;}
+var self=this,o=this.options,$li=$(o.tabTemplate.replace(/#\{href\}/g,url).replace(/#\{label\}/g,label)),id=!url.indexOf('#')?url.replace('#',''):this._tabId($('a',$li)[0]);$li.addClass('ui-state-default ui-corner-top').data('destroy.tabs',true);var $panel=$('#'+id);if(!$panel.length){$panel=$(o.panelTemplate).attr('id',id).data('destroy.tabs',true);}
+$panel.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide');if(index>=this.lis.length){$li.appendTo(this.list);$panel.appendTo(this.list[0].parentNode);}
+else{$li.insertBefore(this.lis[index]);$panel.insertBefore(this.panels[index]);}
+o.disabled=$.map(o.disabled,function(n,i){return n>=index?++n:n;});this._tabify();if(this.anchors.length==1){$li.addClass('ui-tabs-selected ui-state-active');$panel.removeClass('ui-tabs-hide');this.element.queue("tabs",function(){self._trigger('show',null,self._ui(self.anchors[0],self.panels[0]));});this.load(0);}
+this._trigger('add',null,this._ui(this.anchors[index],this.panels[index]));},remove:function(index){var o=this.options,$li=this.lis.eq(index).remove(),$panel=this.panels.eq(index).remove();if($li.hasClass('ui-tabs-selected')&&this.anchors.length>1){this.select(index+(index+1<this.anchors.length?1:-1));}
+o.disabled=$.map($.grep(o.disabled,function(n,i){return n!=index;}),function(n,i){return n>=index?--n:n;});this._tabify();this._trigger('remove',null,this._ui($li.find('a')[0],$panel[0]));},enable:function(index){var o=this.options;if($.inArray(index,o.disabled)==-1){return;}
+this.lis.eq(index).removeClass('ui-state-disabled');o.disabled=$.grep(o.disabled,function(n,i){return n!=index;});this._trigger('enable',null,this._ui(this.anchors[index],this.panels[index]));},disable:function(index){var self=this,o=this.options;if(index!=o.selected){this.lis.eq(index).addClass('ui-state-disabled');o.disabled.push(index);o.disabled.sort();this._trigger('disable',null,this._ui(this.anchors[index],this.panels[index]));}},select:function(index){if(typeof index=='string'){index=this.anchors.index(this.anchors.filter('[href$='+index+']'));}
+else if(index===null){index=-1;}
+if(index==-1&&this.options.collapsible){index=this.options.selected;}
+this.anchors.eq(index).trigger(this.options.event+'.tabs');},load:function(index){var self=this,o=this.options,a=this.anchors.eq(index)[0],url=$.data(a,'load.tabs');this.abort();if(!url||this.element.queue("tabs").length!==0&&$.data(a,'cache.tabs')){this.element.dequeue("tabs");return;}
+this.lis.eq(index).addClass('ui-state-processing');if(o.spinner){var span=$('span',a);span.data('label.tabs',span.html()).html(o.spinner);}
+this.xhr=$.ajax($.extend({},o.ajaxOptions,{url:url,success:function(r,s){$(self._sanitizeSelector(a.hash)).html(r);self._cleanup();if(o.cache){$.data(a,'cache.tabs',true);}
+self._trigger('load',null,self._ui(self.anchors[index],self.panels[index]));try{o.ajaxOptions.success(r,s);}
+catch(e){}
+self.element.dequeue("tabs");}}));},abort:function(){this.element.queue([]);this.panels.stop(false,true);if(this.xhr){this.xhr.abort();delete this.xhr;}
+this._cleanup();},url:function(index,url){this.anchors.eq(index).removeData('cache.tabs').data('load.tabs',url);},length:function(){return this.anchors.length;}});$.extend($.ui.tabs,{version:'1.7.2',getter:'length',defaults:{ajaxOptions:null,cache:false,cookie:null,collapsible:false,disabled:[],event:'click',fx:null,idPrefix:'ui-tabs-',panelTemplate:'<div></div>',spinner:'<em>Loading&#8230;</em>',tabTemplate:'<li><a href="#{href}"><span>#{label}</span></a></li>'}});$.extend($.ui.tabs.prototype,{rotation:null,rotate:function(ms,continuing){var self=this,o=this.options;var rotate=self._rotate||(self._rotate=function(e){clearTimeout(self.rotation);self.rotation=setTimeout(function(){var t=o.selected;self.select(++t<self.anchors.length?t:0);},ms);if(e){e.stopPropagation();}});var stop=self._unrotate||(self._unrotate=!continuing?function(e){if(e.clientX){self.rotate(null);}}:function(e){t=o.selected;rotate();});if(ms){this.element.bind('tabsshow',rotate);this.anchors.bind(o.event+'.tabs',stop);rotate();}
+else{clearTimeout(self.rotation);this.element.unbind('tabsshow',rotate);this.anchors.unbind(o.event+'.tabs',stop);delete this._rotate;delete this._unrotate;}}});})(jQuery);(function($){$.widget("ui.progressbar",{_init:function(){this.element.addClass("ui-progressbar"
++" ui-widget"
++" ui-widget-content"
++" ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=$('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element);this._refreshValue();},destroy:function(){this.element.removeClass("ui-progressbar"
++" ui-widget"
++" ui-widget-content"
++" ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow").removeData("progressbar").unbind(".progressbar");this.valueDiv.remove();$.widget.prototype.destroy.apply(this,arguments);},value:function(newValue){if(newValue===undefined){return this._value();}
+this._setData('value',newValue);return this;},_setData:function(key,value){switch(key){case'value':this.options.value=value;this._refreshValue();this._trigger('change',null,{});break;}
+$.widget.prototype._setData.apply(this,arguments);},_value:function(){var val=this.options.value;if(val<this._valueMin())val=this._valueMin();if(val>this._valueMax())val=this._valueMax();return val;},_valueMin:function(){var valueMin=0;return valueMin;},_valueMax:function(){var valueMax=100;return valueMax;},_refreshValue:function(){var value=this.value();this.valueDiv[value==this._valueMax()?'addClass':'removeClass']("ui-corner-right");this.valueDiv.width(value+'%');this.element.attr("aria-valuenow",value);}});$.extend($.ui.progressbar,{version:"1.7.2",defaults:{value:0}});})(jQuery);;jQuery.effects||(function($){$.effects={version:"1.7.2",save:function(element,set){for(var i=0;i<set.length;i++){if(set[i]!==null)element.data("ec.storage."+set[i],element[0].style[set[i]]);}},restore:function(element,set){for(var i=0;i<set.length;i++){if(set[i]!==null)element.css(set[i],element.data("ec.storage."+set[i]));}},setMode:function(el,mode){if(mode=='toggle')mode=el.is(':hidden')?'show':'hide';return mode;},getBaseline:function(origin,original){var y,x;switch(origin[0]){case'top':y=0;break;case'middle':y=0.5;break;case'bottom':y=1;break;default:y=origin[0]/original.height;};switch(origin[1]){case'left':x=0;break;case'center':x=0.5;break;case'right':x=1;break;default:x=origin[1]/original.width;};return{x:x,y:y};},createWrapper:function(element){if(element.parent().is('.ui-effects-wrapper'))
+return element.parent();var props={width:element.outerWidth(true),height:element.outerHeight(true),'float':element.css('float')};element.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');var wrapper=element.parent();if(element.css('position')=='static'){wrapper.css({position:'relative'});element.css({position:'relative'});}else{var top=element.css('top');if(isNaN(parseInt(top,10)))top='auto';var left=element.css('left');if(isNaN(parseInt(left,10)))left='auto';wrapper.css({position:element.css('position'),top:top,left:left,zIndex:element.css('z-index')}).show();element.css({position:'relative',top:0,left:0});}
+wrapper.css(props);return wrapper;},removeWrapper:function(element){if(element.parent().is('.ui-effects-wrapper'))
+return element.parent().replaceWith(element);return element;},setTransition:function(element,list,factor,value){value=value||{};$.each(list,function(i,x){unit=element.cssUnit(x);if(unit[0]>0)value[x]=unit[0]*factor+unit[1];});return value;},animateClass:function(value,duration,easing,callback){var cb=(typeof easing=="function"?easing:(callback?callback:null));var ea=(typeof easing=="string"?easing:null);return this.each(function(){var offset={};var that=$(this);var oldStyleAttr=that.attr("style")||'';if(typeof oldStyleAttr=='object')oldStyleAttr=oldStyleAttr["cssText"];if(value.toggle){that.hasClass(value.toggle)?value.remove=value.toggle:value.add=value.toggle;}
+var oldStyle=$.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(value.add)that.addClass(value.add);if(value.remove)that.removeClass(value.remove);var newStyle=$.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(value.add)that.removeClass(value.add);if(value.remove)that.addClass(value.remove);for(var n in newStyle){if(typeof newStyle[n]!="function"&&newStyle[n]&&n.indexOf("Moz")==-1&&n.indexOf("length")==-1&&newStyle[n]!=oldStyle[n]&&(n.match(/color/i)||(!n.match(/color/i)&&!isNaN(parseInt(newStyle[n],10))))&&(oldStyle.position!="static"||(oldStyle.position=="static"&&!n.match(/left|top|bottom|right/))))offset[n]=newStyle[n];}
+that.animate(offset,duration,ea,function(){if(typeof $(this).attr("style")=='object'){$(this).attr("style")["cssText"]="";$(this).attr("style")["cssText"]=oldStyleAttr;}else $(this).attr("style",oldStyleAttr);if(value.add)$(this).addClass(value.add);if(value.remove)$(this).removeClass(value.remove);if(cb)cb.apply(this,arguments);});});}};function _normalizeArguments(a,m){var o=a[1]&&a[1].constructor==Object?a[1]:{};if(m)o.mode=m;var speed=a[1]&&a[1].constructor!=Object?a[1]:(o.duration?o.duration:a[2]);speed=$.fx.off?0:typeof speed==="number"?speed:$.fx.speeds[speed]||$.fx.speeds._default;var callback=o.callback||($.isFunction(a[1])&&a[1])||($.isFunction(a[2])&&a[2])||($.isFunction(a[3])&&a[3]);return[a[0],o,speed,callback];}
+$.fn.extend({_show:$.fn.show,_hide:$.fn.hide,__toggle:$.fn.toggle,_addClass:$.fn.addClass,_removeClass:$.fn.removeClass,_toggleClass:$.fn.toggleClass,effect:function(fx,options,speed,callback){return $.effects[fx]?$.effects[fx].call(this,{method:fx,options:options||{},duration:speed,callback:callback}):null;},show:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0])))
+return this._show.apply(this,arguments);else{return this.effect.apply(this,_normalizeArguments(arguments,'show'));}},hide:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0])))
+return this._hide.apply(this,arguments);else{return this.effect.apply(this,_normalizeArguments(arguments,'hide'));}},toggle:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))||($.isFunction(arguments[0])||typeof arguments[0]=='boolean')){return this.__toggle.apply(this,arguments);}else{return this.effect.apply(this,_normalizeArguments(arguments,'toggle'));}},addClass:function(classNames,speed,easing,callback){return speed?$.effects.animateClass.apply(this,[{add:classNames},speed,easing,callback]):this._addClass(classNames);},removeClass:function(classNames,speed,easing,callback){return speed?$.effects.animateClass.apply(this,[{remove:classNames},speed,easing,callback]):this._removeClass(classNames);},toggleClass:function(classNames,speed,easing,callback){return((typeof speed!=="boolean")&&speed)?$.effects.animateClass.apply(this,[{toggle:classNames},speed,easing,callback]):this._toggleClass(classNames,speed);},morph:function(remove,add,speed,easing,callback){return $.effects.animateClass.apply(this,[{add:add,remove:remove},speed,easing,callback]);},switchClass:function(){return this.morph.apply(this,arguments);},cssUnit:function(key){var style=this.css(key),val=[];$.each(['em','px','%','pt'],function(i,unit){if(style.indexOf(unit)>0)
+val=[parseFloat(style),unit];});return val;}});$.each(['backgroundColor','borderBottomColor','borderLeftColor','borderRightColor','borderTopColor','color','outlineColor'],function(i,attr){$.fx.step[attr]=function(fx){if(fx.state==0){fx.start=getColor(fx.elem,attr);fx.end=getRGB(fx.end);}
+fx.elem.style[attr]="rgb("+[Math.max(Math.min(parseInt((fx.pos*(fx.end[0]-fx.start[0]))+fx.start[0],10),255),0),Math.max(Math.min(parseInt((fx.pos*(fx.end[1]-fx.start[1]))+fx.start[1],10),255),0),Math.max(Math.min(parseInt((fx.pos*(fx.end[2]-fx.start[2]))+fx.start[2],10),255),0)].join(",")+")";};});function getRGB(color){var result;if(color&&color.constructor==Array&&color.length==3)
+return color;if(result=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
+return[parseInt(result[1],10),parseInt(result[2],10),parseInt(result[3],10)];if(result=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
+return[parseFloat(result[1])*2.55,parseFloat(result[2])*2.55,parseFloat(result[3])*2.55];if(result=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
+return[parseInt(result[1],16),parseInt(result[2],16),parseInt(result[3],16)];if(result=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
+return[parseInt(result[1]+result[1],16),parseInt(result[2]+result[2],16),parseInt(result[3]+result[3],16)];if(result=/rgba\(0, 0, 0, 0\)/.exec(color))
+return colors['transparent'];return colors[$.trim(color).toLowerCase()];}
+function getColor(elem,attr){var color;do{color=$.curCSS(elem,attr);if(color!=''&&color!='transparent'||$.nodeName(elem,"body"))
+break;attr="backgroundColor";}while(elem=elem.parentNode);return getRGB(color);};var colors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]};$.easing.jswing=$.easing.swing;$.extend($.easing,{def:'easeOutQuad',swing:function(x,t,b,c,d){return $.easing[$.easing.def](x,t,b,c,d);},easeInQuad:function(x,t,b,c,d){return c*(t/=d)*t+b;},easeOutQuad:function(x,t,b,c,d){return-c*(t/=d)*(t-2)+b;},easeInOutQuad:function(x,t,b,c,d){if((t/=d/2)<1)return c/2*t*t+b;return-c/2*((--t)*(t-2)-1)+b;},easeInCubic:function(x,t,b,c,d){return c*(t/=d)*t*t+b;},easeOutCubic:function(x,t,b,c,d){return c*((t=t/d-1)*t*t+1)+b;},easeInOutCubic:function(x,t,b,c,d){if((t/=d/2)<1)return c/2*t*t*t+b;return c/2*((t-=2)*t*t+2)+b;},easeInQuart:function(x,t,b,c,d){return c*(t/=d)*t*t*t+b;},easeOutQuart:function(x,t,b,c,d){return-c*((t=t/d-1)*t*t*t-1)+b;},easeInOutQuart:function(x,t,b,c,d){if((t/=d/2)<1)return c/2*t*t*t*t+b;return-c/2*((t-=2)*t*t*t-2)+b;},easeInQuint:function(x,t,b,c,d){return c*(t/=d)*t*t*t*t+b;},easeOutQuint:function(x,t,b,c,d){return c*((t=t/d-1)*t*t*t*t+1)+b;},easeInOutQuint:function(x,t,b,c,d){if((t/=d/2)<1)return c/2*t*t*t*t*t+b;return c/2*((t-=2)*t*t*t*t+2)+b;},easeInSine:function(x,t,b,c,d){return-c*Math.cos(t/d*(Math.PI/2))+c+b;},easeOutSine:function(x,t,b,c,d){return c*Math.sin(t/d*(Math.PI/2))+b;},easeInOutSine:function(x,t,b,c,d){return-c/2*(Math.cos(Math.PI*t/d)-1)+b;},easeInExpo:function(x,t,b,c,d){return(t==0)?b:c*Math.pow(2,10*(t/d-1))+b;},easeOutExpo:function(x,t,b,c,d){return(t==d)?b+c:c*(-Math.pow(2,-10*t/d)+1)+b;},easeInOutExpo:function(x,t,b,c,d){if(t==0)return b;if(t==d)return b+c;if((t/=d/2)<1)return c/2*Math.pow(2,10*(t-1))+b;return c/2*(-Math.pow(2,-10*--t)+2)+b;},easeInCirc:function(x,t,b,c,d){return-c*(Math.sqrt(1-(t/=d)*t)-1)+b;},easeOutCirc:function(x,t,b,c,d){return c*Math.sqrt(1-(t=t/d-1)*t)+b;},easeInOutCirc:function(x,t,b,c,d){if((t/=d/2)<1)return-c/2*(Math.sqrt(1-t*t)-1)+b;return c/2*(Math.sqrt(1-(t-=2)*t)+1)+b;},easeInElastic:function(x,t,b,c,d){var s=1.70158;var p=0;var a=c;if(t==0)return b;if((t/=d)==1)return b+c;if(!p)p=d*.3;if(a<Math.abs(c)){a=c;var s=p/4;}
+else var s=p/(2*Math.PI)*Math.asin(c/a);return-(a*Math.pow(2,10*(t-=1))*Math.sin((t*d-s)*(2*Math.PI)/p))+b;},easeOutElastic:function(x,t,b,c,d){var s=1.70158;var p=0;var a=c;if(t==0)return b;if((t/=d)==1)return b+c;if(!p)p=d*.3;if(a<Math.abs(c)){a=c;var s=p/4;}
+else var s=p/(2*Math.PI)*Math.asin(c/a);return a*Math.pow(2,-10*t)*Math.sin((t*d-s)*(2*Math.PI)/p)+c+b;},easeInOutElastic:function(x,t,b,c,d){var s=1.70158;var p=0;var a=c;if(t==0)return b;if((t/=d/2)==2)return b+c;if(!p)p=d*(.3*1.5);if(a<Math.abs(c)){a=c;var s=p/4;}
+else var s=p/(2*Math.PI)*Math.asin(c/a);if(t<1)return-.5*(a*Math.pow(2,10*(t-=1))*Math.sin((t*d-s)*(2*Math.PI)/p))+b;return a*Math.pow(2,-10*(t-=1))*Math.sin((t*d-s)*(2*Math.PI)/p)*.5+c+b;},easeInBack:function(x,t,b,c,d,s){if(s==undefined)s=1.70158;return c*(t/=d)*t*((s+1)*t-s)+b;},easeOutBack:function(x,t,b,c,d,s){if(s==undefined)s=1.70158;return c*((t=t/d-1)*t*((s+1)*t+s)+1)+b;},easeInOutBack:function(x,t,b,c,d,s){if(s==undefined)s=1.70158;if((t/=d/2)<1)return c/2*(t*t*(((s*=(1.525))+1)*t-s))+b;return c/2*((t-=2)*t*(((s*=(1.525))+1)*t+s)+2)+b;},easeInBounce:function(x,t,b,c,d){return c-$.easing.easeOutBounce(x,d-t,0,c,d)+b;},easeOutBounce:function(x,t,b,c,d){if((t/=d)<(1/2.75)){return c*(7.5625*t*t)+b;}else if(t<(2/2.75)){return c*(7.5625*(t-=(1.5/2.75))*t+.75)+b;}else if(t<(2.5/2.75)){return c*(7.5625*(t-=(2.25/2.75))*t+.9375)+b;}else{return c*(7.5625*(t-=(2.625/2.75))*t+.984375)+b;}},easeInOutBounce:function(x,t,b,c,d){if(t<d/2)return $.easing.easeInBounce(x,t*2,0,c,d)*.5+b;return $.easing.easeOutBounce(x,t*2-d,0,c,d)*.5+c*.5+b;}});})(jQuery);(function($){$.effects.highlight=function(o){return this.queue(function(){var el=$(this),props=['backgroundImage','backgroundColor','opacity'];var mode=$.effects.setMode(el,o.options.mode||'show');var color=o.options.color||"#ffff99";var oldColor=el.css("backgroundColor");$.effects.save(el,props);el.show();el.css({backgroundImage:'none',backgroundColor:color});var animation={backgroundColor:oldColor};if(mode=="hide")animation['opacity']=0;el.animate(animation,{queue:false,duration:o.duration,easing:o.options.easing,complete:function(){if(mode=="hide")el.hide();$.effects.restore(el,props);if(mode=="show"&&$.browser.msie)this.style.removeAttribute('filter');if(o.callback)o.callback.apply(this,arguments);el.dequeue();}});});};})(jQuery);(function($){$.effects.transfer=function(o){return this.queue(function(){var elem=$(this),target=$(o.options.to),endPosition=target.offset(),animation={top:endPosition.top,left:endPosition.left,height:target.innerHeight(),width:target.innerWidth()},startPosition=elem.offset(),transfer=$('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(o.options.className).css({top:startPosition.top,left:startPosition.left,height:elem.innerHeight(),width:elem.innerWidth(),position:'absolute'}).animate(animation,o.duration,o.options.easing,function(){transfer.remove();(o.callback&&o.callback.apply(elem[0],arguments));elem.dequeue();});});};})(jQuery);
\ No newline at end of file
diff --git a/lib/jquery.MultiFile.js b/lib/jquery.MultiFile.js
new file mode 100644
index 0000000..c74083e
--- /dev/null
+++ b/lib/jquery.MultiFile.js
@@ -0,0 +1,11 @@
+/*
+ ### jQuery Multiple File Upload Plugin v1.3 - 2008-09-30 ###
+ * http://www.fyneworks.com/ - diego@fyneworks.com
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ ###
+ Project: http://jquery.com/plugins/project/MultiFile/
+ Website: http://www.fyneworks.com/jquery/multiple-file-upload/
+*/
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}(';2(K.1k)(3($){$.B($,{6:3(o){7 $("16:q.2L").6(o)}});$.B($.6,{18:{j:\'\',l:-1,1u:3(s){2($.1F){$.1F({2j:s.x(/\\n/m,\'<2i/>\'),19:{17:\'2K\',2s:\'2J\',2y:\'12.2I\',21:\'#1Q\',1P:\'#1O\',20:\'.8\',\'-1Z-17-1j\':\'1G\',\'-2f-17-1j\':\'1G\'}});K.2e($.2d,2h)}1m{2g(s)}},1p:\'$H\',y:{J:\'J\',1v:\'2r 2n 2q a $W q.\\2v 2x...\',T:\'2D T: $q\',1E:\'2E q 2H 1L 1J T:\\n$q\'}}});$.B($.6,{Z:3(a){p o=[];$(\'16:q\').M(3(){2($(5).X()==\'\')o[o.11]=5});7 $(o).M(3(){5.P=U}).1t(a||\'1w\')},1a:3(a){a=a||\'1w\';7 $(\'16:q.\'+a).1W(a).M(3(){5.P=t})},O:[\'28\',\'24\',\'27\'],1b:{},1H:3(b,c,d){p e,k;d=d||[];2(d.1l.1s().1o("1n")<0)d=[d];2(14(b)==\'3\'){$.6.Z();k=b.1r(c||K,d);$.6.1a();7 k};2(b.1l.1s().1o("1n")<0)b=[b];1q(p i=0;i<b.11;i++){e=b[i]+\'\';2(e)(3(a){$.6.1b[a]=$.15[a]||3(){};$.15[a]=3(){$.6.Z();k=$.6.1b[a].1r(5,2m);$.6.1a();7 k}})(e)}}});$.B($.15,{1c:3(){7 5.M(3(){2l{5.1c()}2k(e){}})},6:3(h){2($.6.O){$.6.1H($.6.O);$.6.O=L};7 $(5).M(3(e){2(5.1x)7;5.1x=U;K.6=(K.6||0)+1;e=K.6;p g={e:5,E:$(5),N:$(5).N()};2(14 h==\'2p\')h={l:h};2(14 h==\'2o\')h={j:h};p o=$.B({},$.6.18,h||{},($.2u?g.E.2t():($.1B?g.E.1B():L))||{});2(!(o.l>0)){o.l=g.E.D(\'2w\');2(!(o.l>0)){o.l=(u(g.e.1D.C(/\\b(l|2A)\\-([0-9]+)\\b/m)||[\'\']).C(/[0-9]+/m)||[\'\'])[0];2(!(o.l>0))o.l=-1;1m o.l=u(o.l).C(/[0-9]+/m)[0]}};o.l=Y 2C(o.l);o.j=o.j||g.E.D(\'j\')||\'\';2(!o.j){o.j=(g.e.1D.C(/\\b(j\\-[\\w\\|]+)\\b/m))||\'\';o.j=Y u(o.j).x(/^(j|W)\\-/i,\'\')};$.B(g,o||{});g.y=$.B({},$.6.18.y,g.y);$.B(g,{n:0,F:[],2G:[],1d:g.e.A||\'6\'+u(e),1e:3(z){7 g.1d+(z>0?\'1I\'+u(z):\'\')},G:3(a,b){p c=g[a],k=$(b).D(\'k\');2(c){p d=c(b,k,g);2(d!=L)7 d}7 U}});2(u(g.j).11>1){g.1f=Y 1K(\'\\\\.(\'+(g.j?g.j:\'\')+\')$\',\'m\')};g.I=g.1d+\'1N\';g.E.1M(\'<S A="\'+g.I+\'"></S>\');g.1g=$(\'#\'+g.I+\'\');g.e.H=g.e.H||\'q\'+e+\'[]\';g.1g.10(\'<R A="\'+g.I+\'1h"></R>\');g.13=$(\'#\'+g.I+\'1h\');g.V=3(c,d){g.n++;c.1i=g;c.i=d;2(c.i>0)c.A=c.H=L;c.A=c.A||g.1e(c.i);c.H=u(g.1p.x(/\\$H/m,g.E.D(\'H\')).x(/\\$A/m,g.E.D(\'A\')).x(/\\$g/m,(e>0?e:\'\')).x(/\\$i/m,(d>0?d:\'\')));$(c).X(\'\').D(\'k\',\'\')[0].k=\'\';2((g.l>0)&&((g.n-1)>(g.l)))c.P=U;g.Q=g.F[c.i]=c;c=$(c);$(c).1R(3(){$(5).1T();2(!g.G(\'1S\',5,g))7 t;p a=\'\',v=u(5.k||\'\');2(g.j&&v&&!v.C(g.1f))a=g.y.1v.x(\'$W\',u(v.C(/\\.\\w{1,4}$/m)));1q(p f 1U g.F)2(g.F[f]&&g.F[f]!=5)2(g.F[f].k==v)a=g.y.1E.x(\'$q\',v.C(/[^\\/\\\\]+$/m));p b=$(g.N).N();b.1t(\'6\');2(a!=\'\'){g.1u(a);g.n--;g.V(b[0],5.i);c.1y().1V(b);c.J();7 t};$(5).19({1A:\'1Y\',1z:\'-1X\'});g.13.22(b);g.1C(5);g.V(b[0],5.i+1);2(!g.G(\'23\',5,g))7 t})};g.1C=3(c){2(!g.G(\'2z\',c,g))7 t;p r=$(\'<S></S>\'),v=u(c.k||\'\'),a=$(\'<R 25="q" 26="\'+g.y.T.x(\'$q\',v)+\'">\'+v.C(/[^\\/\\\\]+$/m)[0]+\'</R>\'),b=$(\'<a 2B="#\'+g.I+\'">\'+g.y.J+\'</a>\');g.13.10(r.10(\'[\',b,\']&2b;\',a));b.29(3(){2(!g.G(\'2a\',c,g))7 t;g.n--;g.Q.P=t;g.F[c.i]=L;$(c).J();$(5).1y().J();$(g.Q).19({1A:\'\',1z:\'\'});$(g.Q).1c().X(\'\').D(\'k\',\'\')[0].k=\'\';2(!g.G(\'2F\',c,g))7 t;7 t});2(!g.G(\'2c\',c,g))7 t};2(!g.1i)g.V(g.e,0);g.n++})}});$(3(){$.6()})})(1k);',62,172,'||if|function||this|MultiFile|return||||||||||||accept|value|max|gi|||var|file|||false|String|||replace|STRING||id|extend|match|attr||slaves|trigger|name|wrapID|remove|window|null|each|clone|autoIntercept|disabled|current|span|div|selected|true|addSlave|ext|val|new|disableEmpty|append|length||labels|typeof|fn|input|border|options|css|reEnableEmpty|intercepted|reset|instanceKey|generateID|rxAccept|wrapper|_labels|MF|radius|jQuery|constructor|else|Array|indexOf|namePattern|for|apply|toString|addClass|error|denied|mfD|_MultiFile|parent|top|position|metadata|addToList|className|duplicate|blockUI|10px|intercept|_F|been|RegExp|already|wrap|_wrap|fff|color|900|change|onFileSelect|blur|in|prepend|removeClass|3000px|absolute|webkit|opacity|backgroundColor|before|afterFileSelect|ajaxSubmit|class|title|validate|submit|click|onFileRemove|nbsp|afterFileAppend|unblockUI|setTimeout|moz|alert|2000|br|message|catch|try|arguments|cannot|string|number|select|You|padding|data|meta|nTry|maxlength|again|size|onFileAppend|limit|href|Number|File|This|afterFileRemove|files|has|0pt|15px|none|multi'.split('|'),0,{}))
\ No newline at end of file
diff --git a/lib/jquery.autocomplete.css b/lib/jquery.autocomplete.css
new file mode 100644
index 0000000..ca42582
--- /dev/null
+++ b/lib/jquery.autocomplete.css
@@ -0,0 +1,49 @@
+.ac_results {
+	padding: 0px;
+	border: 1px solid black;
+	background-color: white;
+	overflow: hidden;
+	z-index: 99999;
+	text-align: left;
+}
+
+.ac_results ul {
+	width: 100%;
+	list-style-position: outside;
+	list-style: none;
+	padding: 0;
+	margin: 0;
+}
+
+.ac_results li {
+	margin: 0px;
+	padding: 2px 5px;
+	cursor: default;
+	display: block;
+	/* 
+	if width will be 100% horizontal scrollbar will apear 
+	when scroll mode will be used
+	*/
+	/*width: 100%;*/
+	font: menu;
+	font-size: 12px;
+	/* 
+	it is very important, if line-height not setted or setted 
+	in relative units scroll will be broken in firefox
+	*/
+	line-height: 16px;
+	overflow: hidden;
+}
+
+.ac_loading {
+	background: white url('images/loading-small.gif') right center no-repeat;
+}
+
+.ac_odd {
+	background-color: #eee;
+}
+
+.ac_over {
+	background-color: #0A246A;
+	color: white;
+}
diff --git a/lib/jquery.autocomplete.js b/lib/jquery.autocomplete.js
new file mode 100644
index 0000000..02f2b54
--- /dev/null
+++ b/lib/jquery.autocomplete.js
@@ -0,0 +1,13 @@
+/*
+ * Autocomplete - jQuery plugin 1.0.2
+ *
+ * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.autocomplete.js 5747 2008-06-25 18:30:55Z joern.zaefferer $
+ *
+ */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}(';(3($){$.31.1o({12:3(b,d){5 c=Y b=="1w";d=$.1o({},$.D.1L,{11:c?b:14,w:c?14:b,1D:c?$.D.1L.1D:10,Z:d&&!d.1x?10:3U},d);d.1t=d.1t||3(a){6 a};d.1q=d.1q||d.1K;6 I.K(3(){1E $.D(I,d)})},M:3(a){6 I.X("M",a)},1y:3(a){6 I.15("1y",[a])},20:3(){6 I.15("20")},1Y:3(a){6 I.15("1Y",[a])},1X:3(){6 I.15("1X")}});$.D=3(o,r){5 t={2N:38,2I:40,2D:46,2x:9,2v:13,2q:27,2d:3x,2j:33,2o:34,2e:8};5 u=$(o).3f("12","3c").P(r.24);5 p;5 m="";5 n=$.D.2W(r);5 s=0;5 k;5 h={1z:B};5 l=$.D.2Q(r,o,1U,h);5 j;$.1T.2L&&$(o.2K).X("3S.12",3(){4(j){j=B;6 B}});u.X(($.1T.2L?"3Q":"3N")+".12",3(a){k=a.2F;3L(a.2F){Q t.2N:a.1d();4(l.L()){l.2y()}A{W(0,C)}N;Q t.2I:a.1d();4(l.L()){l.2u()}A{W(0,C)}N;Q t.2j:a.1d();4(l.L()){l.2t()}A{W(0,C)}N;Q t.2o:a.1d();4(l.L()){l.2s()}A{W(0,C)}N;Q r.19&&$.1p(r.R)==","&&t.2d:Q t.2x:Q t.2v:4(1U()){a.1d();j=C;6 B}N;Q t.2q:l.U();N;3A:1I(p);p=1H(W,r.1D);N}}).1G(3(){s++}).3v(3(){s=0;4(!h.1z){2k()}}).2i(3(){4(s++>1&&!l.L()){W(0,C)}}).X("1y",3(){5 c=(1n.7>1)?1n[1]:14;3 23(q,a){5 b;4(a&&a.7){16(5 i=0;i<a.7;i++){4(a[i].M.O()==q.O()){b=a[i];N}}}4(Y c=="3")c(b);A u.15("M",b&&[b.w,b.H])}$.K(1g(u.J()),3(i,a){1R(a,23,23)})}).X("20",3(){n.18()}).X("1Y",3(){$.1o(r,1n[1]);4("w"2G 1n[1])n.1f()}).X("1X",3(){l.1u();u.1u();$(o.2K).1u(".12")});3 1U(){5 b=l.26();4(!b)6 B;5 v=b.M;m=v;4(r.19){5 a=1g(u.J());4(a.7>1){v=a.17(0,a.7-1).2Z(r.R)+r.R+v}v+=r.R}u.J(v);1l();u.15("M",[b.w,b.H]);6 C}3 W(b,c){4(k==t.2D){l.U();6}5 a=u.J();4(!c&&a==m)6;m=a;a=1k(a);4(a.7>=r.22){u.P(r.21);4(!r.1C)a=a.O();1R(a,2V,1l)}A{1B();l.U()}};3 1g(b){4(!b){6[""]}5 d=b.1Z(r.R);5 c=[];$.K(d,3(i,a){4($.1p(a))c[i]=$.1p(a)});6 c}3 1k(a){4(!r.19)6 a;5 b=1g(a);6 b[b.7-1]}3 1A(q,a){4(r.1A&&(1k(u.J()).O()==q.O())&&k!=t.2e){u.J(u.J()+a.48(1k(m).7));$.D.1N(o,m.7,m.7+a.7)}};3 2k(){1I(p);p=1H(1l,47)};3 1l(){5 c=l.L();l.U();1I(p);1B();4(r.2U){u.1y(3(a){4(!a){4(r.19){5 b=1g(u.J()).17(0,-1);u.J(b.2Z(r.R)+(b.7?r.R:""))}A u.J("")}})}4(c)$.D.1N(o,o.H.7,o.H.7)};3 2V(q,a){4(a&&a.7&&s){1B();l.2T(a,q);1A(q,a[0].H);l.1W()}A{1l()}};3 1R(f,d,g){4(!r.1C)f=f.O();5 e=n.2S(f);4(e&&e.7){d(f,e)}A 4((Y r.11=="1w")&&(r.11.7>0)){5 c={45:+1E 44()};$.K(r.2R,3(a,b){c[a]=Y b=="3"?b():b});$.43({42:"41",3Z:"12"+o.3Y,2M:r.2M,11:r.11,w:$.1o({q:1k(f),3X:r.Z},c),3W:3(a){5 b=r.1r&&r.1r(a)||1r(a);n.1h(f,b);d(f,b)}})}A{l.2J();g(f)}};3 1r(c){5 d=[];5 b=c.1Z("\\n");16(5 i=0;i<b.7;i++){5 a=$.1p(b[i]);4(a){a=a.1Z("|");d[d.7]={w:a,H:a[0],M:r.1v&&r.1v(a,a[0])||a[0]}}}6 d};3 1B(){u.1e(r.21)}};$.D.1L={24:"3R",2H:"3P",21:"3O",22:1,1D:3M,1C:B,1a:C,1V:B,1j:10,Z:3K,2U:B,2R:{},1S:C,1K:3(a){6 a[0]},1q:14,1A:B,E:0,19:B,R:", ",1t:3(b,a){6 b.2C(1E 3J("(?![^&;]+;)(?!<[^<>]*)("+a.2C(/([\\^\\$\\(\\)\\[\\]\\{\\}\\*\\.\\+\\?\\|\\\\])/2A,"\\\\$1")+")(?![^<>]*>)(?![^&;]+;)","2A"),"<2z>$1</2z>")},1x:C,1s:3I};$.D.2W=3(g){5 h={};5 j=0;3 1a(s,a){4(!g.1C)s=s.O();5 i=s.3H(a);4(i==-1)6 B;6 i==0||g.1V};3 1h(q,a){4(j>g.1j){18()}4(!h[q]){j++}h[q]=a}3 1f(){4(!g.w)6 B;5 f={},2w=0;4(!g.11)g.1j=1;f[""]=[];16(5 i=0,30=g.w.7;i<30;i++){5 c=g.w[i];c=(Y c=="1w")?[c]:c;5 d=g.1q(c,i+1,g.w.7);4(d===B)1P;5 e=d.3G(0).O();4(!f[e])f[e]=[];5 b={H:d,w:c,M:g.1v&&g.1v(c)||d};f[e].1O(b);4(2w++<g.Z){f[""].1O(b)}};$.K(f,3(i,a){g.1j++;1h(i,a)})}1H(1f,25);3 18(){h={};j=0}6{18:18,1h:1h,1f:1f,2S:3(q){4(!g.1j||!j)6 14;4(!g.11&&g.1V){5 a=[];16(5 k 2G h){4(k.7>0){5 c=h[k];$.K(c,3(i,x){4(1a(x.H,q)){a.1O(x)}})}}6 a}A 4(h[q]){6 h[q]}A 4(g.1a){16(5 i=q.7-1;i>=g.22;i--){5 c=h[q.3F(0,i)];4(c){5 a=[];$.K(c,3(i,x){4(1a(x.H,q)){a[a.7]=x}});6 a}}}6 14}}};$.D.2Q=3(e,g,f,k){5 h={G:"3E"};5 j,y=-1,w,1m="",1M=C,F,z;3 2r(){4(!1M)6;F=$("<3D/>").U().P(e.2H).T("3C","3B").1J(2p.2n);z=$("<3z/>").1J(F).3y(3(a){4(V(a).2m&&V(a).2m.3w()==\'2l\'){y=$("1F",z).1e(h.G).3u(V(a));$(V(a)).P(h.G)}}).2i(3(a){$(V(a)).P(h.G);f();g.1G();6 B}).3t(3(){k.1z=C}).3s(3(){k.1z=B});4(e.E>0)F.T("E",e.E);1M=B}3 V(a){5 b=a.V;3r(b&&b.3q!="2l")b=b.3p;4(!b)6[];6 b}3 S(b){j.17(y,y+1).1e(h.G);2h(b);5 a=j.17(y,y+1).P(h.G);4(e.1x){5 c=0;j.17(0,y).K(3(){c+=I.1i});4((c+a[0].1i-z.1c())>z[0].3o){z.1c(c+a[0].1i-z.3n())}A 4(c<z.1c()){z.1c(c)}}};3 2h(a){y+=a;4(y<0){y=j.1b()-1}A 4(y>=j.1b()){y=0}}3 2g(a){6 e.Z&&e.Z<a?e.Z:a}3 2f(){z.2B();5 b=2g(w.7);16(5 i=0;i<b;i++){4(!w[i])1P;5 a=e.1K(w[i].w,i+1,b,w[i].H,1m);4(a===B)1P;5 c=$("<1F/>").3m(e.1t(a,1m)).P(i%2==0?"3l":"3k").1J(z)[0];$.w(c,"2c",w[i])}j=z.3j("1F");4(e.1S){j.17(0,1).P(h.G);y=0}4($.31.2b)z.2b()}6{2T:3(d,q){2r();w=d;1m=q;2f()},2u:3(){S(1)},2y:3(){S(-1)},2t:3(){4(y!=0&&y-8<0){S(-y)}A{S(-8)}},2s:3(){4(y!=j.1b()-1&&y+8>j.1b()){S(j.1b()-1-y)}A{S(8)}},U:3(){F&&F.U();j&&j.1e(h.G);y=-1},L:3(){6 F&&F.3i(":L")},3h:3(){6 I.L()&&(j.2a("."+h.G)[0]||e.1S&&j[0])},1W:3(){5 a=$(g).3g();F.T({E:Y e.E=="1w"||e.E>0?e.E:$(g).E(),2E:a.2E+g.1i,1Q:a.1Q}).1W();4(e.1x){z.1c(0);z.T({29:e.1s,3e:\'3d\'});4($.1T.3b&&Y 2p.2n.3T.29==="3a"){5 c=0;j.K(3(){c+=I.1i});5 b=c>e.1s;z.T(\'3V\',b?e.1s:c);4(!b){j.E(z.E()-28(j.T("32-1Q"))-28(j.T("32-39")))}}}},26:3(){5 a=j&&j.2a("."+h.G).1e(h.G);6 a&&a.7&&$.w(a[0],"2c")},2J:3(){z&&z.2B()},1u:3(){F&&F.37()}}};$.D.1N=3(b,a,c){4(b.2O){5 d=b.2O();d.36(C);d.35("2P",a);d.4c("2P",c);d.4b()}A 4(b.2Y){b.2Y(a,c)}A{4(b.2X){b.2X=a;b.4a=c}}b.1G()}})(49);',62,261,'|||function|if|var|return|length|||||||||||||||||||||||||data||active|list|else|false|true|Autocompleter|width|element|ACTIVE|value|this|val|each|visible|result|break|toLowerCase|addClass|case|multipleSeparator|moveSelect|css|hide|target|onChange|bind|typeof|max||url|autocomplete||null|trigger|for|slice|flush|multiple|matchSubset|size|scrollTop|preventDefault|removeClass|populate|trimWords|add|offsetHeight|cacheLength|lastWord|hideResultsNow|term|arguments|extend|trim|formatMatch|parse|scrollHeight|highlight|unbind|formatResult|string|scroll|search|mouseDownOnSelect|autoFill|stopLoading|matchCase|delay|new|li|focus|setTimeout|clearTimeout|appendTo|formatItem|defaults|needsInit|Selection|push|continue|left|request|selectFirst|browser|selectCurrent|matchContains|show|unautocomplete|setOptions|split|flushCache|loadingClass|minChars|findValueCallback|inputClass||selected||parseInt|maxHeight|filter|bgiframe|ac_data|COMMA|BACKSPACE|fillList|limitNumberOfItems|movePosition|click|PAGEUP|hideResults|LI|nodeName|body|PAGEDOWN|document|ESC|init|pageDown|pageUp|next|RETURN|nullData|TAB|prev|strong|gi|empty|replace|DEL|top|keyCode|in|resultsClass|DOWN|emptyList|form|opera|dataType|UP|createTextRange|character|Select|extraParams|load|display|mustMatch|receiveData|Cache|selectionStart|setSelectionRange|join|ol|fn|padding|||moveStart|collapse|remove||right|undefined|msie|off|auto|overflow|attr|offset|current|is|find|ac_odd|ac_even|html|innerHeight|clientHeight|parentNode|tagName|while|mouseup|mousedown|index|blur|toUpperCase|188|mouseover|ul|default|absolute|position|div|ac_over|substr|charAt|indexOf|180|RegExp|100|switch|400|keydown|ac_loading|ac_results|keypress|ac_input|submit|style|150|height|success|limit|name|port||abort|mode|ajax|Date|timestamp||200|substring|jQuery|selectionEnd|select|moveEnd'.split('|'),0,{}));
diff --git a/lib/jquery.cookie.js b/lib/jquery.cookie.js
new file mode 100644
index 0000000..6df1fac
--- /dev/null
+++ b/lib/jquery.cookie.js
@@ -0,0 +1,96 @@
+/**
+ * Cookie plugin
+ *
+ * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+/**
+ * Create a cookie with the given name and value and other optional parameters.
+ *
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Set the value of a cookie.
+ * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
+ * @desc Create a cookie with all available options.
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Create a session cookie.
+ * @example $.cookie('the_cookie', null);
+ * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
+ *       used when the cookie was set.
+ *
+ * @param String name The name of the cookie.
+ * @param String value The value of the cookie.
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
+ *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
+ *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
+ *                             when the the browser exits.
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
+ *                        require a secure protocol (like HTTPS).
+ * @type undefined
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+
+/**
+ * Get the value of a cookie with the given name.
+ *
+ * @example $.cookie('the_cookie');
+ * @desc Get the value of a cookie.
+ *
+ * @param String name The name of the cookie.
+ * @return The value of the cookie.
+ * @type String
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+jQuery.cookie = function(name, value, options) {
+    if (typeof value != 'undefined') { // name and value given, set cookie
+        options = options || {};
+        if (value === null) {
+            value = '';
+            options.expires = -1;
+        }
+        var expires = '';
+        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
+            var date;
+            if (typeof options.expires == 'number') {
+                date = new Date();
+                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
+            } else {
+                date = options.expires;
+            }
+            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
+        }
+        // CAUTION: Needed to parenthesize options.path and options.domain
+        // in the following expressions, otherwise they evaluate to undefined
+        // in the packed version for some reason...
+        var path = options.path ? '; path=' + (options.path) : '';
+        var domain = options.domain ? '; domain=' + (options.domain) : '';
+        var secure = options.secure ? '; secure' : '';
+        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
+    } else { // only name given, get cookie
+        var cookieValue = null;
+        if (document.cookie && document.cookie != '') {
+            var cookies = document.cookie.split(';');
+            for (var i = 0; i < cookies.length; i++) {
+                var cookie = jQuery.trim(cookies[i]);
+                // Does this cookie string begin with the name we want?
+                if (cookie.substring(0, name.length + 1) == (name + '=')) {
+                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
+                    break;
+                }
+            }
+        }
+        return cookieValue;
+    }
+};
\ No newline at end of file
diff --git a/lib/jquery.form.js b/lib/jquery.form.js
new file mode 100644
index 0000000..40fb8b1
--- /dev/null
+++ b/lib/jquery.form.js
@@ -0,0 +1,645 @@
+/*
+ * jQuery Form Plugin
+ * version: 2.28 (10-MAY-2009)
+ * @requires jQuery v1.2.2 or later
+ *
+ * Examples and documentation at: http://malsup.com/jquery/form/
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ */
+;(function($) {
+
+/*
+    Usage Note:
+    -----------
+    Do not use both ajaxSubmit and ajaxForm on the same form.  These
+    functions are intended to be exclusive.  Use ajaxSubmit if you want
+    to bind your own submit handler to the form.  For example,
+
+    $(document).ready(function() {
+        $('#myForm').bind('submit', function() {
+            $(this).ajaxSubmit({
+                target: '#output'
+            });
+            return false; // <-- important!
+        });
+    });
+
+    Use ajaxForm when you want the plugin to manage all the event binding
+    for you.  For example,
+
+    $(document).ready(function() {
+        $('#myForm').ajaxForm({
+            target: '#output'
+        });
+    });
+
+    When using ajaxForm, the ajaxSubmit function will be invoked for you
+    at the appropriate time.
+*/
+
+/**
+ * ajaxSubmit() provides a mechanism for immediately submitting
+ * an HTML form using AJAX.
+ */
+$.fn.ajaxSubmit = function(options) {
+    // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
+    if (!this.length) {
+        log('ajaxSubmit: skipping submit process - no element selected');
+        return this;
+    }
+
+    if (typeof options == 'function')
+        options = { success: options };
+
+    var url = $.trim(this.attr('action'));
+    if (url) {
+	    // clean url (don't include hash vaue)
+	    url = (url.match(/^([^#]+)/)||[])[1];
+   	}
+   	url = url || window.location.href || ''
+
+    options = $.extend({
+        url:  url,
+        type: this.attr('method') || 'GET'
+    }, options || {});
+
+    // hook for manipulating the form data before it is extracted;
+    // convenient for use with rich editors like tinyMCE or FCKEditor
+    var veto = {};
+    this.trigger('form-pre-serialize', [this, options, veto]);
+    if (veto.veto) {
+        log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
+        return this;
+    }
+
+    // provide opportunity to alter form data before it is serialized
+    if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
+        log('ajaxSubmit: submit aborted via beforeSerialize callback');
+        return this;
+    }
+
+    var a = this.formToArray(options.semantic);
+    if (options.data) {
+        options.extraData = options.data;
+        for (var n in options.data) {
+          if(options.data[n] instanceof Array) {
+            for (var k in options.data[n])
+              a.push( { name: n, value: options.data[n][k] } );
+          }
+          else
+             a.push( { name: n, value: options.data[n] } );
+        }
+    }
+
+    // give pre-submit callback an opportunity to abort the submit
+    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
+        log('ajaxSubmit: submit aborted via beforeSubmit callback');
+        return this;
+    }
+
+    // fire vetoable 'validate' event
+    this.trigger('form-submit-validate', [a, this, options, veto]);
+    if (veto.veto) {
+        log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
+        return this;
+    }
+
+    var q = $.param(a);
+
+    if (options.type.toUpperCase() == 'GET') {
+        options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
+        options.data = null;  // data is null for 'get'
+    }
+    else
+        options.data = q; // data is the query string for 'post'
+
+    var $form = this, callbacks = [];
+    if (options.resetForm) callbacks.push(function() { $form.resetForm(); });
+    if (options.clearForm) callbacks.push(function() { $form.clearForm(); });
+
+    // perform a load on the target only if dataType is not provided
+    if (!options.dataType && options.target) {
+        var oldSuccess = options.success || function(){};
+        callbacks.push(function(data) {
+            $(options.target).html(data).each(oldSuccess, arguments);
+        });
+    }
+    else if (options.success)
+        callbacks.push(options.success);
+
+    options.success = function(data, status) {
+        for (var i=0, max=callbacks.length; i < max; i++)
+            callbacks[i].apply(options, [data, status, $form]);
+    };
+
+    // are there files to upload?
+    var files = $('input:file', this).fieldValue();
+    var found = false;
+    for (var j=0; j < files.length; j++)
+        if (files[j])
+            found = true;
+
+	var multipart = false;
+//	var mp = 'multipart/form-data';
+//	multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
+
+    // options.iframe allows user to force iframe mode
+   if (options.iframe || found || multipart) {
+       // hack to fix Safari hang (thanks to Tim Molendijk for this)
+       // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
+       if (options.closeKeepAlive)
+           $.get(options.closeKeepAlive, fileUpload);
+       else
+           fileUpload();
+       }
+   else
+       $.ajax(options);
+
+    // fire 'notify' event
+    this.trigger('form-submit-notify', [this, options]);
+    return this;
+
+
+    // private function for handling file uploads (hat tip to YAHOO!)
+    function fileUpload() {
+        var form = $form[0];
+
+	/* (this breaks the watermark form uploader, turn it off for now)
+        if ($(':input[name=submit]', form).length) {
+            alert('Error: Form elements must not be named "submit".');
+            return;
+        }
+	*/
+
+        var opts = $.extend({}, $.ajaxSettings, options);
+		var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts);
+
+        var id = 'jqFormIO' + (new Date().getTime());
+        var $io = $('<iframe id="' + id + '" name="' + id + '" src="about:blank" />');
+        var io = $io[0];
+
+        $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
+
+        var xhr = { // mock object
+            aborted: 0,
+            responseText: null,
+            responseXML: null,
+            status: 0,
+            statusText: 'n/a',
+            getAllResponseHeaders: function() {},
+            getResponseHeader: function() {},
+            setRequestHeader: function() {},
+            abort: function() {
+                this.aborted = 1;
+                $io.attr('src','about:blank'); // abort op in progress
+            }
+        };
+
+        var g = opts.global;
+        // trigger ajax global events so that activity/block indicators work like normal
+        if (g && ! $.active++) $.event.trigger("ajaxStart");
+        if (g) $.event.trigger("ajaxSend", [xhr, opts]);
+
+		if (s.beforeSend && s.beforeSend(xhr, s) === false) {
+			s.global && $.active--;
+			return;
+        }
+        if (xhr.aborted)
+            return;
+
+        var cbInvoked = 0;
+        var timedOut = 0;
+
+        // add submitting element to data if we know it
+        var sub = form.clk;
+        if (sub) {
+            var n = sub.name;
+            if (n && !sub.disabled) {
+                options.extraData = options.extraData || {};
+                options.extraData[n] = sub.value;
+                if (sub.type == "image") {
+                    options.extraData[name+'.x'] = form.clk_x;
+                    options.extraData[name+'.y'] = form.clk_y;
+                }
+            }
+        }
+
+        // take a breath so that pending repaints get some cpu time before the upload starts
+        setTimeout(function() {
+            // make sure form attrs are set
+            var t = $form.attr('target'), a = $form.attr('action');
+
+			// update form attrs in IE friendly way
+			form.setAttribute('target',id);
+			if (form.getAttribute('method') != 'POST')
+				form.setAttribute('method', 'POST');
+			if (form.getAttribute('action') != opts.url)
+				form.setAttribute('action', opts.url);
+
+            // ie borks in some cases when setting encoding
+            if (! options.skipEncodingOverride) {
+                $form.attr({
+                    encoding: 'multipart/form-data',
+                    enctype:  'multipart/form-data'
+                });
+            }
+
+            // support timout
+            if (opts.timeout)
+                setTimeout(function() { timedOut = true; cb(); }, opts.timeout);
+
+            // add "extra" data to form if provided in options
+            var extraInputs = [];
+            try {
+                if (options.extraData)
+                    for (var n in options.extraData)
+                        extraInputs.push(
+                            $('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
+                                .appendTo(form)[0]);
+
+                // add iframe to doc and submit the form
+                $io.appendTo('body');
+                io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
+                form.submit();
+            }
+            finally {
+                // reset attrs and remove "extra" input elements
+				form.setAttribute('action',a);
+                t ? form.setAttribute('target', t) : $form.removeAttr('target');
+                $(extraInputs).remove();
+            }
+        }, 10);
+
+        var nullCheckFlag = 0;
+
+        function cb() {
+            if (cbInvoked++) return;
+
+            io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
+
+            var ok = true;
+            try {
+                if (timedOut) throw 'timeout';
+                // extract the server response from the iframe
+                var data, doc;
+
+                doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
+
+                if ((doc.body == null || doc.body.innerHTML == '') && !nullCheckFlag) {
+                    // in some browsers (cough, Opera 9.2.x) the iframe DOM is not always traversable when
+                    // the onload callback fires, so we give them a 2nd chance
+                    nullCheckFlag = 1;
+                    cbInvoked--;
+                    setTimeout(cb, 100);
+                    return;
+                }
+
+                xhr.responseText = doc.body ? doc.body.innerHTML : null;
+                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
+                xhr.getResponseHeader = function(header){
+                    var headers = {'content-type': opts.dataType};
+                    return headers[header];
+                };
+
+                if (opts.dataType == 'json' || opts.dataType == 'script') {
+                    var ta = doc.getElementsByTagName('textarea')[0];
+                    xhr.responseText = ta ? ta.value : xhr.responseText;
+                }
+                else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
+                    xhr.responseXML = toXml(xhr.responseText);
+                }
+                data = $.httpData(xhr, opts.dataType);
+            }
+            catch(e){
+                ok = false;
+                $.handleError(opts, xhr, 'error', e);
+            }
+
+            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
+            if (ok) {
+                opts.success(data, 'success');
+                if (g) $.event.trigger("ajaxSuccess", [xhr, opts]);
+            }
+            if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
+            if (g && ! --$.active) $.event.trigger("ajaxStop");
+            if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error');
+
+            // clean up
+            setTimeout(function() {
+                $io.remove();
+                xhr.responseXML = null;
+            }, 100);
+        };
+
+        function toXml(s, doc) {
+            if (window.ActiveXObject) {
+                doc = new ActiveXObject('Microsoft.XMLDOM');
+                doc.async = 'false';
+                doc.loadXML(s);
+            }
+            else
+                doc = (new DOMParser()).parseFromString(s, 'text/xml');
+            return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
+        };
+    };
+};
+
+/**
+ * ajaxForm() provides a mechanism for fully automating form submission.
+ *
+ * The advantages of using this method instead of ajaxSubmit() are:
+ *
+ * 1: This method will include coordinates for <input type="image" /> elements (if the element
+ *    is used to submit the form).
+ * 2. This method will include the submit element's name/value data (for the element that was
+ *    used to submit the form).
+ * 3. This method binds the submit() method to the form for you.
+ *
+ * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
+ * passes the options argument along after properly binding events for submit elements and
+ * the form itself.
+ */
+$.fn.ajaxForm = function(options) {
+    return this.ajaxFormUnbind().bind('submit.form-plugin',function() {
+        $(this).ajaxSubmit(options);
+        return false;
+    }).each(function() {
+        // store options in hash
+        $(":submit,input:image", this).bind('click.form-plugin',function(e) {
+            var form = this.form;
+            form.clk = this;
+            if (this.type == 'image') {
+                if (e.offsetX != undefined) {
+                    form.clk_x = e.offsetX;
+                    form.clk_y = e.offsetY;
+                } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
+                    var offset = $(this).offset();
+                    form.clk_x = e.pageX - offset.left;
+                    form.clk_y = e.pageY - offset.top;
+                } else {
+                    form.clk_x = e.pageX - this.offsetLeft;
+                    form.clk_y = e.pageY - this.offsetTop;
+                }
+            }
+            // clear form vars
+            setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 10);
+        });
+    });
+};
+
+// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
+$.fn.ajaxFormUnbind = function() {
+    this.unbind('submit.form-plugin');
+    return this.each(function() {
+        $(":submit,input:image", this).unbind('click.form-plugin');
+    });
+
+};
+
+/**
+ * formToArray() gathers form element data into an array of objects that can
+ * be passed to any of the following ajax functions: $.get, $.post, or load.
+ * Each object in the array has both a 'name' and 'value' property.  An example of
+ * an array for a simple login form might be:
+ *
+ * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
+ *
+ * It is this array that is passed to pre-submit callback functions provided to the
+ * ajaxSubmit() and ajaxForm() methods.
+ */
+$.fn.formToArray = function(semantic) {
+    var a = [];
+    if (this.length == 0) return a;
+
+    var form = this[0];
+    var els = semantic ? form.getElementsByTagName('*') : form.elements;
+    if (!els) return a;
+    for(var i=0, max=els.length; i < max; i++) {
+        var el = els[i];
+        var n = el.name;
+        if (!n) continue;
+
+        if (semantic && form.clk && el.type == "image") {
+            // handle image inputs on the fly when semantic == true
+            if(!el.disabled && form.clk == el) {
+            	a.push({name: n, value: $(el).val()});
+                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+            }
+            continue;
+        }
+
+        var v = $.fieldValue(el, true);
+        if (v && v.constructor == Array) {
+            for(var j=0, jmax=v.length; j < jmax; j++)
+                a.push({name: n, value: v[j]});
+        }
+        else if (v !== null && typeof v != 'undefined')
+            a.push({name: n, value: v});
+    }
+
+    if (!semantic && form.clk) {
+        // input type=='image' are not found in elements array! handle it here
+        var $input = $(form.clk), input = $input[0], n = input.name;
+        if (n && !input.disabled && input.type == 'image') {
+        	a.push({name: n, value: $input.val()});
+            a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+        }
+    }
+    return a;
+};
+
+/**
+ * Serializes form data into a 'submittable' string. This method will return a string
+ * in the format: name1=value1&amp;name2=value2
+ */
+$.fn.formSerialize = function(semantic) {
+    //hand off to jQuery.param for proper encoding
+    return $.param(this.formToArray(semantic));
+};
+
+/**
+ * Serializes all field elements in the jQuery object into a query string.
+ * This method will return a string in the format: name1=value1&amp;name2=value2
+ */
+$.fn.fieldSerialize = function(successful) {
+    var a = [];
+    this.each(function() {
+        var n = this.name;
+        if (!n) return;
+        var v = $.fieldValue(this, successful);
+        if (v && v.constructor == Array) {
+            for (var i=0,max=v.length; i < max; i++)
+                a.push({name: n, value: v[i]});
+        }
+        else if (v !== null && typeof v != 'undefined')
+            a.push({name: this.name, value: v});
+    });
+    //hand off to jQuery.param for proper encoding
+    return $.param(a);
+};
+
+/**
+ * Returns the value(s) of the element in the matched set.  For example, consider the following form:
+ *
+ *  <form><fieldset>
+ *      <input name="A" type="text" />
+ *      <input name="A" type="text" />
+ *      <input name="B" type="checkbox" value="B1" />
+ *      <input name="B" type="checkbox" value="B2"/>
+ *      <input name="C" type="radio" value="C1" />
+ *      <input name="C" type="radio" value="C2" />
+ *  </fieldset></form>
+ *
+ *  var v = $(':text').fieldValue();
+ *  // if no values are entered into the text inputs
+ *  v == ['','']
+ *  // if values entered into the text inputs are 'foo' and 'bar'
+ *  v == ['foo','bar']
+ *
+ *  var v = $(':checkbox').fieldValue();
+ *  // if neither checkbox is checked
+ *  v === undefined
+ *  // if both checkboxes are checked
+ *  v == ['B1', 'B2']
+ *
+ *  var v = $(':radio').fieldValue();
+ *  // if neither radio is checked
+ *  v === undefined
+ *  // if first radio is checked
+ *  v == ['C1']
+ *
+ * The successful argument controls whether or not the field element must be 'successful'
+ * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
+ * The default value of the successful argument is true.  If this value is false the value(s)
+ * for each element is returned.
+ *
+ * Note: This method *always* returns an array.  If no valid value can be determined the
+ *       array will be empty, otherwise it will contain one or more values.
+ */
+$.fn.fieldValue = function(successful) {
+    for (var val=[], i=0, max=this.length; i < max; i++) {
+        var el = this[i];
+        var v = $.fieldValue(el, successful);
+        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
+            continue;
+        v.constructor == Array ? $.merge(val, v) : val.push(v);
+    }
+    return val;
+};
+
+/**
+ * Returns the value of the field element.
+ */
+$.fieldValue = function(el, successful) {
+    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
+    if (typeof successful == 'undefined') successful = true;
+
+    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
+        (t == 'checkbox' || t == 'radio') && !el.checked ||
+        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
+        tag == 'select' && el.selectedIndex == -1))
+            return null;
+
+    if (tag == 'select') {
+        var index = el.selectedIndex;
+        if (index < 0) return null;
+        var a = [], ops = el.options;
+        var one = (t == 'select-one');
+        var max = (one ? index+1 : ops.length);
+        for(var i=(one ? index : 0); i < max; i++) {
+            var op = ops[i];
+            if (op.selected) {
+				var v = op.value;
+				if (!v) // extra pain for IE...
+                	v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
+                if (one) return v;
+                a.push(v);
+            }
+        }
+        return a;
+    }
+    return el.value;
+};
+
+/**
+ * Clears the form data.  Takes the following actions on the form's input fields:
+ *  - input text fields will have their 'value' property set to the empty string
+ *  - select elements will have their 'selectedIndex' property set to -1
+ *  - checkbox and radio inputs will have their 'checked' property set to false
+ *  - inputs of type submit, button, reset, and hidden will *not* be effected
+ *  - button elements will *not* be effected
+ */
+$.fn.clearForm = function() {
+    return this.each(function() {
+        $('input,select,textarea', this).clearFields();
+    });
+};
+
+/**
+ * Clears the selected form elements.
+ */
+$.fn.clearFields = $.fn.clearInputs = function() {
+    return this.each(function() {
+        var t = this.type, tag = this.tagName.toLowerCase();
+        if (t == 'text' || t == 'password' || tag == 'textarea')
+            this.value = '';
+        else if (t == 'checkbox' || t == 'radio')
+            this.checked = false;
+        else if (tag == 'select')
+            this.selectedIndex = -1;
+    });
+};
+
+/**
+ * Resets the form data.  Causes all form elements to be reset to their original value.
+ */
+$.fn.resetForm = function() {
+    return this.each(function() {
+        // guard against an input with the name of 'reset'
+        // note that IE reports the reset function as an 'object'
+        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType))
+            this.reset();
+    });
+};
+
+/**
+ * Enables or disables any matching elements.
+ */
+$.fn.enable = function(b) {
+    if (b == undefined) b = true;
+    return this.each(function() {
+        this.disabled = !b;
+    });
+};
+
+/**
+ * Checks/unchecks any matching checkboxes or radio buttons and
+ * selects/deselects and matching option elements.
+ */
+$.fn.selected = function(select) {
+    if (select == undefined) select = true;
+    return this.each(function() {
+        var t = this.type;
+        if (t == 'checkbox' || t == 'radio')
+            this.checked = select;
+        else if (this.tagName.toLowerCase() == 'option') {
+            var $sel = $(this).parent('select');
+            if (select && $sel[0] && $sel[0].type == 'select-one') {
+                // deselect all other options
+                $sel.find('option').selected(false);
+            }
+            this.selected = select;
+        }
+    });
+};
+
+// helper fn for console logging
+// set $.fn.ajaxSubmit.debug to true to enable debug logging
+function log() {
+    if ($.fn.ajaxSubmit.debug && window.console && window.console.log)
+        window.console.log('[jquery.form] ' + Array.prototype.join.call(arguments,''));
+};
+
+})(jQuery);
diff --git a/lib/jquery.jeditable.js b/lib/jquery.jeditable.js
new file mode 100644
index 0000000..9f0ab37
--- /dev/null
+++ b/lib/jquery.jeditable.js
@@ -0,0 +1,32 @@
+
+(function($){$.fn.editable=function(target,options){var settings={target:target,name:'value',id:'id',type:'text',width:'auto',height:'auto',event:'click',onblur:'cancel',loadtype:'GET',loadtext:'Loading...',placeholder:'Click to edit',loaddata:{},submitdata:{},ajaxoptions:{}};if(options){$.extend(settings,options);}
+var plugin=$.editable.types[settings.type].plugin||function(){};var submit=$.editable.types[settings.type].submit||function(){};var buttons=$.editable.types[settings.type].buttons||$.editable.types['defaults'].buttons;var content=$.editable.types[settings.type].content||$.editable.types['defaults'].content;var element=$.editable.types[settings.type].element||$.editable.types['defaults'].element;var reset=$.editable.types[settings.type].reset||$.editable.types['defaults'].reset;var callback=settings.callback||function(){};var onsubmit=settings.onsubmit||function(){};var onreset=settings.onreset||function(){};var onerror=settings.onerror||reset;if(!$.isFunction($(this)[settings.event])){$.fn[settings.event]=function(fn){return fn?this.bind(settings.event,fn):this.trigger(settings.event);}}
+$(this).attr('title',settings.tooltip);settings.autowidth='auto'==settings.width;settings.autoheight='auto'==settings.height;return this.each(function(){var self=this;var savedwidth=$(self).width();var savedheight=$(self).height();if(!$.trim($(this).html())){$(this).html(settings.placeholder);}
+$(this)[settings.event](function(e){if(self.editing){return;}
+$(self).removeAttr('title');if(0==$(self).width()){settings.width=savedwidth;settings.height=savedheight;}else{if(settings.width!='none'){settings.width=settings.autowidth?$(self).width():settings.width;}
+if(settings.height!='none'){settings.height=settings.autoheight?$(self).height():settings.height;}}
+if($(this).html().toLowerCase().replace(/;/,'')==settings.placeholder.toLowerCase().replace(/;/,'')){$(this).html('');}
+self.editing=true;self.revert=$(self).html();$(self).html('');var form=$('<form />');if(settings.cssclass){if('inherit'==settings.cssclass){form.attr('class',$(self).attr('class'));}else{form.attr('class',settings.cssclass);}}
+if(settings.style){if('inherit'==settings.style){form.attr('style',$(self).attr('style'));form.css('display',$(self).css('display'));}else{form.attr('style',settings.style);}}
+var input=element.apply(form,[settings,self]);var input_content;if(settings.loadurl){var t=setTimeout(function(){input.disabled=true;content.apply(form,[settings.loadtext,settings,self]);},100);var loaddata={};loaddata[settings.id]=self.id;if($.isFunction(settings.loaddata)){$.extend(loaddata,settings.loaddata.apply(self,[self.revert,settings]));}else{$.extend(loaddata,settings.loaddata);}
+$.ajax({type:settings.loadtype,url:settings.loadurl,data:loaddata,async:false,success:function(result){window.clearTimeout(t);input_content=result;input.disabled=false;}});}else if(settings.data){input_content=settings.data;if($.isFunction(settings.data)){input_content=settings.data.apply(self,[self.revert,settings]);}}else{input_content=self.revert;}
+content.apply(form,[input_content,settings,self]);input.attr('name',settings.name);buttons.apply(form,[settings,self]);$(self).append(form);plugin.apply(form,[settings,self]);$(':input:visible:enabled:first',form).focus();if(settings.select){input.select();}
+input.keydown(function(e){if(e.keyCode==27){e.preventDefault();reset.apply(form,[settings,self]);}});var t;if('cancel'==settings.onblur){input.blur(function(e){t=setTimeout(function(){reset.apply(form,[settings,self]);},500);});}else if('submit'==settings.onblur){input.blur(function(e){t=setTimeout(function(){form.submit();},200);});}else if($.isFunction(settings.onblur)){input.blur(function(e){settings.onblur.apply(self,[input.val(),settings]);});}else{input.blur(function(e){});}
+form.submit(function(e){if(t){clearTimeout(t);}
+e.preventDefault();if(false!==onsubmit.apply(form,[settings,self])){if(false!==submit.apply(form,[settings,self])){if($.isFunction(settings.target)){var str=settings.target.apply(self,[input.val(),settings]);$(self).html(str);self.editing=false;callback.apply(self,[self.innerHTML,settings]);if(!$.trim($(self).html())){$(self).html(settings.placeholder);}}else{var submitdata={};submitdata[settings.name]=input.val();submitdata[settings.id]=self.id;if($.isFunction(settings.submitdata)){$.extend(submitdata,settings.submitdata.apply(self,[self.revert,settings]));}else{$.extend(submitdata,settings.submitdata);}
+if('PUT'==settings.method){submitdata['_method']='put';}
+$(self).html(settings.indicator);var ajaxoptions={type:'POST',data:submitdata,url:settings.target,success:function(result,status){$(self).html(result);self.editing=false;callback.apply(self,[self.innerHTML,settings]);if(!$.trim($(self).html())){$(self).html(settings.placeholder);}},error:function(xhr,status,error){onerror.apply(form,[settings,self,xhr]);}}
+$.extend(ajaxoptions,settings.ajaxoptions);$.ajax(ajaxoptions);}}}
+$(self).attr('title',settings.tooltip);return false;});});this.reset=function(form){if(this.editing){if(false!==onreset.apply(form,[settings,self])){$(self).html(self.revert);self.editing=false;if(!$.trim($(self).html())){$(self).html(settings.placeholder);}
+$(self).attr('title',settings.tooltip);}}}});};$.editable={types:{defaults:{element:function(settings,original){var input=$('<input type="hidden"></input>');$(this).append(input);return(input);},content:function(string,settings,original){$(':input:first',this).val(string);},reset:function(settings,original){original.reset(this);},buttons:function(settings,original){var form=this;if(settings.submit){if(settings.submit.match(/>$/)){var submit=$(settings.submit).click(function(){if(submit.attr("type")!="submit"){form.submit();}});}else{var submit=$('<button type="submit" />');submit.html(settings.submit);}
+$(this).append(submit);}
+if(settings.cancel){if(settings.cancel.match(/>$/)){var cancel=$(settings.cancel);}else{var cancel=$('<button type="cancel" />');cancel.html(settings.cancel);}
+$(this).append(cancel);$(cancel).click(function(event){if($.isFunction($.editable.types[settings.type].reset)){var reset=$.editable.types[settings.type].reset;}else{var reset=$.editable.types['defaults'].reset;}
+reset.apply(form,[settings,original]);return false;});}}},text:{element:function(settings,original){var input=$('<input />');if(settings.width!='none'){input.width(settings.width);}
+if(settings.height!='none'){input.height(settings.height);}
+input.attr('autocomplete','off');$(this).append(input);return(input);}},textarea:{element:function(settings,original){var textarea=$('<textarea />');if(settings.rows){textarea.attr('rows',settings.rows);}else{textarea.height(settings.height);}
+if(settings.cols){textarea.attr('cols',settings.cols);}else{textarea.width(settings.width);}
+$(this).append(textarea);return(textarea);}},select:{element:function(settings,original){var select=$('<select />');$(this).append(select);return(select);},content:function(string,settings,original){if(String==string.constructor){eval('var json = '+string);for(var key in json){if(!json.hasOwnProperty(key)){continue;}
+if('selected'==key){continue;}
+var option=$('<option />').val(key).append(json[key]);$('select',this).append(option);}}
+$('select',this).children().each(function(){if($(this).val()==json['selected']||$(this).text()==original.revert){$(this).attr('selected','selected');};});}}},addInputType:function(name,input){$.editable.types[name]=input;}};})(jQuery);
\ No newline at end of file
diff --git a/lib/jquery.js b/lib/jquery.js
new file mode 100644
index 0000000..b1ae21d
--- /dev/null
+++ b/lib/jquery.js
@@ -0,0 +1,19 @@
+/*
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
+/*
+ * Sizzle CSS Selector Engine - v0.9.3
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML='   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})();
\ No newline at end of file
diff --git a/lib/jquery.localscroll.js b/lib/jquery.localscroll.js
new file mode 100644
index 0000000..fa583a4
--- /dev/null
+++ b/lib/jquery.localscroll.js
@@ -0,0 +1,9 @@
+/**
+ * jQuery.LocalScroll - Animated scrolling navigation, using anchors.
+ * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
+ * Dual licensed under MIT and GPL.
+ * Date: 3/11/2009
+ * @author Ariel Flesler
+ * @version 1.2.7
+ **/
+;(function($){var l=location.href.replace(/#.*/,'');var g=$.localScroll=function(a){$('body').localScroll(a)};g.defaults={duration:1e3,axis:'y',event:'click',stop:true,target:window,reset:true};g.hash=function(a){if(location.hash){a=$.extend({},g.defaults,a);a.hash=false;if(a.reset){var e=a.duration;delete a.duration;$(a.target).scrollTo(0,a);a.duration=e}i(0,location,a)}};$.fn.localScroll=function(b){b=$.extend({},g.defaults,b);return b.lazy?this.bind(b.event,function(a){var e=$([a.target,a.target.parentNode]).filter(d)[0];if(e)i(a,e,b)}):this.find('a,area').filter(d).bind(b.event,function(a){i(a,this,b)}).end().end();function d(){return!!this.href&&!!this.hash&&this.href.replace(this.hash,'')==l&&(!b.filter||$(this).is(b.filter))}};function i(a,e,b){var d=e.hash.slice(1),f=document.getElementById(d)||document.getElementsByName(d)[0];if(!f)return;if(a)a.preventDefault();var h=$(b.target);if(b.lock&&h.is(':animated')||b.onBefore&&b.onBefore.call(b,a,f,h)===false)return;if(b.stop)h.stop(true);if(b.hash){var j=f.id==d?'id':'name',k=$('<a> </a>').attr(j,d).css({position:'absolute',top:$(window).scrollTop(),left:$(window).scrollLeft()});f[j]='';$('body').prepend(k);location=e.hash;k.remove();f[j]=d}h.scrollTo(f,b).trigger('notify.serialScroll',[f])}})(jQuery);
\ No newline at end of file
diff --git a/lib/jquery.scrollTo.js b/lib/jquery.scrollTo.js
new file mode 100644
index 0000000..5e78778
--- /dev/null
+++ b/lib/jquery.scrollTo.js
@@ -0,0 +1,11 @@
+/**
+ * jQuery.ScrollTo - Easy element scrolling using jQuery.
+ * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
+ * Dual licensed under MIT and GPL.
+ * Date: 5/25/2009
+ * @author Ariel Flesler
+ * @version 1.4.2
+ *
+ * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
+ */
+;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);
\ No newline at end of file
diff --git a/lib/json2-min.js b/lib/json2-min.js
new file mode 100644
index 0000000..988ab6f
--- /dev/null
+++ b/lib/json2-min.js
@@ -0,0 +1,39 @@
+/*
+    http://www.JSON.org/json2.js
+    2010-11-17
+
+    Public Domain.
+
+    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+    See http://www.JSON.org/js.html
+*/
+
+if(!this.JSON){this.JSON={};}
+(function(){"use strict";function f(n){return n<10?'0'+n:n;}
+if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+
+f(this.getUTCMonth()+1)+'-'+
+f(this.getUTCDate())+'T'+
+f(this.getUTCHours())+':'+
+f(this.getUTCMinutes())+':'+
+f(this.getUTCSeconds())+'Z':null;};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
+var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
+function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
+if(typeof rep==='function'){value=rep.call(holder,key,value);}
+switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
+gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
+v=partial.length===0?'[]':gap?'[\n'+gap+
+partial.join(',\n'+gap)+'\n'+
+mind+']':'['+partial.join(',')+']';gap=mind;return v;}
+if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==='string'){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
+v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+
+mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
+if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
+rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
+return str('',{'':value});};}
+if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
+return reviver.call(holder,key,value);}
+text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
+('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
+if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
+throw new SyntaxError('JSON.parse');};}}());
\ No newline at end of file
diff --git a/lib/superfish/css/superfish.css b/lib/superfish/css/superfish.css
new file mode 100644
index 0000000..cc33fdb
--- /dev/null
+++ b/lib/superfish/css/superfish.css
@@ -0,0 +1,136 @@
+
+/*** ESSENTIAL STYLES ***/
+.sf-menu, .sf-menu * {
+	margin:			0;
+	padding:		0;
+	list-style:		none;
+}
+.sf-menu {
+	line-height:	1.0;
+}
+.sf-menu ul {
+	position:		absolute;
+	top:			-999em;
+	width:			10em; /* left offset of submenus need to match (see below) */
+}
+.sf-menu ul li {
+	width:			100%;
+}
+.sf-menu li:hover {
+	visibility:		inherit; /* fixes IE7 'sticky bug' */
+}
+.sf-menu li {
+	float:			left;
+	position:		relative;
+}
+.sf-menu a {
+	display:		block;
+	position:		relative;
+}
+.sf-menu li:hover ul,
+.sf-menu li.sfHover ul {
+	left:			0;
+	top:			2.5em; /* match top ul list item height */
+	z-index:		99;
+}
+ul.sf-menu li:hover li ul,
+ul.sf-menu li.sfHover li ul {
+	top:			-999em;
+}
+ul.sf-menu li li:hover ul,
+ul.sf-menu li li.sfHover ul {
+	left:			10em; /* match ul width */
+	top:			0;
+}
+ul.sf-menu li li:hover li ul,
+ul.sf-menu li li.sfHover li ul {
+	top:			-999em;
+}
+ul.sf-menu li li li:hover ul,
+ul.sf-menu li li li.sfHover ul {
+	left:			10em; /* match ul width */
+	top:			0;
+}
+
+/*** DEMO SKIN ***/
+.sf-menu {
+	float:			left;
+	margin-bottom:	1em;
+}
+.sf-menu a {
+	border-left:	1px solid #fff;
+	border-top:		1px solid #CFDEFF;
+	padding: 		.75em 1em;
+	text-decoration:none;
+}
+.sf-menu a, .sf-menu a:visited  { /* visited pseudo selector so IE6 applies text colour*/
+	color:			#13a;
+}
+.sf-menu li {
+	background:		#BDD2FF;
+}
+.sf-menu li li {
+	background:		#AABDE6;
+}
+.sf-menu li li li {
+	background:		#9AAEDB;
+}
+.sf-menu li:hover, .sf-menu li.sfHover,
+.sf-menu a:focus, .sf-menu a:hover, .sf-menu a:active {
+	background:		#CFDEFF;
+	outline:		0;
+}
+
+/*** arrows **/
+.sf-menu a.sf-with-ul {
+	padding-right: 	2.25em;
+	min-width:		1px; /* trigger IE7 hasLayout so spans position accurately */
+}
+.sf-sub-indicator {
+	position:		absolute;
+	display:		block;
+	right:			.75em;
+	top:			1.05em; /* IE6 only */
+	width:			10px;
+	height:			10px;
+	text-indent: 	-999em;
+	overflow:		hidden;
+	background:		url('../images/arrows-ffffff.png') no-repeat -10px -100px; /* 8-bit indexed alpha png. IE6 gets solid image only */
+}
+a > .sf-sub-indicator {  /* give all except IE6 the correct values */
+	top:			.8em;
+	background-position: 0 -100px; /* use translucent arrow for modern browsers*/
+}
+/* apply hovers to modern browsers */
+a:focus > .sf-sub-indicator,
+a:hover > .sf-sub-indicator,
+a:active > .sf-sub-indicator,
+li:hover > a > .sf-sub-indicator,
+li.sfHover > a > .sf-sub-indicator {
+	background-position: -10px -100px; /* arrow hovers for modern browsers*/
+}
+
+/* point right for anchors in subs */
+.sf-menu ul .sf-sub-indicator { background-position:  -10px 0; }
+.sf-menu ul a > .sf-sub-indicator { background-position:  0 0; }
+/* apply hovers to modern browsers */
+.sf-menu ul a:focus > .sf-sub-indicator,
+.sf-menu ul a:hover > .sf-sub-indicator,
+.sf-menu ul a:active > .sf-sub-indicator,
+.sf-menu ul li:hover > a > .sf-sub-indicator,
+.sf-menu ul li.sfHover > a > .sf-sub-indicator {
+	background-position: -10px 0; /* arrow hovers for modern browsers*/
+}
+
+/*** shadows for all but IE6 ***/
+.sf-shadow ul {
+	background:	url('../images/shadow.png') no-repeat bottom right;
+	padding: 0 8px 9px 0;
+	-moz-border-radius-bottomleft: 17px;
+	-moz-border-radius-topright: 17px;
+	-webkit-border-top-right-radius: 17px;
+	-webkit-border-bottom-left-radius: 17px;
+}
+.sf-shadow ul.sf-shadow-off {
+	background: transparent;
+}
diff --git a/lib/superfish/images/arrows-ffffff-rtl.png b/lib/superfish/images/arrows-ffffff-rtl.png
new file mode 100644
index 0000000..2fe14a3
Binary files /dev/null and b/lib/superfish/images/arrows-ffffff-rtl.png differ
diff --git a/lib/superfish/images/arrows-ffffff.png b/lib/superfish/images/arrows-ffffff.png
new file mode 100644
index 0000000..995df52
Binary files /dev/null and b/lib/superfish/images/arrows-ffffff.png differ
diff --git a/lib/superfish/images/shadow.png b/lib/superfish/images/shadow.png
new file mode 100644
index 0000000..c04d21b
Binary files /dev/null and b/lib/superfish/images/shadow.png differ
diff --git a/lib/superfish/js/superfish.js b/lib/superfish/js/superfish.js
new file mode 100644
index 0000000..c6a9c7d
--- /dev/null
+++ b/lib/superfish/js/superfish.js
@@ -0,0 +1,121 @@
+
+/*
+ * Superfish v1.4.8 - jQuery menu widget
+ * Copyright (c) 2008 Joel Birch
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * 	http://www.opensource.org/licenses/mit-license.php
+ * 	http://www.gnu.org/licenses/gpl.html
+ *
+ * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
+ */
+
+;(function($){
+	$.fn.superfish = function(op){
+
+		var sf = $.fn.superfish,
+			c = sf.c,
+			$arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
+			over = function(){
+				var $$ = $(this), menu = getMenu($$);
+				clearTimeout(menu.sfTimer);
+				$$.showSuperfishUl().siblings().hideSuperfishUl();
+			},
+			out = function(){
+				var $$ = $(this), menu = getMenu($$), o = sf.op;
+				clearTimeout(menu.sfTimer);
+				menu.sfTimer=setTimeout(function(){
+					o.retainPath=($.inArray($$[0],o.$path)>-1);
+					$$.hideSuperfishUl();
+					if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
+				},o.delay);	
+			},
+			getMenu = function($menu){
+				var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
+				sf.op = sf.o[menu.serial];
+				return menu;
+			},
+			addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); };
+			
+		return this.each(function() {
+			var s = this.serial = sf.o.length;
+			var o = $.extend({},sf.defaults,op);
+			o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
+				$(this).addClass([o.hoverClass,c.bcClass].join(' '))
+					.filter('li:has(ul)').removeClass(o.pathClass);
+			});
+			sf.o[s] = sf.op = o;
+			
+			$('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
+				if (o.autoArrows) addArrow( $('>a:first-child',this) );
+			})
+			.not('.'+c.bcClass)
+				.hideSuperfishUl();
+			
+			var $a = $('a',this);
+			$a.each(function(i){
+				var $li = $a.eq(i).parents('li');
+				$a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
+			});
+			o.onInit.call(this);
+			
+		}).each(function() {
+			var menuClasses = [c.menuClass];
+			if (sf.op.dropShadows  && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
+			$(this).addClass(menuClasses.join(' '));
+		});
+	};
+
+	var sf = $.fn.superfish;
+	sf.o = [];
+	sf.op = {};
+	sf.IE7fix = function(){
+		var o = sf.op;
+		if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
+			this.toggleClass(sf.c.shadowClass+'-off');
+		};
+	sf.c = {
+		bcClass     : 'sf-breadcrumb',
+		menuClass   : 'sf-js-enabled',
+		anchorClass : 'sf-with-ul',
+		arrowClass  : 'sf-sub-indicator',
+		shadowClass : 'sf-shadow'
+	};
+	sf.defaults = {
+		hoverClass	: 'sfHover',
+		pathClass	: 'overideThisToUse',
+		pathLevels	: 1,
+		delay		: 800,
+		animation	: {opacity:'show'},
+		speed		: 'normal',
+		autoArrows	: true,
+		dropShadows : true,
+		disableHI	: false,		// true disables hoverIntent detection
+		onInit		: function(){}, // callback functions
+		onBeforeShow: function(){},
+		onShow		: function(){},
+		onHide		: function(){}
+	};
+	$.fn.extend({
+		hideSuperfishUl : function(){
+			var o = sf.op,
+				not = (o.retainPath===true) ? o.$path : '';
+			o.retainPath = false;
+			var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
+					.find('>ul').hide().css('visibility','hidden');
+			o.onHide.call($ul);
+			return this;
+		},
+		showSuperfishUl : function(){
+			var o = sf.op,
+				sh = sf.c.shadowClass+'-off',
+				$ul = this.addClass(o.hoverClass)
+					.find('>ul:hidden').css('visibility','visible');
+			sf.IE7fix.call($ul);
+			o.onBeforeShow.call($ul);
+			$ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
+			return this;
+		}
+	});
+
+})(jQuery);
diff --git a/lib/swfobject.js b/lib/swfobject.js
new file mode 100644
index 0000000..87e6155
--- /dev/null
+++ b/lib/swfobject.js
@@ -0,0 +1,4 @@
+/*	SWFObject v2.2 <http://code.google.com/p/swfobject/> 
+	is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> 
+*/
+var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+encodeURI(O.location).toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();
\ No newline at end of file
diff --git a/lib/uploadify/cancel.png b/lib/uploadify/cancel.png
new file mode 100644
index 0000000..1c062ae
Binary files /dev/null and b/lib/uploadify/cancel.png differ
diff --git a/lib/uploadify/jquery.uploadify.min.js b/lib/uploadify/jquery.uploadify.min.js
new file mode 100644
index 0000000..c7edbeb
--- /dev/null
+++ b/lib/uploadify/jquery.uploadify.min.js
@@ -0,0 +1,37 @@
+/*
+Uploadify v2.1.0
+Release Date: August 24, 2009
+
+Copyright (c) 2009 Ronnie Garcia, Travis Nickels
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+jQuery&&function(a){a.extend(a.fn,{uploadify:function(e){a(this).each(function(){settings=a.extend({id:a(this).attr("id"),uploader:"uploadify.swf",script:"uploadify.php",expressInstall:null,folder:"",height:30,width:110,cancelImg:"cancel.png",wmode:"opaque",scriptAccess:"sameDomain",fileDataName:"Filedata",method:"POST",queueSizeLimit:999,simUploadLimit:1,queueID:!1,displayData:"percentage",onInit:function(){},onSelect:function(){},onQueueFull:function(){},onCheck:function(){},onCancel:function(){},
+onError:function(){},onProgress:function(){},onComplete:function(){},onAllComplete:function(){}},e);var f=location.pathname,f=f.split("/");f.pop();var f=f.join("/")+"/",b={};b.uploadifyID=settings.id;b.pagepath=f;settings.buttonImg&&(b.buttonImg=escape(settings.buttonImg));settings.buttonText&&(b.buttonText=escape(settings.buttonText));settings.rollover&&(b.rollover=!0);b.script=settings.script;b.folder=escape(settings.folder);if(settings.scriptData){var g="",j;for(j in settings.scriptData)g+="&"+
+j+"="+settings.scriptData[j];b.scriptData=escape(g.substr(1))}b.width=settings.width;b.height=settings.height;b.wmode=settings.wmode;b.method=settings.method;b.queueSizeLimit=settings.queueSizeLimit;b.simUploadLimit=settings.simUploadLimit;settings.hideButton&&(b.hideButton=!0);settings.fileDesc&&(b.fileDesc=settings.fileDesc);settings.fileExt&&(b.fileExt=settings.fileExt);settings.multi&&(b.multi=!0);settings.auto&&(b.auto=!0);settings.sizeLimit&&(b.sizeLimit=settings.sizeLimit);settings.checkScript&&
+(b.checkScript=settings.checkScript);settings.fileDataName&&(b.fileDataName=settings.fileDataName);settings.queueID&&(b.queueID=settings.queueID);!1!==settings.onInit()&&(a(this).css("display","none"),a(this).after('<div id="'+a(this).attr("id")+'Uploader"></div>'),swfobject.embedSWF(settings.uploader,settings.id+"Uploader",settings.width,settings.height,"9.0.24",settings.expressInstall,b,{quality:"high",wmode:settings.wmode,allowScriptAccess:settings.scriptAccess}),!1==settings.queueID&&a("#"+a(this).attr("id")+
+"Uploader").after('<div id="'+a(this).attr("id")+'Queue" class="uploadifyQueue"></div>'));"function"==typeof settings.onOpen&&a(this).bind("uploadifyOpen",settings.onOpen);a(this).bind("uploadifySelect",{action:settings.onSelect,queueID:settings.queueID},function(k,d,b){if(!1!==k.data.action(k,d,b)){var c=0.01*Math.round(100*(b.size/1024)),h="KB";1E3<c&&(c=0.01*Math.round(0.1*c),h="MB");c=c.toString().split(".");c=1<c.length?c[0]+"."+c[1].substr(0,2):c[0];fileName=20<b.name.length?b.name.substr(0,
+20)+"...":b.name;queue="#"+a(this).attr("id")+"Queue";k.data.queueID&&(queue="#"+k.data.queueID);a(queue).append('<div id="'+a(this).attr("id")+d+'" class="uploadifyQueueItem">\t\t\t\t\t\t\t\t<div class="cancel">\t\t\t\t\t\t\t\t\t<a href="javascript:jQuery(\'#'+a(this).attr("id")+"').uploadifyCancel('"+d+'\')"><img src="'+settings.cancelImg+'" border="0" /></a>\t\t\t\t\t\t\t\t</div>\t\t\t\t\t\t\t\t<span class="fileName"></span><span class="percentage"></span>\t\t\t\t\t\t\t\t<div class="uploadifyProgress">\t\t\t\t\t\t\t\t\t<div id="'+
+a(this).attr("id")+d+'ProgressBar" class="uploadifyProgressBar">\x3c!--Progress Bar--\x3e</div>\t\t\t\t\t\t\t\t</div>\t\t\t\t\t\t\t</div>');a("div#"+a(this).attr("id")+d+" span.fileName").text(fileName+" ("+c+h+")")}});"function"==typeof settings.onSelectOnce&&a(this).bind("uploadifySelectOnce",settings.onSelectOnce);a(this).bind("uploadifyQueueFull",{action:settings.onQueueFull},function(a,b){!1!==a.data.action(a,b)&&alert("The queue is full.  The max size is "+b+".")});a(this).bind("uploadifyCheckExist",
+{action:settings.onCheck},function(b,d,m,c,h){var e={},e=m;e.folder=f+c;if(h)for(var g in m)var j=g;a.post(d,e,function(f){for(var e in f)!1!==b.data.action(b,d,m,c,h)&&(confirm("Do you want to replace the file "+f[e]+"?")||document.getElementById(a(b.target).attr("id")+"Uploader").cancelFileUpload(e,!0,!0));h?document.getElementById(a(b.target).attr("id")+"Uploader").startFileUpload(j,!0):document.getElementById(a(b.target).attr("id")+"Uploader").startFileUpload(null,!0)},"json")});a(this).bind("uploadifyCancel",
+{action:settings.onCancel},function(b,d,f,c,e){!1!==b.data.action(b,d,f,c,e)&&a("#"+a(this).attr("id")+d).fadeOut(!0==e?0:250,function(){a(this).remove()})});"function"==typeof settings.onClearQueue&&a(this).bind("uploadifyClearQueue",settings.onClearQueue);var l=[];a(this).bind("uploadifyError",{action:settings.onError},function(b,d,e,c){!1!==b.data.action(b,d,e,c)&&(l.push([d,e,c]),a("#"+a(this).attr("id")+d+" .percentage").text(" - "+c.type+" Error"),a("#"+a(this).attr("id")+d).addClass("uploadifyError"))});
+a(this).bind("uploadifyProgress",{action:settings.onProgress,toDisplay:settings.displayData},function(b,d,e,c){!1!==b.data.action(b,d,e,c)&&(a("#"+a(this).attr("id")+d+"ProgressBar").css("width",c.percentage+"%"),"percentage"==b.data.toDisplay&&(displayData=" - "+c.percentage+"%"),"speed"==b.data.toDisplay&&(displayData=" - "+c.speed+"KB/s"),null==b.data.toDisplay&&(displayData=" "),a("#"+a(this).attr("id")+d+" .percentage").text(displayData))});a(this).bind("uploadifyComplete",{action:settings.onComplete},
+function(b,d,e,c,f){!1!==b.data.action(b,d,e,unescape(c),f)&&(a("#"+a(this).attr("id")+d+" .percentage").text(" - Completed"),a("#"+a(this).attr("id")+d).fadeOut(250,function(){a(this).remove()}))});"function"==typeof settings.onAllComplete&&a(this).bind("uploadifyAllComplete",{action:settings.onAllComplete},function(a,b){!1!==a.data.action(a,b)&&(l=[])})})},uploadifySettings:function(e,f,b){var g=!1;a(this).each(function(){if("scriptData"==e&&null!=f){var d=b?f:a.extend(settings.scriptData,f),c=
+"",h;for(h in d)c+="&"+h+"="+escape(d[h]);f=c.substr(1)}g=document.getElementById(a(this).attr("id")+"Uploader").updateSettings(e,f)});if(null==f){if("scriptData"==e){for(var j=unescape(g).split("&"),l={},k=0;k<j.length;k++){var d=j[k].split("=");l[d[0]]=d[1]}g=l}return g}},uploadifyUpload:function(e){a(this).each(function(){document.getElementById(a(this).attr("id")+"Uploader").startFileUpload(e,!1)})},uploadifyCancel:function(e){a(this).each(function(){document.getElementById(a(this).attr("id")+
+"Uploader").cancelFileUpload(e,!0,!1)})},uploadifyClearQueue:function(){a(this).each(function(){document.getElementById(a(this).attr("id")+"Uploader").clearFileUploadQueue(!1)})}})}(jQuery); 
diff --git a/lib/uploadify/uploadify.allglyphs.swf.php b/lib/uploadify/uploadify.allglyphs.swf.php
new file mode 100644
index 0000000..f140dec
--- /dev/null
+++ b/lib/uploadify/uploadify.allglyphs.swf.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+// Redirect the initial request to strip off any query parameters or URL fragments
+// We know it's an initial request if the token is missing
+if (empty($_GET["token"])) {
+  // We have not yet redirected
+  $rand = md5(rand());
+  setcookie("uploadify_token", $rand);
+  header("Location: uploadify.allglyphs.swf.php?token=$rand#.");
+  exit;
+}
+
+// If the token exists but there's no cookie, then this is a bogus token
+// or the user does not support cookies.  Ignore this request.
+if (empty($_COOKIE["uploadify_token"])) {
+  exit;
+}
+
+// If the token exists but it doesn't match our cookie, then this is a bogus
+// request.  Ignore this request.
+if ($_GET["token"] != $_COOKIE["uploadify_token"]) {
+  exit;
+}
+
+// This is a legitimate request.  Serve it, but disallow caching.
+header("Content-Type: application/x-shockwave-flash");
+header("Cache-Control: no-cache, no-store, must-revalidate");
+setcookie("uploadify_token", "", time() - 3600);
+print base64_decode("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McaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkU985gtf+cZ3nnjmhVfeeOeDgGn9CSSIYEIIJYxwIogkimhiiCWOeBJIJIlkUkgljXQyyCSLbHLIJY98CiikiGJKKKWMciqopIpqaqiljnoaaKSJZlpopY12Ouiki2566KWPfgYYZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545BOf+cJXvvGdJ5554ZU33vkg4E/pTyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI5/4zBe+8o3vPPHMC6+88c4HATP6E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJF9300Esf/QwwyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyCc+84WvfOM7TzzzwitvvPNBwJ/Wn0CCCCaEUMIIJ4JIoogmhljiiCeBRJJIJoVU0kgng0yyyCaHXPLIp4BCiiimhFLKKKeCSqqopoZa6qingUaaaKaFVtpop4NOuuimh1766GeAQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBRz7xmS985RvfeeKZF155450PAmb1J5AgggkhlDDCiSCSKKKJIZY44kkgkSSSSSGVNNLJIJMssskhlzzyKaCQIoopoZQyyqmgkiqqqaGWOuppoJEmmmmhlTba6aCTLrrpoZc++hlgkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkU985gtf+cZ3nnjmhVfeeOeDgD+jP4EEEUwIoYQRTgSRRBFN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Dzzyic984Svf+M4Tz7zwyhvvfBDwN/UnkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRT3zmC1/5xneeeOaFV95454OAHf0JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkE5/5wle+8Z0nnnnhlTfe+SDgb+lPIEEEE0IoYYQTQSRRRBNDLHHEk0AiSSSTQipppJNBJllkk0MueeRTQCFFFFNCKWWUU0ElVVRTQy111NNAI00000IrbbTTQSdddNNDL330M8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88Ajn/jMF77yje888cwLr7zxzgcBu/oTSBDBhBBKGOFEEEkU0cQQSxzxJJBIEsmkkEoa6WSQSRbZ5JBLHvkUUEgRxZRQShnlVFBJFdXUUEsd9TTQSBPNtNBKG+100EkX3fTQSx/9DDDIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIJz7zha984ztPPPPCK2+880HA39afQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHPvGZL3zlG9954pkXXnnjnQ8C9vQnkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGV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EkkimRRSSSOdDDLJIpsccskjnwIKKaKYEkopo5wKKqmimhpqqaOeBhppopkWWmmjnQ466aKbHnrpo58BBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvkj4MR/AgkimBBCCSOcCCKJIpoYYokjngQSSSKZFFJJI50MMskimxxyySOfAgopopgSSimjnAoqqaKaGmqpo54GGmmimRZaaaOdDjrpopseeumjnwEGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++SPgn/hPIEEEE0IoYYQTQSRRRBNDLHHEk0AiSSSTQipppJNBJllkk0MueeRTQCFFFFNCKWWUU0ElVVRTQy111NNAI00000IrbbTTQSdddNNDL330M8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwSc+k8gQQQTQihhhBNBJFFEE0MsccSTQCJJJJNCKmmkk0EmWWSTQy555FNAIUUUU0IpZZRTQSVVVFNDLXXU00AjTTTTQitttNNBJ11000MvffQzwCBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/BPxT/wkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10Msgki2xyyCWPfAoopIhiSiiljHIqqKSKamqopY56GmikiWZaaKWNdjropItueuilj34GGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgDP/CSSIYEIIJYxwIogkimhiiCWOeBJIJIlkUkgljXQyyCSLbHLIJY98CiikiGJKKKWMciqopIpqaqiljnoaaKSJZlpopY12Ouiki2566KWPfgYYZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZItt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HPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwH/0X8CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I+DVfwIJIpgQQgkjnAgiiSKaGGKJI54EEkkimRRSSSOdDDLJIpsccskjnwIKKaKYEkopo5wKKqmimhpqqaOeBhppopkWWmmjnQ466aKbHnrpo58BBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvkj4D/5TyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38EvPlPIEEEE0IoYYQTQSRRRBNDLHHEk0AiSSSTQipppJNBJllkk0MueeRTQCFFFFNCKWWUU0ElVVRTQy111NNAI00000IrbbTTQSdddNNDL330M8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwT8Z/8JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4B3/wkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10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Gmqpo54GGmmimRZaaaOdDjrpopseeumjnwEGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++SPg138CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I+B/+U8gQQQTQihhhBNBJFFEE0MsccSTQCJJJJNCKmmkk0EmWWSTQy555FNAIUUUU0IpZZRTQSVVVFNDLXXU00AjTTTTQitttNNBJ11000MvffQzwCBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/BPz5TyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38E/IPAf/AP+T8FEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wREOA/gQQRTAihhBFOBJFEEU0MscQRTwKJJJFMCqmkkU4GmWSRTQ655JFPAYUUUUwJpZRRTgWVVFFNDbXUUU8DjTTRTAuttNFOB5100U0PvfTRzwCDDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//BHwf/lPIEEEE0IoYYQTQSRRRBPD/2aIDlsBAADAwKadOTMzMzMzM2dmZmZmZmZmTpIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkex/eL3ixxBFPAokkkUwKqaSRTgaZZJFNDrnkkU8BhRRRTAmllFFOBZVUUU0NtdRRTwONNNFMC6200U4HnXTRTQ+99NHPAIMMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8EfAP/BNIEMGEEEoY4UQQSRTRxBBLHPEkkEgSyaSQShrpZJBJFtnkkEse+RRQSBHFlFBKGeVUUEkV1dRQSx31NNBIE8200Eob7XTQSRfd9NBLH/0MMMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAf+PfwIJIpgQQgkjnAgiiSKaGGKJI54EEkkimRRSSSOdDDLJIpsccskjnwIKKaKYEkopo5wKKqmimhpqqaOeBhppopkWWmmjnQ466aKbHnrpo58BBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvkjINA/gQQRTAihhBFOBJFEEU0MscQRTwKJJJFMCqmkkU4GmWSRTQ655JFPAYUUUUwJpZRRTgWVVFFNDbXUUU8DjTTRTAuttNFOB5100U0PvfTRzwCDDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//BHwD/0TSBDBhBBKGOFEEEkU0cQQSxzxJJBIEsmkkEoa6WSQSRbZ5JBLHvkUUEgRxZRQShnlVFBJFdXUUEsd9TTQSBPNtNBKG+100EkX3fTQSx/9DDDIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwFB/gkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10Msgki2xyyCWPfAoopIhiSiiljHIqqKSKamqopY56GmikiWZaaKWNdjropItueuilj34GGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgP/XP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wREOyfQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gj4R/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4AQ/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHwD/2TyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38EhPonkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwL+iX8CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375IyDMP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wR8E/9E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJF9300Esf/QwwyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8B4f4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4B/5p9AgggmhFDCCCeCSKKIJoZY4ogngUSSSCaFVNJIJ4NMssgmh1zyyKeAQooopoRSyiingkqqqKaGWuqop4FGmmimhVbaaKeDTrropode+uhngEGGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+CIjwTyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38E/HP/BBJEMCGEEkY4EUQSRTQxxBJHPAkkkkQyKaSSRjoZZJJFNjnkkkc+BRRSRDEllFJGORVUUkU1NdRSRz0NNNJEMy200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88kdApH8CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I+Bf+CeQIIIJIZQwwokgkiiiiSGWOOJJIJEkkkkhlTTSySCTLLLJIZc88imgkCKKKaGUMsqpoJIqqqmhljrqaaCRJpppoZU22umgky666aGXPvoZYJAhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/AqL8E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJF9300Esf/QwwyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8B/9I/gQQRTAihhBFOBJFEEU0MscQRTwKJJJFMCqmkkU4GmWSRTQ655JFPAYUUUUwJpZRRTgWVVFFNDbXUUU8DjTTRTAuttNFOB5100U0PvfTRzwCDDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//BEQ7Z9AgggmhFDCCCeCSKKIJoZY4ogngUSSSCaFVNJIJ4NMssgmh1zyyKeAQooopoRSyiingkqqqKaGWuqop4FGmmimhVbaaKeDTrropode+uhngEGGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+CPhX/gkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10Msgki2xyyCWPfAoopIhiSiiljHIqqKSKamqopY56GmikiWZaaKWNdjropItueuilj34GGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgBj/BBJEMCGEEkY4EUQSRTQxxBJHPAkkkkQyKaSSRjoZZJJFNjnkkkc+BRRSRDEllFJGORVUUkU1NdRSRz0NNNJEMy200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88kfAv/ZPIEEEE0IoYYQTQSRRRBNDLHHEk0AiSSSTQipppJNBJllkk0MueeRTQCFFFFNCKWWUU0ElVVRTQy111NNAI00000IrbbTTQSdddNNDL330M8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwTE+ieQIIIJIZQwwokgkiiiiSGWOOJJIJEkkkkhlTTSySCTLLLJIZc88imgkCKKKaGUMsqpoJIqqqmhljrqaaCRJpppoZU22umgky666aGXPvoZYJAhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Av6NfwIJIpgQQgkjnAgiiSKaGGKJI54EEkkimRRSSSOdDDLJIpsccskjnwIKKaKYEkopo5wKKqmimhpqqaOeBhppopkWWmmjnQ466aKbHnrpo58BBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvkjIM4/gQQRTAihhBFOBJFEEU0MscQRTwKJJJFMCqmkkU4GmWSRTQ655JFPAYUUUUwJpZRRTgWVVFFNDbXUUU8DjTTRTAuttNFOB5100U0PvfTRzwCDDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//BHwb/0TSBDBhBBKGOFEEEkU0cQQSxzxJJBIEsmkkEoa6WSQSRbZ5JBLHvkUUEgRxZRQShnlVFBJFdXUUEsd9TTQSBPNtNBKG+100EkX3fTQSx/9DDDIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwHx/gkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10Msgki2xyyCWPfAoopIhiSiiljHIqqKSKamqopY56GmikiWZaaKWNdjropItueuilj34GGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgP/PP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wRkOCfQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gj4d/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4BE/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHwL/3TyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38EJPknkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwL+g38CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375IyDZP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wR8B/9E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJF9300Esf/QwwyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8BKf4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4D/5J9AgggmhFDCCCeCSKKIJoZY4ogngUSSSCaFVNJIJ4NMssgmh1zyyKeAQooopoRSyiingkqqqKaGWuqop4FGmmimhVbaaKeDTrropode+uhngEGGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+CEj1TyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38E/Gf/BBJEMCGEEkY4EUQSRTQxxBJHPAkkkkQyKaSSRjoZZJJFNjnkkkc+BRRSRDEllFJGORVUUkU1NdRSRz0NNNJEMy200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88kdAmn8CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I+C/+CeQIIIJIZQwwokgkiiiiSGWOOJJIJEkkkkhlTTSySCTLLLJIZc88imgkCKKKaGUMsqpoJIqqqmhljrqaaCRJpppoZU22umgky666aGXPvoZYJAhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/AtL9E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJF9300Esf/QwwyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8B/9U/gQQRTAihhBFOBJFEEU0MscQRTwKJJJFMCqmkkU4GmWSRTQ655JFPAYUUUUwJpZRRTgWVVFFNDbXUUU8DjTTRTAuttNFOB5100U0PvfTRzwCDDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//BGQ4Z9AgggmhFDCCCeCSKKIJoZY4ogngUSSSCaFVNJIJ4NMssgmh1zyyKeAQooopoRSyiingkqqqKaGWuqop4FGmmimhVbaaKeDTrropode+uhngEGGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+CPhv/gkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10Msgki2xyyCWPfAoopIhiSiiljHIqqKSKamqopY56GmikiWZaaKWNdjropItueuilj34GGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgEz/BBJEMCGEEkY4EUQSRTQxxBJHPAkkkkQyKaSSRjoZZJJFNjnkkkc+BRRSRDEllFJGORVUUkU1NdRSRz0NNNJEMy200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88kfAf/dPIEEEE0IoYYQTQSRRRBNDLHHEk0AiSSSTQipppJNBJllkk0MueeRTQCFFFFNCKWWUU0ElVVRTQy111NNAI00000IrbbTTQSdddNNDL330M8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwRk+SeQIIIJIZQwwokgkiiiiSGWOOJJIJEkkkkhlTTSySCTLLLJIZc88imgkCKKKaGUMsqpoJIqqqmhljrqaaCRJpppoZU22umgky666aGXPvoZYJAhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Av6HfwIJIpgQQgkjnAgiiSKaGGKJI54EEkkimRRSSSOdDDLJIpsccskjnwIKKaKYEkopo5wKKqmimhpqqaOeBhppopkWWmmjnQ466aKbHnrpo58BBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvkjINs/gQQRTAihhBFOBJFEEU0MscQRTwKJJJFMCqmkkU4GmWSRTQ655JFPAYUUUUwJpZRRTgWVVFFNDbXUUU8DjTTRTAuttNFOB5100U0PvfTRzwCDDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//BHwP/0TSBDBhBBKGOFEEEkU0cQQSxzxJJBIEsmkkEoa6WSQSRbZ5JBLHvkUUEgRxZRQShnlVFBJFdXUUEsd9TTQSBPNtNBKG+100EkX3fTQSx/9DDDIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwE5/gkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10Msgki2xyyCWPfAoopIhiSiiljHIqqKSKamqopY56GmikiWZaaKWNdjropItueuilj34GGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgP/ln0CCCCaEUMIIJ4JIoogmhljiiCeBRJJIJoVU0kgng0yyyCaHXPLIp4BCiiimhFLKKKeCSqqopoZa6qingUaaaKaFVtpop4NOuuimh1766GeAQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4IyPVPIEEEE0IoYYQTQSRRRBNDLHHEk0AiSSSTQipppJNBJllkk0MueeRTQCFFFFNCKWWUU0ElVVRTQy111NNAI00000IrbbTTQSdddNNDL330M8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwT8b/8EEkQwIYQSRjgRRBJFNDHEEkc8CSSSRDIppJJGOhlkkkU2OeSSRz4FFFJEMSWUUkY5FVRSRTU11FJHPQ000kQzLbTSRjsddNJFNz300kc/AwwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyR0CefwIJIpgQQgkjnAgiiSKaGGKJI54EEkkimRRSSSOdDDLJIpsccskjnwIKKaKYEkopo5wKKqmimhpqqaOeBhppopkWWmmjnQ466aKbHnrpo58BBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvkj4P/4J5AgggkhlDDCiSCSKKKJIZY44kkgkSSSSSGVNNLJIJMssskhlzzyKaCQIoopoZQyyqmgkiqqqaGWOuppoJEmmmmhlTba6aCTLrrpoZc++hlgkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8C8v0TSBDBhBBKGOFEEEkU0cQQSxzxJJBIEsmkkEoa6WSQSRbZ5JBLHvkUUEgRxZRQShnlVFBJFdXUUEsd9TTQSBPNtNBKG+100EkX3fTQSx/9DDDIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwH/v38CCSKYEEIJI5wIIokimpj/yxAdrQIAAIChzYMkSZIkSZIkSZIkSTIzMzMzMzPXNTMzMzMzMzMzSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZLsPJwvOMQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHQIF/AgkimBBCCSOcCCKJIpoYYokjngQSSSKZFFJJI50MMskimxxyySOfAgopopgSSimjnAoqqaKaGmqpo54GGmmimRZaaaOdDjrpopseeumjnwEGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++SPgH/gnkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwIK/RNIEMGEEEoY4UQQSRTRxBBLHPEkkEgSyaSQShrpZJBJFtnkkEse+RRQSBHFlFBKGeVUUEkV1dRQSx31NNBIE8200Eob7XTQSRfd9NBLH/0MMMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAf/QP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wRUOSfQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gj4R/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Bi/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHwD/2TyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38ElPgnkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwL+iX8CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I6DUP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wR8E/9E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJF9300Esf/QwwyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8BZf4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4B/5p9AgggmhFDCCCeCSKKIJoZY4ogngUSSSCaFVNJIJ4NMssgmh1zyyKeAQooopoRSyiingkqqqKaGWuqop4FGmmimhVbaaKeDTrropode+uhngEGGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+CCj3TyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38E/HP/BBJEMCGEEkY4EUQSRTQxxBJHPAkkkkQyKaSSRjoZZJJFNjnkkkc+BRRSRDEllFJGORVUUkU1NdRSRz0NNNJEMy200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88kdAhX8CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I+Bf+CeQIIIJIZQwwokgkiiiiSGWOOJJIJEkkkkhlTTSySCTLLLJIZc88imgkCKKKaGUMsqpoJIqqqmhljrqaaCRJpppoZU22umgky666aGXPvoZYJAhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Air9E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJF9300Esf/QwwyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8B/9I/gQQRTAihhBFOBJFEEU0MscQRTwKJJJFMCqmkkU4GmWSRTQ655JFPAYUUUUwJpZRRTgWVVFFNDbXUUU8DjTTRTAuttNFOB5100U0PvfTRzwCDDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//BFQ5Z9AgggmhFDCCCeCSKKIJoZY4ogngUSSSCaFVNJIJ4NMssgmh1zyyKeAQooopoRSyiingkqqqKaGWuqop4FGmmimhVbaaKeDTrropode+uhngEGGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+CPhX/gkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10Msgki2xyyCWPfAoopIhiSiiljHIqqKSKamqopY56GmikiWZaaKWNdjropItueuilj34GGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgGr/BBJEMCGEEkY4EUQSRTQxxBJHPAkkkkQyKaSSRjoZZJJFNjnkkkc+BRRSRDEllFJGORVUUkU1NdRSRz0NNNJEMy200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88kfAv/ZPIEEEE0IoYYQTQSRRRBNDLHHEk0AiSSSTQipppJNBJllkk0MueeRTQCFFFFNCKWWUU0ElVVRTQy111NNAI00000IrbbTTQSdddNNDL330M8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwTU+CeQIIIJIZQwwokgkiiiiSGWOOJJIJEkkkkhlTTSySCTLLLJIZc88imgkCKKKaGUMsqpoJIqqqmhljrqaaCRJpppoZU22umgky666aGXPvoZYJAhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Av6NfwIJIpgQQgkjnAgiiSKaGGKJI54EEkkimRRSSSOdDDLJIpsccskjnwIKKaKYEkopo5wKKqmimhpqqaOeBhppopkWWmmjnQ466aKbHnrpo58BBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvkjoNY/gQQRTAihhBFOBJFEEU0MscQRTwKJJJFMCqmkkU4GmWSRTQ655JFPAYUUUUwJpZRRTgWVVFFNDbXUUU8DjTTRTAuttNFOB5100U0PvfTRzwCDDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//BHw//knkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwLq/BNIEMGEEEoY4UQQSRTRxBBLHPEkkEgSyaSQShrpZJBJFtnkkEse+RRQSBHFlFBKGeVUUEkV1dRQSx31NNBIE8200Eob7XTQSRfd9NBLH/0MMMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAf+/fwIJIpgQQgkjnAgiiSKaGGKJI54EEkkimRRSSSOdDDLJIpsccskjnwIKKaKYEkopo5wKKqmimhpqqaOeBhppopkWWmmjnQ466aKbHnrpo58BBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvkjoN4/gQQRTAihhBFOBJFEEU0MscQRTwKJJJFMCqmkkU4GmWSRTQ655JFPAYUUUUwJpZRRTgWVVFFNDbXUUU8DjTTRTAuttNFOB5100U0PvfTRzwCDDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//BHwb/0TSBDBhBBKGOFEEEkU0cQQSxzxJJBIEsmkkEoa6WSQSRbZ5JBLHvkUUEgRxZRQShnlVFBJFdXUUEsd9TTQSBPNtNBKG+100EkX3fTQSx/9DDDIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwEN/gkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10Msgki2xyyCWPfAoopIhiSiiljHIqqKSKamqopY56GmikiWZaaKWNdjropItueuilj34GGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgH/nn0CCCCaEUMIIJ4JIoogmhljiiCeBRJJIJoVU0kgng0yyyCaHXPLIp4BCiiimhFLKKKeCSqqopoZa6qingUaaaKaFVtpop4NOuuimh1766GeAQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4IaPRPIEEEE0IoYYQTQSRRRBNDLHHEk0AiSSSTQipppJNBJllkk0MueeRTQCFFFFNCKWWUU0ElVVRTQy111NNAI00000IrbbTTQSdddNNDL330M8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwT8e/8EEkQwIYQSRjgRRBJFNDHEEkc8CSSSRDIppJJGOhlkkkU2OeSSRz4FFFJEMSWUUkY5FVRSRTU11FJHPQ000kQzLbTSRjsddNJFNz300kc/AwwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyR0CTfwIJIpgQQgkjnAgiiSKaGGKJI54EEkkimRRSSSOdDDLJIpsccskjnwIKKaKYEkopo5wKKqmimhpqqaOeBhppopkWWmmjnQ466aKbHnrpo58BBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvkj4D/4J5AgggkhlDDCiSCSKKKJIZY44kkgkSSSSSGVNNLJIJMssskhlzzyKaCQIoopoZQyyqmgkiqqqaGWOuppoJEmmmmhlTba6aCTLrrpoZc++hlgkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8Cmv0TSBDBhBBKGOFEEEkU0cQQSxzxJJBIEsmkkEoa6WSQSRbZ5JBLHvkUUEgRxZRQShnlVFBJFdXUUEsd9TTQSBPNtNBKG+100EkX3fTQSx/9DDDIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwH/0T+BBBFMCKGEEU4EkUQRTQyxxBFPAokkkUwKqaSRTgaZZJFNDrnkkU8BhRRRTAmllFFOBZVUUU0NtdRRTwONNNFMC6200U4HnXTRTQ+99NHPAIMMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8EdDin0CCCCaEUMIIJ4JIoogmhljiiCeBRJJIJoVU0kgng0yyyCaHXPLIp4BCiiimhFLKKKeCSqqopoZa6qingUaaaKaFVtpop4NOuuimh1766GeAQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4I+E/+CSSIYEIIJYxwIogkimhiiCWOeBJIJIlkUkgljXQyyCSLbHLIJY98CiikiGJKKKWMciqopIpqaqiljnoaaKSJZlpopY12Ouiki2566KWPfgYYZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+AVv8EEkQwIYQSRjgRRBJFNDHEEkc8CSSSRDIppJJGOhlkkkU2OeSSRz4FFFJEMSWUUkY5FVRSRTU11FJHPQ000kQzLbTSRjsddNJFNz300kc/AwwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyR8B/9k8gQQQTQihhhBNBJFFEE0MsccSTQCJJJJNCKmmkk0EmWWSTQy555FNAIUUUU0IpZZRTQSVVVFNDLXXU00AjTTTTQitttNNBJ11000MvffQzwCBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/BLT5J5AgggkhlDDCiSCSKKKJIZY44kkgkSSSSSGVNNLJIJMssskhlzzyKaCQIoopoZQyyqmgkiqqqaGWOuppoJEmmmmhlTba6aCTLrrpoZc++hlgkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8C/ot/AgkimBBCCSOcCCKJIpoYYokjngQSSSKZFFJJI50MMskimxxyySOfAgopopgSSimjnAoqqaKaGmqpo54GGmmimRZaaaOdDjrpopseeumjnwEGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++SOg3T+BBBFMCKGEEU4EkUQRTQyxxBFPAokkkUwKqaSRTgaZZJFNDrnkkU8BhRRRTAmllFFOBZVUUU0NtdRRTwONNNFMC6200U4HnXTRTQ+99NHPAIMMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8EfBf/RNIEMGEEEoY4UQQSRTRxBBLHPEkkEgSyaSQShrpZJBJFtnkkEse+RRQSBHFlFBKGeVUUEkV1dRQSx31NNBIE8200Eob7XTQSRfd9NBLH/0MMMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAR3+CSSIYEIIJYxwIogkimhiiCWOeBJIJIlkUkgljXQyyCSLbHLIJY98CiikiGJKKKWMciqopIpqaqiljnoaaKSJZlpopY12Ouiki2566KWPfgYYZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+A/+afQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gjo9E8gQQQTQihhhBNBJFFEE0MsccSTQCJJJJNCKmmkk0EmWWSTQy555FNAIUUUU0IpZZRTQSVVVFNDLXXU00AjTTTTQitttNNBJ11000MvffQzwCBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/BPx3/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHQJd/AgkimBBCCSOcCCKJIpoYYokjngQSSSKZFFJJI50MMskimxxyySOfAgopopgSSimjnAoqqaKaGmqpo54GGmmimRZaaaOdDjrpopseeumjnwEGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++SPgf/gnkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwK6/RNIEMGEEEoY4UQQSRTRxBBLHPEkkEgSyaSQShrpZJBJFtnkkEse+RRQSBHFlFBKGeVUUEkV1dRQSx31NNBIE8200Eob7XTQSRfd9NBLH/0MMMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAf/TP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wR0OOfQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gj4X/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Be/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHwP/2TyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38E9PknkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwL+j38CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I6DfP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wR8H/9E0gQwYQQShjhRBBJFNH8P4boaBUAAAAMbR4kSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZKZmZmZmZmZmZmZmZm5rpmZSZIkSZIkSZIkSZJk5+F8wYkhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwIG/BNIEMGEEEoY4UQQSRTRxBBLHPEkkEgSyaSQShrpZJBJFtnkkEse+RRQSBHFlFBKGeVUUEkV1dRQSx31NNBIE8200Eob7XTQSRfd9NBLH/0MMMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAf/AP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wRMOifQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gj4h/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Ah/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHwD/yTyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38EDPsnkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwL+sX8CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I2DEP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wR8E/8E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJF9300Esf/QwwyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Bo/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4B/6p9AgggmhFDCCCeCSKKIJoZY4ogngUSSSCaFVNJIJ4NMssgmh1zyyKeAQooopoRSyiingkqqqKaGWuqop4FGmmimhVbaaKeDTrropode+uhngEGGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+CBjzTyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38E/DP/BBJEMCGEEkY4EUQSRTQxxBJHPAkkkkQyKaSSRjoZZJJFNjnkkkc+BRRSRDEllFJGORVUUkU1NdRSRz0NNNJEMy200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88kfAuH8CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE045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/PDLHwGz/gkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10Msgki2xyyCWPfAoopIhiSiiljHIqqKSKamqopY56GmikiWZaaKWNdjropItueuilj34GGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgH/rn0CCCCaEUMIIJ4JIoogmhljiiCeBRJJIJoVU0kgng0yyyCaHXPLIp4BCiiimhFLKKKeCSqqopoZa6qingUaaaKaFVtpop4NOuuimh1766GeAQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4ImPNPIEEEE0IoYYQTQSRRRBNDLHHEk0AiSSSTQipppJNBJllkk0MueeRTQCFFFFNCKWWUU0ElVVRTQy111NNAI00000IrbbTTQSdddNNDL330M8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwT8O/8EEkQwIYQSRjgRRBJFNDHEEkc8CSSSRDIppJJGOhlkkkU2OeSSRz4FFFJEMSWUUkY5FVRSRTU11FJHPQ000kQzLbTSRjsddNJFNz300kc/AwwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyR8C8fwIJIpgQQgkjnAgiiSKaGGKJI54EEkkimRRSSSOdDDLJIpsccskjnwIKKaKYEkopo5wKKqmimhpqqaOeBhppopkWWmmjnQ466aKbHnrpo58BBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvkj4N/7J5AgggkhlDDCiSCSKKKJIZY44kkgkSSSSSGVNNLJIJMssskhlzzyKaCQIoopoZQyyqmgkiqqqaGWOuppoJEmmmmhlTba6aCTLrrpoZc++hlgkCGGGWGU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dthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+A/+qfQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/ghY808gQQQTQihhhBNBJFFEE0MsccSTQCJJJJNCKmmkk0EmWWSTQy555FNAIUUUU0IpZZRTQSVVVFNDLXXU00AjTTTTQitttNNBJ11000MvffQzwCBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/BPw3/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHwLp/AgkimBBCCSOcCCKJIpoYYokjngQSSSKZFFJJI50MMskimxxyySOfAgopopgSSimjnAoqqaKaGmqpo54GGmmimRZaaaOdDjrpopseeumjnwEGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++SPgv/snkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwI2/BNIEMGEEEoY4UQQSRTRxBBLHPEkkEgSyaSQShrpZJBJFtnkkEse+RRQSBHFlFBKGeVUUEkV1dRQSx31NNBIE8200Eob7XTQSRfd9NBLH/0MMMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAf/DP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wRsOmfQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gj4//wTSBDBhBBKGOFEEEkU0cQQSxzxJJBIEsmkkEoa6WSQSRbZ5JBLHvkUUEgRxZRQShnlVFBJFdXUUEsd9TTQSBPNtNBKG+100EkX3fTQSx/9DDDIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwFb/gkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10Msgki2xyyCWPfAoopIhiSiiljHIqqKSKamqopY56GmikiWZaaKWNdjropItueuilj34GGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgP/fP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wRsO2fQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gj4n/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Ad/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHwP/yTyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38E7PonkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwL+t38CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I2DPP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wR8H/8E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJF9300Esf/QwwyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8B+/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4D/659AgggmhFDCCCeCSKKI/n8M0WErAAAAGNi5ZZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkmXNmZmZm5pwzMzMzMzMzM3sf3i94xBBLHPEkkEgSyaSQShrpZJBJFtnkkEse+RRQSBHFlFBKGeVUUEkV1dRQSx31NNBIE8200Eob7XTQSRfd9NBLH/0MMMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAQf+CSSIYEIIJYxwIogkimhiiCWOeBJIJIlkUkgljXQyyCSLbHLIJY98CiikiGJKKKWMciqopIpqaqiljnoaaKSJZlpopY12Ouiki2566KWPfgYYZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Af+yfQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gg49E8gQQQTQihhhBNBJFFEE0MsccSTQCJJJJNCKmmkk0EmWWSTQy555FNAIUUUU0IpZZRTQSVVVFNDLXXU00AjTTTTQitttNNBJ11000MvffQzwCBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/BPzf/gkkiGBCCCWMcCKIJIpoYogljngSSCSJZFJIJY10Msgki2xyyCWPfAoopIhiSiiljHIqqKSKamqopY56GmikiWZaaKWNdjropItueuilj34GGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgCP/BBJEMCGEEkY4EUQSRTQxxBJHPAkkkkQyKaSSRjoZZJJFNjnkkkc+BRRSRDEllFJGORVUUkU1NdRSRz0NNNJEMy200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88kfA/+OfQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gg49k8gQQQTQihhhBNBJFFEE0MsccSTQCJJJJNCKmmkk0EmWWSTQy555FNAIUUUU0IpZZRTQSVVVFNDLXXU00AjTTTTQitttNNBJ11000MvffQzwCBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/BPwT/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHwIl/AgkimBBCCSOcCCKJIpoYYokjngQSSSKZFFJJI50MMskimxxyySOfAgopopgSSimjnAoqqaKaGmqpo54GGmmimRZaaaOdDjrpopseeumjnwEGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++SPgn/onkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwJO/RNIEMGEEEoY4UQQSRTRxBBLHPEkkEgSyaSQShrpZJBJFtnkkEse+RRQSBHFlFBKGeVUUEkV1dRQSx31NNBIE8200Eob7XTQSRfd9NBLH/0MMMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAf/MP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wRcOafQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gj45/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Bz/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHwL/wTyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38EXPgnkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwL+pX8CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I+DSP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wR8K/8E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJF9300Esf/QwwyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8BV/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4B/7Z9AgggmhFDCCCeCSKKIJoZY4ogngUSSSCaFVNJIJ4NMssgmh1zyyKeAQooopoRSyiingkqqqKaGWuqop4FGmmimhVbaaKeDTrropode+uhngEGGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+CLj2TyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38E/Bv/BBJEMCGEEkY4EUQSRTQxxBJHPAkkkkQyKaSSRjoZZJJFNjnkkkc+BRRSRDEllFJGORVUUkU1NdRSRz0NNNJEMy200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88kfAjX8CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I+D/9U8gQQQTQihhhBNBJFFEE0MsccSTQCJJJJNCKmmkk0EmWWSTQy555FNAIUUUU0IpZZRTQSVVVFNDLXXU00AjTTTTQitttNNBJ11000MvffQzwCBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/BNz6J5AgggkhlDDCiSCSKKKJIZY44kkgkSSSSSGVNNLJIJMssskhlzzyKaCQIoopoZQyyqmgkiqqqaGWOuppoJEmmmmhlTba6aCTLrrpoZc++hlgkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8C/j//BBJEMCGEEkY4EUQSRTQxxBJHPAkkkkQyKaSSRjoZZJJFNjnkkkc+BRRSRDEllFJGORVUUkU1NdRSRz0NNNJEMy200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88kfAnX8CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I+D/908gQQQTQihhhBNBJFFEE0MsccSTQCJJJJNCKmmkk0EmWWSTQy555FNAIUUUU0IpZZRTQSVVVFNDLXXU00AjTTTTQitttNNBJ11000MvffQzwCBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/BNz7J5AgggkhlDDCiSCSKKKJIZY44kkgkSSSSSGVNNLJIJMssskhlzzyKaCQIoopoZQyyqmgkiqqqaGWOuppoJEmmmmhlTba6aCTLrrpoZc++hlgkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8C/q1/AgkimBBCCSOcCCKJIpoYYokjngQSSSKZFFJJI50MMskimxxyySOfAgopopgSSimjnAoqqaKaGmqpo54GGmmimRZaaaOdDjrpopseeumjnwEGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++SPgwT+BBBFMCKGEEU4EkUQRTQyxxBFPAokkkUwKqaSRTgaZZJFNDrnkkU8BhRRRTAmllFFOBZVUUU0NtdRRTwONNNFMC6200U4HnXTRTQ+99NHPAIMMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8EfDv/BNIEMGEEEoY4UQQSRTRxBBLHPEkkEgSyaSQShrpZJBJFtnkkEse+RRQSBHFlFBKGeVUUEkV1dRQSx31NNBIE8200Eob7XTQSRfd9NBLH/0MMMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAY/+CSSIYEIIJYxwIogkimhiiCWOeBJIJIlkUkgljXQyyCSLbHLIJY98CiikiGJKKKWMciqopIpqaqiljnoaaKSJZlpopY12Ouiki2566KWPfgYYZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Af++fQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gh48k8gQQQTQihhhBNBJFFEE0MsccSTQCJJJJNCKmmkk0EmWWSTQy555FNAIUUUU0IpZZRTQSVVVFNDLXXU00AjTTTTQitttNNBJ11000MvffQzwCBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/BPwH/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHwLN/AgkimBBCCSOcCCKJIpoYYokjngQSSSKZFFJJI50MMskimxxyySOfAgopopgSSimjnAoqqaKaGmqpo54GGmmimRZaaaOdDjrpopseeumjnwEGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++SPgP/onkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwJe/BNIEMGEEEoY4UQQSRTRxBBLHPEkkEgSyaSQShrpZJBJFtnkkEse+RRQSBHFlFBKGeVUUEkV1dRQSx31NNBIE8200Eob7XTQSRfd9NBLH/0MMMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAf/JP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wR8OqfQIIIJoRQwggngkiiiCaGWOKIJ4FEkkgmhVTSSCeDTLLIJodc8singEKKKKaEUsoop4JKqqimhlrqqKeBRppopoVW2ming0666KaHXvroZ4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/gj4z/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4A3/wQSRDAhhBJGOBFEEkU0McQSRzwJJJJEMimkkkY6GWSSRTY55JJHPgUUUkQxJZRSRjkVVFJFNTXUUkc9DTTSRDMttNJGOx100kU3PfTSRz8DDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PJHwH/xTyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38EvPsnkCCCCSGUMMKJIJIoookhljjiSSCRJJJJIZU00skgkyyyySGXPPIpoJAiiimhlDLKqaCSKqqpoZY66mmgkSaaaaGVNtrpoJMuuumhlz76GWCQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwL+q38CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I+DDP4EEEUwIoYQRTgSRRBFNDLHEEU8CiSSRTAqppJFOBplkkU0OueSRTwGFFFFMCaWUUU4FlVRRTQ211FFPA4000UwLrbTRTgeddNFND7300c8AgwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wR8N/8E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJF9300Esf/QwwyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Bn/4JJIhgQggljHAiiCSKaGKIJY54EkgkiWRSSCWNdDLIJItscsglj3wKKKSIYkoopYxyKqikimpqqKWOehpopIlmWmiljXY66KSLbnropY9+BhhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4D/7p9AgggmhFDCCCeCSKKIJoZY4ogngUSSSCaFVNJIJ4NMssgmh1zyyKeAQooopoRSyiingkqqqKaGWuqop4FGmmimhVbaaKeDTrropode+uhngEGGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+CPjyTyBBBBNCKGGEE0EkUUQTQyxxxJNAIkkkk0IqaaSTQSZZZJNDLnnkU0AhRRRTQilllFNBJVVUU0MtddTTQCNNNNNCK22000EnXXTTQy999DPAIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38E/A//BBJEMCGEEkY4EUQSRTQxxBJHPAkkkkQyKaSSRjoZZJJFNjnkkkc+BRRSRDEllFJGORVUUkU1NdRSRz0NNNJEMy200kY7HXTSRTc99NJHPwMMMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88kfAt38CCSKYEEIJI5wIIokimhhiiSOeBBJJIpkUUkkjnQwyySKbHHLJI58CCimimBJKKaOcCiqpopoaaqmjngYaaaKZFlppo50OOumimx566aOfAQYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375I+B/+ieQIIIJIZQwwokgkiiiiSGWOOJJIJEkkkkhlTTSySCTLLLJIZc88imgkCKKKaGUMsqpoJIqqqmhljrqaaCRJpppoZU22umgky666aGXPvoZYJAhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/An78E0gQwYQQShjhRBBJFNHEEEsc8SSQSBLJpJBKGulkkEkW2eSQSx75FFBIEcWUUEoZ5VRQSRXV1FBLHfU00EgTzbTQShvtdNBJ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UzGrkHSpVebxW0Oq3AqJAlz9KaDKkU3x48InXmKSzqZ7sGPJyuBUBAjN1aBeNDnpWPynklOrRh7+VbNZOevt1Lpdxkfm/Vd6oFZusGjZfMAP3Bqy49bgAq1y9C4spMy4uaBQU0AW/9evZficjXWKhLZOOhg/pzoxtfDSkBKRuQCsugmwRWfWmcqqc8oZCYk/ixj1MyVUBWTkv65t3HFpwfJpIdV3DF95elzGu1qOrlNzLvtXJu7ltcTffTJ22HXrHCye+/LNadn/RO/kwv+sXAawR12rdn1y98x1bt7ZUcWy9Fs+qcEBWHNrlzogJPrJmnqTTl3vmDcy63SY+dXKqhVuVCsL6qwHWIUs8UkPK7SfUjFr1B/xqBn+pE40bNxpUxLI2a3g8pUpsXVzp3ve6yGzrULs3AHVQqL/RZP875dopuGNOxsGFgj7GNf5/qf+Kwoc2r069UmzZ+Wef0iISQX/p7W2/5uD/xmxeMMgtenr5DqZrlW8OTRLl91j/kc/i5D/68SHsVmaDc5z5XTtktrPxw3nz3r+ruHqabMHJOfkz9ap/DOlZZrLmZ93S50Xey1jyrs2c/8eub747oWaYdenvYnKfm/A8tYnq5fs0OQ/Wvv/QZ4H8v9N/0dLk3g4vMriv3uhmWeerf67KwKKxJR2NreofPF56txpwqCjc8h/I7dPxNicUc9aSo3YCFC555m2FSt1TIjdAoziB7CUtBE76dh35KkX2SdvWzXhyJIl77K2wnY/AABwTR4PTRMX9ne3M3Xfp6qtT1KlukZhH2802FL8vzUR2v2vE6EJ/t8/Ef6fvGx/r4T3NO1/FFP4f+1K/F0S0gIY9Z9cEkbyx4otD+vSZ9W1ivF9ruT9Hz3oEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEOT/BgBAgAEcEIAEFKABA1jAAR4IQAQSkP/+QgUa0IEBTGABGzjABR7wQQDSgLQgHUgPMoCMIBPIDLKArCAbyA5CQA4QCnKCXCA3yAPygnwgPygACoJCoDAoAoqCYqA4KAFKglKgNCgDyoJyIAyUBxVARVAJVAbhoAqoCqqB6qAGqAlqgQhQG9QBdUE9UB80AA1BI9AYNAFNQTPQHLQALUEr0Bq0AW1BOxAJ2oMOIAp0BJ1AZ9AFdAXdQHfQA/QEvUBv0Af0Bf1AfzAADASDwGAwBAwFw8BwEA1GgJFgFBgNYsAYMBaMA+NBLJgAJoJJIA5MBlPAVDANTAfxYAaYCWaB2SABzAFzwTwwHywAC8EisBgsAYkgCSwFy8BysAKsBKvAarAGrAXrwHqwAWwEm8BmsAVsBdvAdrAD7AS7wG6wB+wF+8B+cAAcBIfAYXAEHAXHwHFwApwEp8BpcAacBefAeXABXASXwGWQDK6Aq+AauA5ugJvgFrgN7oC74B64Dx6Ah+ARSAGPwRPwFDwDqeA5eAFeglfgNXgD3oJ34D34AD6CT+Az+AK+gm/gO/gBfoJf4Df48/f2Q4hBHBKQhBSkIQNZyEEeClCEEpShAlWoQR0a0IQWtKEDXehBHwYwDUwL08H0MAPMCDPBzDALzAqzwewwBOaAoTAnzAVzwzwwL8wH88MCsCAsBAvDIrAoLAaLwxKwJCwFS8MysCwsB8NgeVgBVoSVYGUYDqvAqrAarA5rwJqwFoyAtWEdWBfWg/VhA9gQNoKNYRPYFDaDzWEL2BK2gq1hG9gWtoORsD3sAKNgR9gJdoZdYFfYDXaHPWBP2Av2hn1gX9gP9ocD4EA4CA6GQ+BQOAwOh9FwBBwJR8HRMAaOgWPhODgexsIJcCKcBOPgZDgFToXT4HQYD2fAmXAWnA0T4Bw4F86D8+ECuBAugovhEpgIk+BSuAwuhyvgSrgKroZr4Fq4Dq6HG+BGuAluhlvgVrgNboc74E64C+6Ge+BeuA/uhwfgQXgIHoZH4FF4DB6HJ+BJeAqehmfgWXgOnocX4EV4CV6GyfAKvAqvwevwBrwJb8Hb8A68C+/B+/ABfAgfwRT4GD6BT+EzmAqfwxfwJXwFX8M38C18B9/DD/Aj/AQ/wy/wK/wGv8Mf8Cf8BX/DP38nP8QwDMcIjMQojMYYjMU4jMcETMQkTMYUTMU0TMcMzMQszMYczMU8zMcCLA2WFkuHpccyYBmxTFhmLAuWFcuGZcdCsBxYKJYTy4XlxvJgebF8WH6sAFYQK4QVxopgRbFiWHGsBFYSK4WVxspgZbFyWBhWHquAVcQqYZWxcKwKVhWrhlXHamA1sVpYBFYbq4PVxeph9bEGWEOsEdYYa4I1xZphzbEWWEusFdYaa4O1xdphkVh7rAMWhXXEOmGdsS5YV6wb1h3rgfXEemG9sT5YX6wf1h8bgA3EBmGDsSHYUGwYNhyLxkZgI7FR2GgsBhuDjcXGYeOxWGwCNhGbhMVhk7Ep2FRsGjYdi8dmYDOxWdhsLAGbg83F5mHzsQXYQmwRthhbgiViSdhSbBm2HFuBrcRWYauxNdhabB22HtuAbcQ2YZuxLdhWbBu2HduB7cR2YbuxPdhebB+2HzuAHcQOYYexI9hR7Bh2HDuBncROYaexM9hZ7Bx2HruAXcQuYZexZOwKdhW7hl3HbmA3sVvYbewOdhe7h93HHmAPsUdYCvYYe4I9xZ5hqdhz7AX2EnuFvcbeYG+xd9h77AP2EfuEfca+YF+xb9h37Af2E/uF/cb+/F36IY7hOE7gJE7hNM7gLM7hPC7gIi7hMq7gKq7hOm7gJm7hNu7gLu7hPh7gafC0eDo8PZ4Bz4hnwjPjWfCseDY8Ox6C58BD8Zx4Ljw3ngfPi+fD8+MF8IJ4IbwwXgQvihfDi+Ml8JJ4Kbw0XgYvi5fDw/DyeAW8Il4Jr4yH41Xwqng1vDpeA6+J18Ij8Np4HbwuXg+vjzfAG+KN8MZ4E7wp3gxvjrfAW+Kt8NZ4G7wt3g6PxNvjHfAovCPeCe+Md8G74t3w7ngPvCfeC++N98H74v3w/vgAfCA+CB+MD8GH4sPw4Xg0PgIfiY/CR+Mx+Bh8LD4OH4/H4hPwifgkPA6fjE/Bp+LT8Ol4PD4Dn4nPwmfjCfgcfC4+D5+PL8AX4ovwxfgSPBFPwpfiy/Dl+Ap8Jb4KX42vwdfi6/D1+AZ8I74J34xvwbfi2/Dt+A58J74L343vwffi+/D9+AH8IH4IP4wfwY/ix/Dj+An8JH4KP42fwc/i5/Dz+AX8In4Jv4wn41fwq/g1/Dp+A7+J38Jv43fwu/g9/D7+AH+IP8JT8Mf4E/wp/gxPxZ/jL/CX+Cv8Nf4Gf4u/w9/jH/CP+Cf8M/4F/4p/w7/jP/Cf+C/8N/7n74MfEhiBEwRBEhRBEwzBEhzBEwIhEhIhEwqhEhqhEwZhEhZhEw7hEh7hEwGRhkhLpCPSExmIjEQmIjORhchKZCOyEyFEDiKUyEnkInITeYi8RD4iP1GAKEgUIgoTRYiiRDGiOFGCKEmUIkoTZYiyRDkijChPVCAqEpWIykQ4UYWoSlQjqhM1iJpELSKCqE3UIeoS9Yj6RAOiIdGIaEw0IZoSzYjmRAuiJdGKaE20IdoS7YhIoj3RgYgiOhKdiM5EF6Ir0Y3oTvQgehK9iN5EH6Iv0Y/oTwwgBhKDiMHEEGIoMYwYTkQTI4iRxChiNBFDjCHGEuOI8UQsMYGYSEwi4ojJxBRiKjGNmE7EEzOImcQsYjaRQMwh5hLziPnEAmIhsYhYTCwhEokkYimxjFhOrCBWEquI1cQaYi2xjlhPbCA2EpuIzcQWYiuxjdhO7CB2EruI3cQeYi+xj9hPHCAOEoeIw8QR4ihxjDhOnCBOEqeI08QZ4ixxjjhPXCAuEpeIy0QycYW4SlwjrhM3iJvELeI2cYe4S9wj7hMPiIfEIyKFeEw8IZ4Sz4hU4jnxgnhJvCJeE2+It8Q74j3xgfhIfCI+E1+Ir8Q34jvxg/hJ/CJ+E3/+bvsgiZE4SZAkSZE0yZAsyZE8KZAiKZEyqZAqqZE6aZAmaZE26ZAu6ZE+GZBpyLRkOjI9mYHMSGYiM5NZyKxkNjI7GULmIEPJnGQuMjeZh8xL5iPzkwXIgmQhsjBZhCxKFiOLkyXIkmQpsjRZhixLliPDyPJkBbIiWYmsTIaTVciqZDWyOlmDrEnWIiPI2mQdsi5Zj6xPNiAbko3IxmQTsinZjGxOtiBbkq3I1mQbsi3Zjowk25MdyCiyI9mJ7Ex2IbuS3cjuZA+yJ9mL7E32IfuS/cj+5AByIDmIHEwOIYeSw8jhZDQ5ghxJjiJHkzHkGHIsOY4cT8aSE8iJ5CQyjpxMTiGnktPI6WQ8OYOcSc4iZ5MJ5BxyLjmPnE8uIBeSi8jF5BIykUwil5LLyOXkCnIluYpcTa4h15LryPXkBnIjuYncTG4ht5LbyO3kDnInuYvcTe4h95L7yP3kAfIgeYg8TB4hj5LHyOPkCfIkeYo8TZ4hz5LnyPPkBfIieYm8TCaTV8ir5DXyOnmDvEneIm+Td8i75D3yPvmAfEg+IlPIx+QT8in5jEwln5MvyJfkK/I1+YZ8S74j35MfyI/kJ/Iz+YX8Sn4jv5M/yJ/kL/I3+efvph9SGIVTBEVSFEVTDMVSHMVTAiVSEiVTCqVSGqVTBmVSFmVTDuVSHuVTAZWGSkulo9JTGaiMVCYqM5WFykplo7JTIVQOKpTKSeWiclN5qLxUPio/VYAqSBWiClNFqKJUMao4VYIqSZWiSlNlqLJUOSqMKk9VoCpSlajKVDhVhapKVaOqUzWomlQtKoKqTdWh6lL1qPpUA6oh1YhqTDWhmlLNqOZUC6ol1YpqTbWh2lLtqEiqPdWBiqI6Up2ozlQXqivVjepO9aB6Ur2o3lQfqi/Vj+pPDaAGUoOowdQQaig1jBpORVMjqJHUKGo0FUONocZS46jxVCw1gZpITaLiqMnUFGoqNY2aTsVTM6iZ1CxqNpVAzaHmUvOo+dQCaiG1iFpMLaESqSRqKbWMWk6toFZSq6jV1BpqLbWOWk9toDZSm6jN1BZqK7WN2k7toHZSu6jd1B5qL7WP2k8doA5Sh6jD1BHqKHWMOk6doE5Sp6jT1BnqLHWOOk9doC5Sl6jLVDJ1hbpKXaOuUzeom9Qt6jZ1h7pL3aPuUw+oh9QjKoV6TD2hnlLPqFTqOfWCekm9ol5Tb6i31DvqPfWB+kh9oj5TX6iv1DfqO/WD+kn9on5Tf/6+8kEao3GaoEmaommaoVmao3laoEVaomVaoVVao3XaoE3aom3aoV3ao306oNPQael0dHo6A52RzkRnprPQWelsdHY6hM5Bh9I56Vx0bjoPnZfOR+enC9AF6UJ0YboIXZQuRhenS9Al6VJ0aboMXZYuR4fR5ekKdEW6El2ZDqer0FXpanR1ugZdk65FR9C16Tp0XboeXZ9uQDekG9GN6SZ0U7oZ3ZxuQbekW9Gt6TZ0W7odHUm3pzvQUXRHuhPdme5Cd6W70d3pHnRPuhfdm+5D96X70f3pAfRAehA9mB5CD6WH0cPpaHoEPZIeRY+mY+gx9Fh6HD2ejqUn0BPpSXQcPZmeQk+lp9HT6Xh6Bj2TnkXPphPoOfRceh49n15AL6QX0YvpJXQinUQvpZfRy+kV9Ep6Fb2aXkOvpdfR6+kN9EZ6E72Z3kJvpbfR2+kd9E56F72b3kPvpffR++kD9EH6EH2YPkIfpY/Rx+kT9En6FH2aPkOfpc/R5+kL9EX6En2ZTqav0Ffpa/R1+gZ9k75F36bv0Hfpe/R9+gH9kH5Ep9CP6Sf0U/oZnUo/p1/QL+lX9Gv6Df2Wfke/pz/QH+lP9Gf6C/2V/kZ/p3/QP+lf9G/6z98XfshgDM4QDMlQDM0wDMtwDM8IjMhIjMwojMpojM4YjMlYjM04jMt4jM8ETBomLZOOSc9kYDIymZjMTBYmK5ONyc6EMDmYUCYnk4vJzeRh8jL5mPxMAaYgU4gpzBRhijLFmOJMCaYkU4opzZRhyjLlmDCmPFOBqchUYioz4UwVpipTjanO1GBqMrWYCKY2U4epy9Rj6jMNmIZMI6Yx04RpyjRjmjMtmJZMK6Y104Zpy7RjIpn2TAcmiunIdGI6M12Yrkw3pjvTg+nJ9GJ6M32Yvkw/pj8zgBnIDGIGM0OYocwwZjgTzYxgRjKjmNFMDDOGGcuMY8YzscwEZiIziYljJjNTmKnMNGY6E8/MYGYys5jZTAIzh5nLzGPmMwuYhcwiZjGzhElkkpilzDJmObOCWcmsYlYza5i1zDpmPbOB2chsYjYzW5itzDZmO7OD2cnsYnYze5i9zD5mP3OAOcgcYg4zR5ijzDHmOHOCOcmcYk4zZ5izzDnmPHOBuchcYi4zycwV5ipzjbnO3GBuMreY28wd5i5zj7nPPGAeMo+YFOYx84R5yjxjUpnnzAvmJfOKec28Yd4y75j3zAfmI/OJ+cx8Yb4y35jvzA/mJ/OL+c38YQALWYzFWYIlWYqlWYZlWY7lWYEVWYmVWYVVWY3VWYM1WYu1WYd1WY/12YBNw6Zl07Hp2QxsRjYTm5nNwmZls7HZ2RA2BxvK5mRzsbnZPGxeNh+bny3AFmQLsYXZImxRthhbnC3BlmRLsaXZMmxZthwbxpZnK7AV2UpsZTacrcJWZaux1dkabE22FhvB1mbrsHXZemx9tgHbkG3ENmabsE3ZZmxztgXbkm3FtmbbsG3Zdmwk257twEaxHdlObGe2C9uV7cZ2Z3uwPdlebG+2D9uX7cf2ZwewA9lB7GB2CDuUHcYOZ6PZEexIdhQ7mo1hx7Bj2XHseDaWncBOZCexcexkdgo7lZ3GTmfj2RnsTHYWO5tNYOewc9l57Hx2AbuQXcQuZpewiWwSu5Rdxi5nV7Ar2VXsanYNu5Zdx65nN7Ab2U3sZnYLu5Xdxm5nd7A72V3sbnYPu5fdx+5nD7AH2UPsYfYIe5Q9xh5nT7An2VPsafYMe5Y9x55nL7AX2UvsZTaZvcJeZa+x19kb7E32FnubvcPeZe+x99kH7EP2EZvCPmafsE/ZZ2wq+5x9wb5kX7Gv2TfsW/Yd+579wH5kP7Gf2S/sV/Yb+539wf5kf7G/2T8s4CCHcThHcCRHcTTHcCzHcTwncCIncTKncCqncTpncCZncTbncC7ncT4XcGm4tFw6Lj2XgcvIZeIyc1m4rFw2LjsXwuXgQrmcXC4uN5eHy8vl4/JzBbiCXCGuMFeEK8oV44pzJbiSXCmuNFeGK8uV48K48lwFriJXiavMhXNVuKpcNa46V4OrydXiIrjaXB2uLlePq8814BpyjbjGXBOuKdeMa8614FpyrbjWXBuuLdeOi+Tacx24KK4j14nrzHXhunLduO5cD64n14vrzfXh+nL9uP7cAG4gN4gbzA3hhnLDuOFcNDeCG8mN4kZzMdwYbiw3jhvPxXITuIncJC6Om8xN4aZy07jpXDw3g5vJzeJmcwncHG4uN4+bzy3gFnKLuMXcEi6RS+KWcsu45dwKbiW3ilvNreHWcuu49dwGbiO3idvMbeG2ctu47dwObie3i9vN7eH2cvu4/dwB7iB3iDvMHeGOcse449wJ7iR3ijvNneHOcue489wF7iJ3ibvMJXNXuKvcNe46d4O7yd3ibnN3uLvcPe4+94B7yD3iUrjH3BPuKfeMS+Wecy+4l9wr7jX3hnvLvePecx+4j9wn7jP3hfvKfeO+cz+4n9wv7jf3hwM85DEe5wme5Cme5hme5Tme5wVe5CVe5hVe5TVe5w3e5C3e5h3e5T3e5wM+DZ+WT8en5zPwGflMfGY+C5+Vz8Zn50P4HHwon5PPxefm8/B5+Xx8fr4AX5AvxBfmi/BF+WJ8cb4EX5IvxZfmy/Bl+XJ8GF+er8BX5Cvxlflwvgpfla/GV+dr8DX5WnwEX5uvw9fl6/H1+QZ8Q74R35hvwjflm/HN+RZ8S74V35pvw7fl2/GRfHu+Ax/Fd+Q78Z35LnxXvhvfne/B9+R78b35Pnxfvh/fnx/AD+QH8YP5IfxQfhg/nI/mR/Aj+VH8aD6GH8OP5cfx4/lYfgI/kZ/Ex/GT+Sn8VH4aP52P52fwM/lZ/Gw+gZ/Dz+Xn8fP5BfxCfhG/mF/CJ/JJ/FJ+Gb+cX8Gv5Ffxq/k1/Fp+Hb+e38Bv5Dfxm/kt/FZ+G7+d38Hv5Hfxu/k9/F5+H7+fP8Af5A/xh/kj/FH+GH+cP8Gf5E/xp/kz/Fn+HH+ev8Bf5C/xl/lk/gp/lb/GX+dv8Df5W/xt/g5/l7/H3+cf8A/5R3wK/5h/wj/ln/Gp/HP+Bf+Sf8W/5t/wb/l3/Hv+A/+R/8R/5r/wX/lv/Hf+B/+T/8X/5v/wQIACJuACIZACJdACI7ACJ/CCIIiCJMiCIqiCJuiCIZiCJdiCI7iCJ/hCIKQR0grphPRCBiGjkEnILGQRsgrZhOxCiJBDCBVyCrmE3EIeIa+QT8gvFBAKCoWEwkIRoahQTCgulBBKCqWE0kIZoaxQTggTygsVhIpCJaGyEC5UEaoK1YTqQg2hplBLiBBqC3WEukI9ob7QQGgoNBIaC02EpkIzobnQQmgptBJaC22EtkI7IVJoL3QQooSOQiehs9BF6Cp0E7oLPYSeQi+ht9BH6Cv0E/oLA4SBwiBhsDBEGCoME4YL0cIIYaQwShgtxAhjhLHCOGG8ECtMECYKk4Q4YbIwRZgqTBOmC/HCDGGmMEuYLSQIc4S5wjxhvrBAWCgsEhYLS4REIUlYKiwTlgsrhJXCKmG1sEZYK6wT1gsbhI3CJmGzsEXYKmwTtgs7hJ3CLmG3sEfYK+wT9gsHhIPCIeGwcEQ4KhwTjgsnhJPCKeG0cEY4K5wTzgsXhIvCJeGykCxcEa4K14Trwg3hpnBLuC3cEe4K94T7wgPhofBISBEeC0+Ep8IzIVV4LrwQXgqvhNfCG+Gt8E54L3wQPgqfhM/CF+Gr8E34LvwQfgq/hN/CHwGIUMREXCREUqREWmREVuREXhREUZREWVREVdREXTREU7REW3REV/REXwzENGJaMZ2YXswgZhQziZnFLGJWMZuYXQwRc4ihYk4xl5hbzCPmFfOJ+cUCYkGxkFhYLCIWFYuJxcUSYkmxlFhaLCOWFcuJYWJ5sYJYUawkVhbDxSpiVbGaWF2sIdYUa4kRYm2xjlhXrCfWFxuIDcVGYmOxidhUbCY2F1uILcVWYmuxjdhWbCdGiu3FDmKU2FHsJHYWu4hdxW5id7GH2FPsJfYW+4h9xX5if3GAOFAcJA4Wh4hDxWHicDFaHCGOFEeJo8UYcYw4VhwnjhdjxQniRHGSGCdOFqeIU8Vp4nQxXpwhzhRnibPFBHGOOFecJ84XF4gLxUXiYnGJmCgmiUvFZeJycYW4UlwlrhbXiGvFdeJ6cYO4Udwkbha3iFvFbeJ2cYe4U9wl7hb3iHvFfeJ+8YB4UDwkHhaPiEfFY+Jx8YR4UjwlnhbPiGfFc+J58YJ4UbwkXhaTxSviVfGaeF28Id4Ub4m3xTviXfGeeF98ID4UH4kp4mPxifhUfCamis/FF+JL8ZX4WnwjvhXfie/FD+JH8ZP4WfwifhW/id/FH+JP8Zf4W/wjAglKmIRLhERKlERLjMRKnMRLgiRKkiRLiqRKmqRLhmRKlmRLjuRKnuRLgZRGSiulk9JLGaSMUiYps5RFyiplk7JLIVIOKVTKKeWSckt5pLxSPim/VEAqKBWSCktFpKJSMam4VEIqKZWSSktlpLJSOSlMKi9VkCpKlaTKUrhURaoqVZOqSzWkmlItKUKqLdWR6kr1pPpSA6mh1EhqLDWRmkrNpOZSC6ml1EpqLbWR2krtpEipvdRBipI6Sp2kzlIXqavUTeou9ZB6Sr2k3lIfqa/UT+ovDZAGSoOkwdIQaag0TBouRUsjpJHSKGm0FCONkcZK46TxUqw0QZooTZLipMnSFGmqNE2aLsVLM6SZ0ixptpQgzZHmSvOk+dICaaG0SFosLZESpSRpqbRMWi6tkFZKq6TV0hpprbROWi9tkDZKm6TN0hZpq7RN2i7tkHZKu6Td0h5pr7RP2i8dkA5Kh6TD0hHpqHRMOi6dkE5Kp6TT0hnprHROOi9dkC5Kl6TLUrJ0RboqXZOuSzekm9It6bZ0R7or3ZPuSw+kh9IjKUV6LD2RnkrPpFTpufRCeim9kl5Lb6S30jvpvfRB+ih9kj5LX6Sv0jfpu/RD+in9kn5LfyQgQxmTcZmQSZmSaZmRWZmTeVmQRVmSZVmRVVmTddmQTdmSbdmRXdmTfTmQ08hp5XRyejmDnFHOJGeWs8hZ5WxydjlEziGHyjnlXHJuOY+cV84n55cLyAXlQnJhuYhcVC4mF5dLyCXlUnJpuYxcVi4nh8nl5QpyRbmSXFkOl6vIVeVqcnW5hlxTriVHyLXlOnJduZ5cX24gN5QbyY3lJnJTuZncXG4ht5Rbya3lNnJbuZ0cKbeXO8hRcke5k9xZ7iJ3lbvJ3eUeck+5l9xb7iP3lfvJ/eUB8kB5kDxYHiIPlYfJw+VoeYQ8Uh4lj5Zj5DHyWHmcPF6OlSfIE+VJcpw8WZ4iT5WnydPleHmGPFOeJc+WE+Q58lx5njxfXiAvlBfJi+UlcqKcJC+Vl8nL5RXySnmVvFpeI6+V18nr5Q3yRnmTvFneIm+Vt8nb5R3yTnmXvFveI++V98n75QPyQfmQfFg+Ih+Vj8nH5RPySfmUfFo+I5+Vz8nn5QvyRfmSfFlOlq/IV+Vr8nX5hnxTviXflu/Id+V78n35gfxQfiSnyI/lJ/JT+ZmcKj+XX8gv5Vfya/mN/FZ+J7+XP8gf5U/yZ/mL/FX+Jn+Xf8g/5V/yb/mPDBSoYAquEAqpUAqtMAqrcAqvCIqoSIqsKIqqaIquGIqpWIqtOIqreIqvBEoaJa2STkmvZFAyKpmUzEoWJauSTcmuhCg5lFAlp5JLya3kUfIq+ZT8SgGloFJIKawUUYoqxZTiSgmlpFJKKa2UUcoq5ZQwpbxSQamoVFIqK+FKFaWqUk2prtRQaiq1lAiltlJHqavUU+orDZSGSiOlsdJEaao0U5orLZSWSiultdJGaau0UyKV9koHJUrpqHRSOitdlK5KN6W70kPpqfRSeit9lL5KP6W/MkAZqAxSBitDlKHKMGW4Eq2MUEYqo5TRSowyRhmrjFPGK7HKBGWiMkmJUyYrU5SpyjRluhKvzFBmKrOU2UqCMkeZq8xT5isLlIXKImWxskRJVJKUpcoyZbmyQlmprFJWK2uUtco6Zb2yQdmobFI2K1uUrco2ZbuyQ9mp7FJ2K3uUvco+Zb9yQDmoHFIOK0eUo8ox5bhyQjmpnFJOK2eUs8o55bxyQbmoXFIuK8nKFeWqck25rtxQbiq3lNvKHeWuck+5rzxQHiqPlBTlsfJEeao8U1KV58oL5aXySnmtvFHeKu+U98oH5aPySfmsfFG+Kt+U78oP5afyS/mt/FGAClVMxVVCJVVKpVVGZVVO5VVBFVVJlVVFVVVN1VVDNVVLtVVHdVVP9dVATaOmVdOp6dUMakY1k5pZzaJmVbOp2dUQNYcaquZUc6m51TxqXjWfml8toBZUC6mF1SJqUbWYWlwtoZZUS6ml1TJqWbWcGqaWVyuoFdVKamU1XK2iVlWrqdXVGmpNtZYaodZW66h11XpqfbWB2lBtpDZWm6hN1WZqc7WF2lJtpbZW26ht1XZqpNpe7aBGqR3VTmpntYvaVe2mdld7qD3VXmpvtY/aV+2n9lcHqAPVQepgdYg6VB2mDlej1RHqSHWUOlqNUceoY9Vx6ng1Vp2gTlQnqXHqZHWKOlWdpk5X49UZ6kx1ljpbTVDnqHPVeep8dYG6UF2kLlaXqIlqkrpUXaYuV1eoK9VV6mp1jbpWXaeuVzeoG9VN6mZ1i7pV3aZuV3eoO9Vd6m51j7pX3afuVw+oB9VD6mH1iHpUPaYeV0+oJ9VT6mn1jHpWPaeeVy+oF9VL6mU1Wb2iXlWvqdfVG+pN9ZZ6W72j3lXvqffVB+pD9ZGaoj5Wn6hP1WdqqvpcfaG+VF+pr9U36lv1nfpe/aB+VD+pn9Uv6lf1m/pd/aH+VH+pv9U/KtCghmm4RmikRmm0xmisxmm8JmiiJmmypmiqpmm6ZmimZmm25miu5mm+FmhptLRaOi29lkHLqGXSMmtZtKxaNi27FqLl0EK1nFouLbeWR8ur5dPyawW0glohrbBWRCuqFdOKayW0kloprbRWRiurldPCtPJaBa2iVkmrrIVrVbSqWjWtulZDq6nV0iK02lodra5WT6uvNdAaao20xloTranWTGuutdBaaq201lobra3WTovU2msdtCito9ZJ66x10bpq3bTuWg+tp9ZL66310fpq/bT+2gBtoDZIG6wN0YZqw7ThWrQ2QhupjdJGazHaGG2sNk4br8VqE7SJ2iQtTpusTdGmatO06Vq8NkObqc3SZmsJ2hxtrjZPm68t0BZqi7TF2hItUUvSlmrLtOXaCm2ltkpbra3R1mrrtPXaBm2jtknbrG3RtmrbtO3aDm2ntkvbre3R9mr7tP3aAe2gdkg7rB3RjmrHtOPaCe2kdko7rZ3RzmrntPPaBe2idkm7rCVrV7Sr2jXtunZDu6nd0m5rd7S72j3tvvZAe6g90lK0x9oT7an2TEvVnmsvtJfaK+219kZ7q73T3msftI/aJ+2z9kX7qn3Tvms/tJ/aL+239kcDOtQxHdcJndQpndYZndU5ndcFXdQlXdYVXdU1XdcN3dQt3dYd3dU93dcDPY2eVk+np9cz6Bn1THpmPYueVc+mZ9dD9Bx6qJ5Tz6Xn1vPoefV8en69gF5QL6QX1ovoRfVienG9hF5SL6WX1svoZfVyepheXq+gV9Qr6ZX1cL2KXlWvplfXa+g19Vp6hF5br6PX1evp9fUGekO9kd5Yb6I31ZvpzfUWeku9ld5ab6O31dvpkXp7vYMepXfUO+md9S56V72b3l3voffUe+m99T56X72f3l8foA/UB+mD9SH6UH2YPlyP1kfoI/VR+mg9Rh+jj9XH6eP1WH2CPlGfpMfpk/Up+lR9mj5dj9dn6DP1WfpsPUGfo8/V5+nz9QX6Qn2RvlhfoifqSfpSfZm+XF+hr9RX6av1NfpafZ2+Xt+gb9Q36Zv1LfpWfZu+Xd+h79R36bv1PfpefZ++Xz+gH9QP6Yf1I/pR/Zh+XD+hn9RP6af1M/pZ/Zx+Xr+gX9Qv6Zf1ZP2KflW/pl/Xb+g39Vv6bf2Ofle/p9/XH+gP9Ud6iv5Yf6I/1Z/pqfpz/YX+Un+lv9bf6G/1d/p7/YP+Uf+kf9a/6F/1b/p3/Yf+U/+l/9b/6MCABmbgBmGQBmXQBmOwBmfwhmCIhmTIhmKohmbohmGYhmXYhmO4hmf4RmCkMdIa6Yz0RgYjo5HJyGxkMbIa2YzsRoiRwwg1chq5jNxGHiOvkc/IbxQwChqFjMJGEaOoUcwobpQwShqljNJGGaOsUc4IM8obFYyKRiWjshFuVDGqGtWM6kYNo6ZRy4gwaht1jLpGPaO+0cBoaDQyGhtNjKZGM6O50cJoabQyWhttjLZGOyPSaG90MKKMjkYno7PRxehqdDO6Gz2MnkYvo7fRx+hr9DP6GwOMgcYgY7AxxBhqDDOGG9HGCGOkMcoYbcQYY4yxxjhjvBFrTDAmGpOMOGOyMcWYakwzphvxxgxjpjHLmG0kGHOMucY8Y76xwFhoLDIWG0uMRCPJWGosM5YbK4yVxipjtbHGWGusM9YbG4yNxiZjs7HF2GpsM7YbO4ydxi5jt7HH2GvsM/YbB4yDxiHjsHHEOGocM44bJ4yTxinjtHHGOGucM84bF4yLxiXjspFsXDGuGteM68YN46Zxy7ht3DHuGveM+8YD46HxyEgxHhtPjKfGMyPVeG68MF4ar4zXxhvjrfHOeG98MD4an4zPxhfjq/HN+G78MH4av4zfxh8DmNDETNwkTNKkTNpkTNbkTN4UTNGUTNlUTNXUTN00TNO0TNt0TNf0TN8MzDRmWjOdmd7MYGY0M5mZzSxmVjObmd0MMXOYoWZOM5eZ28xj5jXzmfnNAmZBs5BZ2CxiFjWLmcXNEmZJs5RZ2ixjljXLmWFmebOCWdGsZFY2w80qZlWzmlndrGHWNGuZEWZts45Z16xn1jcbmA3NRmZjs4nZ1GxmNjdbmC3NVmZrs43Z1mxnRprtzQ5mlNnR7GR2NruYXc1uZnezh9nT7GX2NvuYfc1+Zn9zgDnQHGQONoeYQ81h5nAz2hxhjjRHmaPNGHOMOdYcZ443Y80J5kRzkhlnTjanmFPNaeZ0M96cYc40Z5mzzQRzjjnXnGfONxeYC81F5mJziZloJplLzWXmcnOFudJcZa4215hrzXXmenODudHcZG42t5hbzW3mdnOHudPcZe4295h7zX3mfvOAedA8ZB42j5hHzWPmcfOEedI8ZZ42z5hnzXPmefOCedG8ZF42k80r5lXzmnndvGHeNG+Zt8075l3znnnffGA+NB+ZKeZj84n51HxmpprPzRfmS/OV+dp8Y74135nvzQ/mR/OT+dn8Yn41v5nfzR/mT/OX+dv8YwILWpiFW4RFWpRFW4zFWpzFW4IlWpIlW4qlWpqlW4ZlWpZlW47lWp7lW4GVxkprpbPSWxmsjFYmK7OVxcpqZbOyWyFWDivUymnlsnJbeay8Vj4rv1XAKmgVsgpbRayiVjGruFXCKmmVskpbZayyVjkrzCpvVbAqWpWsyla4VcWqalWzqls1rJpWLSvCqm3Vsepa9az6VgOrodXIamw1sZpazazmVgurpdXKam21sdpa7axIq73VwYqyOlqdrM5WF6ur1c3qbvWwelq9rN5WH6uv1c/qbw2wBlqDrMHWEGuoNcwabkVbI6yR1ihrtBVjjbHGWuOs8VasNcGaaE2y4qzJ1hRrqjXNmm7FWzOsmdYsa7aVYM2x5lrzrPnWAmuhtchabC2xEq0ka6m1zFpurbBWWqus1dYaa621zlpvbbA2WpuszdYWa6u1zdpu7bB2Wrus3dYea6+1z9pvHbAOWoesw9YR66h1zDpunbBOWqes09YZ66x1zjpvXbAuWpesy1aydcW6al2zrls3rJvWLeu2dce6a92z7lsPrIfWIyvFemw9sZ5az6xU67n1wnppvbJeW2+st9Y76731wfpofbI+W1+sr9Y367v1w/pp/bJ+W38sYEMbs3GbsEmbsmmbsVmbs3lbsEVbsmVbsVVbs3XbsE3bsm3bsV3bs307sNPYae10dno7g53RzmRntrPYWe1sdnY7xM5hh9o57Vx2bjuPndfOZ+e3C9gF7UJ2YbuIXdQuZhe3S9gl7VJ2abuMXdYuZ4fZ5e0KdkW7kl3ZDrer2FXtanZ1u4Zd065lR9i17Tp2XbueXd9uYDe0G9mN7SZ2U7uZ3dxuYbe0W9mt7TZ2W7udHWm3tzvYUXZHu5Pd2e5id7W72d3tHnZPu5fd2+5j97X72f3tAfZAe5A92B5iD7WH2cPtaHuEPdIeZY+2Y+wx9lh7nD3ejrUn2BPtSXacPdmeYk+1p9nT7Xh7hj3TnmXPthPsOfZce549315gL7QX2YvtJXainWQvtZfZy+0V9kp7lb3aXmOvtdfZ6+0N9kZ7k73Z3mJvtbfZ2+0d9k57l73b3mPvtffZ++0D9kH7kH3YPmIftY/Zx+0T9kn7lH3aPmOftc/Z5+0L9kX7kn3ZTrav2Ffta/Z1+4Z9075l37bv2Hfte/Z9+4H90H5kp9iP7Sf2U/uZnWo/t1/YL+1X9mv7jf3Wfme/tz/YH+1P9mf7i/3V/mZ/t3/YP+1f9m/7jw0c6GAO7hAO6VAO7TAO63AO7wiO6EiO7CiO6miO7hiO6ViO7TiO63iO7wROGietk85J72RwMjqZnMxOFierk83J7oQ4OZxQJ6eTy8nt5HHyOvmc/E4Bp6BTyCnsFHGKOsWc4k4Jp6RTyintlHHKOuWcMKe8U8Gp6FRyKjvhThWnqlPNqe7UcGo6tZwIp7ZTx6nr1HPqOw2chk4jp7HTxGnqNHOaOy2clk4rp7XTxmnrtHMinfZOByfK6eh0cjo7XZyuTjenu9PD6en0cno7fZy+Tj+nvzPAGegMcgY7Q5yhzjBnuBPtjHBGOqOc0U6MM8YZ64xzxjuxzgRnojPJiXMmO1Ocqc40Z7oT78xwZjqznNlOgjPHmevMc+Y7C5yFziJnsbPESXSSnKXOMme5s8JZ6axyVjtrnLXOOme9s8HZ6GxyNjtbnK3ONme7s8PZ6exydjt7nL3OPme/c8A56BxyDjtHnKPOMee4c8I56ZxyTjtnnLPOOee8c8G56FxyLjvJzhXnqnPNue7ccG46t5zbzh3nrnPPue88cB46j5wU57HzxHnqPHNSnefOC+el88p57bxx3jrvnPfOB+ej88n57HxxvjrfnO/OD+en88v57fxxgAtdzMVdwiVdyqVdxmVdzuVdwRVdyZVdxVVdzdVdwzVdy7Vdx3Vdz/XdwE3jpnXTuendDG5GN5Ob2c3iZnWzudndEDeHG+rmdHO5ud08bl43n5vfLeAWdAu5hd0iblG3mFvcLeGWdEu5pd0yblm3nBvmlncruBXdSm5lN9yt4lZ1q7nV3RpuTbeWG+HWduu4dd16bn23gdvQbeQ2dpu4Td1mbnO3hdvSbeW2dtu4bd12bqTb3u3gRrkd3U5uZ7eL29Xt5nZ3e7g93V5ub7eP29ft5/Z3B7gD3UHuYHeIO9Qd5g53o90R7kh3lDvajXHHuGPdce54N9ad4E50J7lx7mR3ijvVneZOd+PdGe5Md5Y7201w57hz3XnufHeBu9Bd5C52l7iJbpK71F3mLndXuCvdVe5qd4271l3nrnc3uBvdTe5md4u71d3mbnd3uDvdXe5ud4+7193n7ncPuAfdQ+5h94h71D3mHndPuCfdU+5p94x71j3nnncvuBfdS+5lN9m94l51r7nX3RvuTfeWe9u9495177n33QfuQ/eRm+I+dp+4T91nbqr73H3hvnRfua/dN+5b95373v3gfnQ/uZ/dL+5X95v73f3h/nR/ub/dPy7woId5uEd4pEd5tMd4rMd5vCd4oid5sqd4qqd5umd4pmd5tud4rud5vhd4aby0XjovvZfBy+hl8jJ7WbysXjYvuxfi5fBCvZxeLi+3l8fL6+Xz8nsFvIJeIa+wV8Qr6hXzinslvJJeKa+0V8Yr65XzwrzyXgWvolfJq+yFe1W8ql41r7pXw6vp1fIivNpeHa+uV8+r7zXwGnqNvMZeE6+p18xr7rXwWnqtvNZeG6+t186L9Np7Hbwor6PXyevsdfG6et287l4Pr6fXy+vt9fH6ev28/t4Ab6A3yBvsDfGGesO84V60N8Ib6Y3yRnsx3hhvrDfOG+/FehO8id4kL86b7E3xpnrTvOlevDfDm+nN8mZ7Cd4cb643z5vvLfAWeou8xd4SL9FL8pZ6y7zl3gpvpbfKW+2t8dZ667z13gZvo7fJ2+xt8bZ627zt3g5vp7fL2+3t8fZ6+7z93gHvoHfIO+wd8Y56x7zj3gnvpHfKO+2d8c5657zz3gXvonfJu+wle1e8q94177p3w7vp3fJue3e8u9497773wHvoPfJSvMfeE++p98xL9Z57L7yX3ivvtffGe+u98957H7yP3ifvs/fF++p98757P7yf3i/vt/fHAz70MR/3CZ/0KZ/2GZ/1OZ/3BV/0JV/2FV/1NV/3Dd/0Ld/2Hd/1Pd/3Az+Nn9ZP56f3M/gZ/Ux+Zj+Ln9XP5mf3Q/wcfqif08/l5/bz+Hn9fH5+v4Bf0C/kF/aL+EX9Yn5xv4Rf0i/ll/bL+GX9cn6YX96v4Ff0K/mV/XC/il/Vr+ZX92v4Nf1afoRf26/j1/Xr+fX9Bn5Dv5Hf2G/iN/Wb+c39Fn5Lv5Xf2m/jt/Xb+ZF+e7+DH+V39Dv5nf0ufle/m9/d7+H39Hv5vf0+fl+/n9/fH+AP9Af5g/0h/lB/mD/cj/ZH+CP9Uf5oP8Yf44/1x/nj/Vh/gj/Rn+TH+ZP9Kf5Uf5o/3Y/3Z/gz/Vn+bD/Bn+PP9ef58/0F/kJ/kb/YX+In+kn+Un+Zv9xf4a/0V/mr/TX+Wn+dv97f4G/0N/mb/S3+Vn+bv93f4e/0d/m7/T3+Xn+fv98/4B/0D/mH/SP+Uf+Yf9w/4Z/0T/mn/TP+Wf+cf96/4F/0L/mX/WT/in/Vv+Zf92/4N/1b/m3/jn/Xv+ff9x/4D/1Hfor/2H/iP/Wf+an+c/+F/9J/5b/23/hv/Xf+e/+D/9H/5H/2v/hf/W/+d/+H/9P/5f/2//gggAEW4AERkAEV0AETsAEX8IEQiIEUyIESqIEW6IERmIEV2IETuIEX+EEQpAnSBumC9EGGIGOQKcgcZAmyBtmC7EFIkCMIDXIGuYLcQZ4gb5AvyB8UCAoGhYLCQZGgaFAsKB6UCEoGpYLSQZmgbFAuCAvKBxWCikGloHIQHlQJqgbVgupBjaBmUCuICGoHdYK6Qb2gftAgaBg0ChoHTYKmQbOgedAiaBm0CloHbYK2QbsgMmgfdAiigo5Bp6Bz0CXoGnQLugc9gp5Br6B30CfoG/QL+gcDgoHBoGBwMCQYGgwLhgfRwYhgZDAqGB3EBGOCscG4YHwQG0wIJgaTgrhgcjAlmBpMC6YH8cGMYGYwK5gdJARzgrnBvGB+sCBYGCwKFgdLgsQgKVgaLPufCIIHwLqBAACgs238XGxdLsZs27Zt27Zt20Y7r51t2+Z7sVWx1bE1sbWxdbH1sQ2xjbFNsc2xLbGtsW2x7bEdsZ2xXbHdsT2xvbF9sf2xA7GDsUOxw7EjsaOxY7HjsbhYfOxE7GTsVOx07EzsbOxc7HwsIZYYuxC7GLsUuxy7Ersauxa7HrsRuxm7FbsduxO7G7sXux97EHsYexR7HHsSexp7FnseexF7GXsVex17E3sbexd7H/sQ+xj7FPsc+xL7GvsW+x77EfsZ+xX7HfsT+xv7F0uCJcWSYcmxFFhKLBWWGkuDpcXSYemxDFhGLBOWGcuCZcWyYdmxHFhOLBeWG8uD5cXyYfmxGIZhAMMxAiMxCqMxBmMxDuMxARMxCZMxBVMxDdMxiBkYwkzMwmzMwVzMw3wswEIswgpgBbFCWGGsCFYUK4YVx0pgJbFSWGmsDFYWK4eVxypgFbFKWGWsClYVq4ZVx2pgNbFaWG2sDlYXq4fVxxpgDbFGWGOsCdYUa4Y1x1pgLbFWWGusDdYWa4e1xzpgHbFOWGesC9YV64Z1x3pgPbFeWG+sD9YX64f1xwZgA7FB2GBsCDYUG4YNx0ZgI7FR2GhsDDYWG4eNxyZgE7FJ2GRsCjYVm4ZNx2ZgM7FZ2GxsDjYXm4fNxxZgC7FF2GJsCbYUW4Ytx1ZgK7FV2GpsDbYWW4etxzZgG7FN2GZsC7YV24Ztx3ZgO7Fd2G5sD7YX24ftxw5gB7FD2GHsCHYUO4Ydx+KweOwEdhI7hZ3GzmBnsXPYeSwBS8QuYBexS9hl7Ap2FbuGXcduYDexW9ht7A52F7uH3cceYA+xR9hj7An2FHuGPcdeYC+xV9hr7A32FnuHvcc+YB+xT9hn7Av2FfuGfcd+YD+xX9hv7A/2F/uHJQFJQTKQHKQAKUEqkBqkAWlBOpAeZAAZQSaQGWQBWUE2kB3kADlBLpAb5AF5QT6QH8QABgDAAQFIQAEaMIAFHOCBAEQgARkoQAUa0AEEBkDABBawgQNc4AEfBCAEESgACoJCoDAoAoqCYqA4KAFKglKgNCgDyoJyoDyoACqCSqAyqAKqgmqgOqgBaoJaoDaoA+qCeqA+aAAagkagMWgCmoJmoDloAVqCVqA1aAPagnagPegAOoJOoDPoArqCbqA76AF6gl6gN+gD+oJ+oD8YAAaCQWAwGAKGgmFgOBgBRoJRYDQYA8aCcWA8mAAmgklgMpgCpoJpYDqYAWaCWWA2mAPmgnlgPlgAFoJFYDFYApaCZWA5WAFWglVgNVgD1oJ1YD3YADaCTWAz2AK2gm1gO9gBdoJdYDfYA/aCfWA/OAAOgkPgMDgCjoJj4DiIA/HgBDgJToHT4Aw4C86B8yABJIIL4CK4BC6DK+AquAaugxvgJrgFboM74C64B+6DB+AheAQegyfgKXgGnoMX4CV4BV6DN+AteAfegw/gI/gEPoMv4Cv4Br6DH+An+AV+gz/gL/gHkuBJ8WR4cjwFnhJPhafG0+Bp8XR4ejwDnhHPhGfGs+BZ8Wx4djwHnhPPhefG8+B58Xx4fjyGYzjAcZzASZzCaZzBWZzDeVzARVzCZVzBVVzDdRziBo5wE7dwG3dwF/dwHw/wEI/wAnhBvBBeGC+CF8WL4cXxEnhJvBReGi+Dl8XL4eXxCnhFvBJeGa+CV8Wr4dXxGnhNvBZeG6+D18Xr4fXxBnhDvBHeGG+CN8Wb4c3xFnhLvBXeGm+Dt8Xb4e3xDnhHvBPeGe+Cd8W74d3xHnhPvBfeG++D98X74f3xAfhAfBA+GB+CD8WH4cPxEfhIfBQ+Gh+Dj8XH4ePxCfhEfBI+GZ+CT8Wn4dPxGfhMfBY+G5+Dz8Xn4fPxBfhCfBG+GF+CL8WX4cvxFfhKfBW+Gl+Dr8XX4evxDfhGfBO+Gd+Cb8W34dvxHfhOfBe+G9+D78X34fvxA/hB/BB+GD+CH8WP4cfxODweP4GfxE/hp/Ez+Fn8HH4eT8AT8Qv4RfwSfhm/gl/Fr+HX8Rv4TfwWfhu/g9/F7+H38Qf4Q/wR/hh/gj/Fn+HP8Rf4S/wV/hp/g7/F3+Hv8Q/4R/wT/hn/gn/Fv+Hf8R/4T/wX/hv/g//F/+FJiKREMiI5kYJISaQiUhNpiLREOiI9kYHISGQiMhNZiKxENiI7kYPISeQichN5iLxEPiI/ESMwAhA4QRAkQRE0wRAswRE8IRAiIREyoRAqoRE6AQmDQIRJWIRNOIRLeIRPBERIREQBoiBRiChMFCGKEsWI4kQJoiRRiihNlCHKEuWI8kQFoiJRiahMVCGqEtWI6kQNoiZRi6hN1CHqEvWI+kQDoiHRiGhMNCGaEs2I5kQLoiXRimhNtCHaEu2I9kQHoiPRiehMdCG6Et2I7kQPoifRi+hN9CH6Ev2I/sQAYiAxiBhMDCGGEsOI4cQIYiQxihhNjCHGEuOI8cQEYiIxiZhMTCGmEtOI6cQMYiYxi5hNzCHmEvOI+cQCYiGxiFhMLCGWEsuI5cQKYiWxilhNrCHWEuuI9cQGYiOxidhMbCG2EtuI7cQOYiexi9hN7CH2EvuI/cQB4iBxiDhMHCGOEseI40QcEU+cIE4Sp4jTxBniLHGOOE8kEInEBeIicYm4TFwhrhLXiOvEDeImcYu4Tdwh7hL3iPvEA+Ih8Yh4TDwhnhLPiOfEC+Il8Yp4Tbwh3hLviPfEB+Ij8Yn4THwhvhLfiO/ED+In8Yv4Tfwh/hL/iCRkUjIZmZxMQaYkU5GpyTRkWjIdmZ7MQGYkM5GZySxkVjIbmZ3MQeYkc5G5yTxkXjIfmZ+MkRgJSJwkSJKkSJpkSJbkSJ4USJGUSJlUSJXUSJ2EpEEi0iQt0iYd0iU90icDMiQjsgBZkCxEFiaLkEXJYmRxsgRZkixFlibLkGXJcmR5sgJZkaxEViarkFXJamR1sgZZk6xF1ibrkHXJemR9sgHZkGxENiabkE3JZmRzsgXZkmxFtibbkG3JdmR7sgPZkexEdia7kF3JbmR3sgfZk+xF9ib7kH3JfmR/cgA5kBxEDiaHkEPJYeRwcgQ5khxFjibHkGPJceR4cgI5kZxETiankFPJaeR0cgY5k5xFzibnkHPJeeR8cgG5kFxELiaXkEvJZeRycgW5klxFribXkGvJdeR6cgO5kdxEbia3kFvJbeR2cge5k9xF7ib3kHvJfeR+8gB5kDxEHiaPkEfJY+RxMo6MJ0+QJ8lT5GnyDHmWPEeeJxPIRPICeZG8RF4mr5BXyWvkdfIGeZO8Rd4m75B3yXvkffIB+ZB8RD4mn5BPyWfkc/IF+ZJ8Rb4m35BvyXfke/ID+ZH8RH4mv5BfyW/kd/IH+ZP8Rf4m/5B/yX9kEioplYxKTqWgUlKpqNRUGiotlY5KT2WgMlKZqMxUFiorlY3KTuWgclK5qNxUHiovlY/KT8UojAIUThEUSVEUTTEUS3EUTwmUSEmUTCmUSmmUTkHKoBBlUhZlUw7lUh7lUwEVUhFVgCpIFaIKU0WoolQxqjhVgipJlaJKU2WoslQ5qjxVgapIVaIqU1WoqlQ1qjpVg6pJ1aJqU3WoulQ9qj7VgGpINaIaU02oplQzqjnVgmpJtaJaU22otlQ7qj3VgepIdaI6U12orlQ3qjvVg+pJ9aJ6U32ovlQ/qj81gBpIDaIGU0OoodQwajg1ghpJjaJGU2OosdQ4ajw1gZpITaImU1OoqdQ0ajo1g5pJzaJmU3OoudQ8aj61gFpILaIWU0uopdQyajm1glpJraJWU2uotdQ6aj21gdpIbaI2U1uordQ2aju1g9pJ7aJ2U3uovdQ+aj91gDpIHaIOU0eoo9Qx6jgVR8VTJ6iT1CnqNHWGOkudo85TCVQidYG6SF2iLlNXqKvUNeo6dYO6Sd2iblN3qLvUPeo+9YB6SD2iHlNPqKfUM+o59YJ6Sb2iXlNvqLfUO+o99YH6SH2iPlNfqK/UN+o79YP6Sf2iflN/qL/UPyoJnZRORienU9Ap6VR0ajoNnZZOR6enM9AZ6Ux0ZjoLnZXORmenc9A56Vx0bjoPnZfOR+enYzRGAxqnCZqkKZqmGZqlOZqnBVqkJVqmFVqlNVqnIW3QiDZpi7Zph3Zpj/bpgA7piC5AF6QL0YXpInRRuhhdnC5Bl6RL0aXpMnRZuhxdnq5AV6Qr0ZXpKnRVuhpdna5B16Rr0bXpOnRduh5dn25AN6Qb0Y3pJnRTuhndnG5Bt6Rb0a3pNnRbuh3dnu5Ad6Q70Z3pLnRXuhvdne5B96R70b3pPnRfuh/dnx5AD6QH0YPpIfRQehg9nB5Bj6RH0aPpMfRYehw9np5AT6Qn0ZPpKfRUeho9nZ5Bz6Rn0bPpOfRceh49n15AL6QX0YvpJfRSehm9nF5Br6RX0avpNfRaeh29nt5Ab6Q30ZvpLfRWehu9nd5B76R30bvpPfReeh+9nz5AH6QP0YfpI/RR+hh9nI6j4+kT9En6FH2aPkOfpc/R5+kEOpG+QF+kL9GX6Sv0VfoafZ2+Qd+kb9G36Tv0XfoefZ9+QD+kH9GP6Sf0U/oZ/Zx+Qb+kX9Gv6Tf0W/od/Z7+QH+kP9Gf6S/0V/ob/Z3+Qf+kf9G/6T/0X/ofnYRJyiRjkjMpmJRMKiY1k4ZJy6Rj0jMZmIxMJiYzk4XJymRjsjM5mJxMLiY3k4fJy+Rj8jMxBmMAgzMEQzIUQzMMwzIcwzMCIzISIzMKozIaozOQMRjEmIzF2IzDuIzH+EzAhEzEFGAKMoWYwkwRpihTjCnOlGBKMqWY0kwZpixTjinPVGAqMpWYykwVpipTjanO1GBqMrWY2kwdpi5Tj6nPNGAaMo2YxkwTpinTjGnOtGBaMq2Y1kwbpi3TjmnPdGA6Mp2YzkwXpivTjenO9GB6Mr2Y3kwfpi/Tj+nPDGAGMoOYwcwQZigzjBnOjGBGMqOY0cwYZiwzjhnPTGAmMpOYycwUZiozjZnOzGBmMrOY2cwcZi4zj5nPLGAWMouYxcwSZimzjFnOrGBWMquY1cwaZi2zjlnPbGA2MpuYzcwWZiuzjdnO7GB2MruY3cweZi+zj9nPHGAOMoeYw8wR5ihzjDnOxDHxzAnmJHOKOc2cYc4y55jzTAKTyFxgLjKXmMvMFeYqc425ztxgbjK3mNvMHeYuc4+5zzxgHjKPmMfME+Yp84x5zrxgXjKvmNfMG+Yt8455z3xgPjKfmM/MF+Yr8435zvxgfjK/mN/MH+Yv849JwiZlk7HJ2RRsSjYVm5pNw6Zl07Hp2QxsRjYTm5nNwmZls7HZ2RxsTjYXm5vNw+Zl87H52RiLsYDFWYIlWYqlWYZlWY7lWYEVWYmVWYVVWY3VWcgaLGJN1mJt1mFd1mN9NmBDNmILsAXZQmxhtghblC3GFmdLsCXZUmxptgxbli3HlmcrsBXZSmxltgpbla3GVmdrsDXZWmxttg5bl63H1mcbsA3ZRmxjtgnblG3GNmdbsC3ZVmxrtg3blm3Htmc7sB3ZTmxntgvble3Gdmd7sD3ZXmxvtg/bl+3H9mcHsAPZQexgdgg7lB3GDmdHsCPZUexodgw7lh3HjmcnsBPZSexkdgo7lZ3GTmdnsDPZWexsdg47l53HzmcXsAvZRexidgm7lF3GLmdXsCvZVexqdg27ll3Hrmc3sBvZTexmdgu7ld3Gbmd3sDvZXexudg+7l93H7mcPsAfZQ+xh9gh7lD3GHmfj2Hj2BHuSPcWeZs+wZ9lz7Hk2gU1kL7AX2UvsZfYKe5W9xl5nb7A32VvsbfYOe5e9x95nH7AP2UfsY/YJ+5R9xj5nX7Av2Vfsa/YN+5Z9x75nP7Af2U/sZ/YL+5X9xn5nf7A/2V/sb/YP+5f9xybhknLJuORcCi4ll4pLzaXh0nLpuPRcBi4jl4nLzGXhsnLZuOxcDi4nl4vLzeXh8nL5uPxcjMM4wOEcwZEcxdEcw7Ecx/GcwImcxMmcwqmcxukc5AwOcSZncTbncC7ncT4XcCEXcQW4glwhrjBXhCvKFeOKcyW4klwprjRXhivLlePKcxW4ilwlrjJXhavKVeOqczW4mlwtrjZXh6vL1ePqcw24hlwjrjHXhGvKNeOacy24llwrrjXXhmvLtePacx24jlwnrjPXhevKdeO6cz24nlwvrjfXh+vL9eP6cwO4gdwgbjA3hBvKDeOGcyO4kdwobjQ3hhvLjePGcxO4idwkbjI3hZvKTeOmczO4mdwsbjY3h5vLzePmcwu4hdwibjG3hFvKLeOWcyu4ldwqbjW3hlvLrePWcxu4jdwmbjO3hdvKbeO2czu4ndwubje3h9vL7eP2cwe4g9wh7jB3hDvKHeOOc3FcPHeCO8md4k5zZ7iz3DnuPJfAJXIXuIvcJe4yd4W7yl3jrnM3uJvcLe42d4e7y93j7nMPuIfcI+4x94R7yj3jnnMvuJfcK+4194Z7y73j3nMfuI/cJ+4z94X7yn3jvnM/uJ/cL+4394f7y/3jkvBJ+WR8cj4Fn5JPxafm0/Bp+XR8ej4Dn5HPxGfms/BZ+Wx8dj4Hn5PPxefm8/B5+Xx8fj7GYzzgcZ7gSZ7iaZ7hWZ7jeV7gRV7iZV7hVV7jdR7yBo94k7d4m3d4l/d4nw/4kI/4AnxBvhBfmC/CF+WL8cX5EnxJvhRfmi/Dl+XL8eX5CnxFvhJfma/CV+Wr8dX5GnxNvhZfm6/D1+Xr8fX5BnxDvhHfmG/CN+Wb8c35FnxLvhXfmm/Dt+Xb8e35DnxHvhPfme/Cd+W78d35HnxPvhffm+/D9+X78f35AfxAfhA/mB/CD+WH8cP5EfxIfhQ/mh/Dj+XH8eP5CfxEfhI/mZ/CT+Wn8dP5GfxMfhY/m5/Dz+Xn8fP5BfxCfhG/mF/CL+WX8cv5FfxKfhW/ml/Dr+XX8ev5DfxGfhO/md/Cb+W38dv5HfxOfhe/m9/D7+X38fv5A/xB/hB/mD/CH+WP8cf5OD6eP8Gf5E/xp/kz/Fn+HH+eT+AT+Qv8Rf4Sf5m/wl/lr/HX+Rv8Tf4Wf5u/w9/l7/H3+Qf8Q/4R/5h/wj/ln/HP+Rf8S/4V/5p/w7/l3/Hv+Q/8R/4T/5n/wn/lv/Hf+R/8T/4X/5v/w//l//FJhKRCMiG5kEJIKaQSUgtphLRCOiG9kEHIKGQSMgtZhKxCNiG7kEPIKeQScgt5hLxCPiG/EBMwAQi4QAikQAm0wAiswAm8IAiiIAmyoAiqoAm6AAVDQIIpWIItOIIreIIvBEIoREIBoaBQSCgsFBGKCsWE4kIJoaRQSigtlBHKCuWE8kIFoaJQSagsVBGqCtWE6kINoaZQS6gt1BHqCvWE+kIDoaHQSGgsNBGaCs2E5kILoaXQSmgttBHaCu2E9kIHoaPQSegsdBG6Ct2E7kIPoafQS+gt9BH6Cv2E/sIAYaAwSBgsDBGGCsOE4cIIYaQwShgtjBHGCuOE8cIEYaIwSZgsTBGmCtOE6cIMYaYwS5gtzBHmCvOE+cICYaGwSFgsLBGWCsuE5cIKYaWwSlgtrBHWCuuE9cIGYaOwSdgsbBG2CtuE7cIOYaewS9gt7BH2CvuE/cIB4aBwSDgsHBGOCseE40KcEC+cEE4Kp4TTwhnhrHBOOC8kCInCBeGicEm4LFwRrgrXhOvCDeGmcEu4LdwR7gr3hPvCA+Gh8Eh4LDwRngrPhOfCC+Gl8Ep4LbwR3grvhPfCB+Gj8En4LHwRvgrfhO/CD+Gn8Ev4LfwR/gr/hCRiUjGZmFxMIaYUU4mpxTRiWjGdmF7MIGYUM4mZxSxiVjGbmF3MIeYUc4m5xTxiXjGfmF+MiZgIRFwkRFKkRFpkRFbkRF4URFGURFlURFXURF2EoiEi0RQt0RYd0RU90RcDMRQjsYBYUCwkFhaLiEXFYmJxsYRYUiwllhbLiGXFcmJ5sYJYUawkVhariFXFamJ1sYZYU6wl1hbriHXFemJ9sYHYUGwkNhabiE3FZmJzsYXYUmwlthbbiG3FdmJ7sYPYUewkdha7iF3FbmJ3sYfYU+wl9hb7iH3FfmJ/cYA4UBwkDhaHiEPFYeJwcYQ4UhwljhbHiGPFceJ4cYI4UZwkThaniFPFaeJ0cYY4U5wlzhbniHPFeeJ8cYG4UFwkLhaXiEvFZeJycYW4UlwlrhbXiGvFdeJ6cYO4Udwkbha3iFvFbeJ2cYe4U9wl7hb3iHvFfeJ+8YB4UDwkHhaPiEfFY+JxMU6MF0+IJ8VT4mnxjHhWPCeeFxPERPGCeFG8JF4Wr4hXxWvidfGGeFO8Jd4W74h3xXviffGB+FB8JD4Wn4hPxWfic/GF+FJ8Jb4W34hvxXfie/GD+FH8JH4Wv4hfxW/id/GH+FP8Jf4W/4h/xX9iEimplExKLqWQUkqppNRSGimtlE5KL2WQMkqZpMxSFimrlE3KLuWQckq5pNxSHimvlE/KL8UkTAISLhESKVESLTESK3ESLwmSKEmSLCmSKmmSLkHJkJBkSpZkS47kSp7kS4EUSpFUQCooFZIKS0WkolIxqbhUQioplZJKS2WkslI5qbxUQaooVZIqS1WkqlI1qbpUQ6op1ZJqS3WkulI9qb7UQGooNZIaS02kplIzqbnUQmoptZJaS22ktlI7qb3UQeoodZI6S12krlI3qbvUQ+op9ZJ6S32kvlI/qb80QBooDZIGS0OkodIwabg0QhopjZJGS2OksdI4abw0QZooTZImS1OkqdI0abo0Q5opzZJmS3OkudI8ab60QFooLZIWS0ukpdIyabm0QloprZJWS2uktdI6ab20QdoobZI2S1ukrdI2abu0Q9op7ZJ2S3ukvdI+ab90QDooHZIOS0eko9Ix6bgUJ8VLJ6ST0inptHRGOiudk85LCVKidEG6KF2SLktXpKvSNem6dEO6Kd2Sbkt3pLvSPem+9EB6KD2SHktPpKfSM+m59EJ6Kb2SXktvpLfSO+m99EH6KH2SPktfpK/SN+m79EP6Kf2Sfkt/pL/SPymJnFROJieXU8gp5VRyajmNnFZOJ6eXM8gZ5UxyZjmLnFXOJmeXc8g55VxybjmPnFfOJ+eXYzImAxmXCZmUKZmWGZmVOZmXBVmUJVmWFVmVNVmXoWzISDZlS7ZlR3ZlT/blQA7lSC4gF5QLyYXlInJRuZhcXC4hl5RLyaXlMnJZuZxcXq4gV5QryZXlKnJVuZpcXa4h15RrybXlOnJduZ5cX24gN5QbyY3lJnJTuZncXG4ht5Rbya3lNnJbuZ3cXu4gd5Q7yZ3lLnJXuZvcXe4h95R7yb3lPnJfuZ/cXx4gD5QHyYPlIfJQeZg8XB4hj5RHyaPlMfJYeZw8Xp4gT5QnyZPlKfJUeZo8XZ4hz5RnybPlOfJceZ48X14gL5QXyYvlJfJSeZm8XF4hr5RXyavlNfJaeZ28Xt4gb5Q3yZvlLfJWeZu8Xd4h75R3ybvlPfJeeZ+8Xz4gH5QPyYflI/JR+Zh8XI6T4+UT8kn5lHxaPiOflc/J5+UEOVG+IF+UL8mX5SvyVfmafF2+Id+Ub8m35TvyXfmefF9+ID+UH8mP5SfyU/mZ/Fx+Ib+UX8mv5TfyW/md/F7+IH+UP8mf5S/yV/mb/F3+If+Uf8m/5T/yX/mfnERJqiRTkisplJRKKiW1kkZJq6RT0isZlIxKJiWzkkXJqmRTsis5lJxKLiW3kkfJq+RT8isxBVOAgiuEQiqUQiuMwiqcwiuCIiqSIiuKoiqaoitQMRSkmIql2IqjuIqn+EqghEqkFFAKKoWUwkoRpahSTCmulFBKKqWU0koZpaxSTimvVFAqKpWUykoVpapSTamu1FBqKrWU2kodpa5ST6mvNFAaKo2UxkoTpanSTGmutFBaKq2U1kobpa3STmmvdFA6Kp2UzkoXpavSTemu9FB6Kr2U3kofpa/ST+mvDFAGKoOUwcoQZagyTBmujFBGKqOU0coYZawyThmvTFAmKpOUycoUZaoyTZmuzFBmKrOU2cocZa4yT5mvLFAWKouUxcoSZamyTFmurFBWKquU1coaZa2yTlmvbFA2KpuUzcoWZauyTdmu7FB2KruU3coeZa+yT9mvHFAOKoeUw8oR5ahyTDmuxCnxygnlpHJKOa2cUc4q55TzSoKSqFxQLiqXlMvKFeWqck25rtxQbiq3lNvKHeWuck+5rzxQHiqPlMfKE+Wp8kx5rrxQXiqvlNfKG+Wt8k55r3xQPiqflM/KF+Wr8k35rvxQfiq/lN/KH+Wv8k9JoiZVk6nJ1RRqSjWVmlpNo6ZV06np1QxqRjWTmlnNomZVs6nZ1RxqTjWXmlvNo+ZV86n51ZiKqUDFVUIlVUqlVUZlVU7lVUEVVUmVVUVVVU3VVagaKlJN1VJt1VFd1VN9NVBDNVILqAXVQmphtYhaVC2mFldLqCXVUmpptYxaVi2nllcrqBXVSmpltYpaVa2mVldrqDXVWmpttY5aV62n1lcbqA3VRmpjtYnaVG2mNldbqC3VVmprtY3aVm2ntlc7qB3VTmpntYvaVe2mdld7qD3VXmpvtY/aV+2n9lcHqAPVQepgdYg6VB2mDldHqCPVUepodYw6Vh2njlcnqBPVSepkdYo6VZ2mTldnqDPVWepsdY46V52nzlcXqAvVRepidYm6VF2mLldXqCvVVepqdY26Vl2nrlc3qBvVTepmdYu6Vd2mbld3qDvVXepudY+6V92n7lcPqAfVQ+ph9Yh6VD2mHlfj1Hj1hHpSPaWeVs+oZ9Vz6nk1QU1UL6gX1UvqZfWKelW9pl5Xb6g31VvqbfWOele9p95XH6gP1UfqY/WJ+lR9pj5XX6gv1Vfqa/WN+lZ9p75XP6gf1U/qZ/WL+lX9pn5Xf6g/1V/qb/WP+lf9pybRkmrJtORaCi2llkpLraXR0mrptPRaBi2jlknLrGXRsmrZtOxaDi2nlkvLreXR8mr5tPxaTMM0oOEaoZEapdEao7Eap/GaoImapMmaoqmapuka1AwNaaZmabbmaK7mab4WaKEWaQW0glohrbBWRCuqFdOKayW0kloprbRWRiurldPKaxW0ilolrbJWRauqVdOqazW0mlotrbZWR6ur1dPqaw20hlojrbHWRGuqNdOaay20llorrbXWRmurtdPaax20jlonrbPWReuqddO6az20nlovrbfWR+ur9dP6awO0gdogbbA2RBuqDdOGayO0kdoobbQ2RhurjdPGaxO0idokbbI2RZuqTdOmazO0mdosbbY2R5urzdPmawu0hdoibbG2RFuqLdOWayu0ldoqbbW2RlurrdPWaxu0jdombbO2RduqbdO2azu0ndoubbe2R9ur7dP2awe0g9oh7bB2RDuqHdOOa3FavHZCO6md0k5rZ7Sz2jntvJagJWoXtIvaJe2ydkW7ql3Trms3tJvaLe22dke7q93T7msPtIfaI+2x9kR7qj3TnmsvtJfaK+219kZ7q73T3msftI/aJ+2z9kX7qn3Tvms/tJ/aL+239kf7q/3TkuhJ9WR6cj2FnlJPpafW0+hp9XR6ej2DnlHPpGfWs+hZ9Wx6dj2HnlPPpefW8+h59Xx6fj2mYzrQcZ3QSZ3SaZ3RWZ3TeV3QRV3SZV3RVV3TdR3qho50U7d0W3d0V/d0Xw/0UI/0AnpBvZBeWC+iF9WL6cX1EnpJvZReWi+jl9XL6eX1CnpFvZJeWa+iV9Wr6dX1GnpNvZZeW6+j19Xr6fX1BnpDvZHeWG+iN9Wb6c31FnpLvZXeWm+jt9Xb6e31DnpHvZPeWe+id9W76d31HnpPvZfeW++j99X76f31AfpAfZA+WB+iD9WH6cP1EfpIfZQ+Wh+jj9XH6eP1CfpEfZI+WZ+iT9Wn6dP1GfpMfZY+W5+jz9Xn6fP1BfpCfZG+WF+iL9WX6cv1FfpKfZW+Wl+jr9XX6ev1DfpGfZO+Wd+ib9W36dv1HfpOfZe+W9+j79X36fv1A/pB/ZB+WD+iH9WP6cf1OD1eP6Gf1E/pp/Uz+ln9nH5eT9AT9Qv6Rf2Sflm/ol/Vr+nX9Rv6Tf2Wflu/o9/V7+n39Qf6Q/2R/lh/oj/Vn+nP9Rf6S/2V/lp/o7/V3+nv9Q/6R/2T/ln/on/Vv+nf9R/6T/2X/lv/o//V/+lJYFKYDCaHKWBKmAqmhmlgWpgOpocZYEaYCWaGWWBWmA1mhzlgTpgL5oZ5YF6YD+aHMYhBAHFIQBJSkIYMZCEHeShAEUpQhgpUoQZ1CKEBETShBW3oQBd60IcBDGEEC8CCsBAsDIvAorAYLA5LwJKwFCwNy8CysBwsDyvAirASrAyrwKqwGqwOa8CasBasDevAurAerA8bwIawEWwMm8CmsBlsDlvAlrAVbA3bwLawHWwPO8COsBPsDLvArrAb7A57wJ6wF+wN+8C+sB/sDwfAgXAQHAyHwKFwGBwOR8CRcBQcDcfAsXAcHA8nwIlwEpwMp8CpcBqcDmfAmXAWnA3nwLlwHpwPF8CFcBFcDJfApXAZXA5XwJVwFVwN18C1cB1cDzfAjXAT3Ay3wK1wG9wOd8CdcBfcDffAvXAf3A8PwIPwEDwMj8Cj8Bg8DuNgPDwBT8JT8DQ8A8/Cc/A8TICJ8AK8CC/By/AKvAqvwevwBrwJb8Hb8A68C+/B+/ABfAgfwcfwCXwKn8Hn8AV8CV/B1/ANfAvfwffwA/wIP8HP8Av8Cr/B7/AH/Al/wd/wD/wL/8EkRlIjmZHcSGGkNFIZqY00RlojnZHeyGBkNDIZmY0sRlYjm5HdyGHkNHIZuY08Rl4jn5HfiBmYAQzcIAzSoAzaYAzW4AzeEAzRkAzZUAzV0AzdgIZhIMM0LMM2HMM1PMM3AiM0IqOAUdAoZBQ2ihhFjWJGcaOEUdIoZZQ2yhhljXJGeaOCUdGoZFQ2qhhVjWpGdaOGUdOoZdQ26hh1jXpGfaOB0dBoZDQ2mhhNjWZGc6OF0dJoZbQ22hhtjXZGe6OD0dHoZHQ2uhhdjW5Gd6OH0dPoZfQ2+hh9jX5Gf2OAMdAYZAw2hhhDjWHGcGOEMdIYZYw2xhhjjXHGeGOCMdGYZEw2phhTjWnGdGOGMdOYZcw25hhzjXnGfGOBsdBYZCw2lhhLjWXGcmOFsdJYZaw21hhrjXXGemODsdHYZGw2thhbjW3GdmOHsdPYZew29hh7jX3GfuOAcdA4ZBw2jhhHjWPGcSPOiDdOGCeNU8Zp44xx1jhnnDcSjETjgnHRuGRcNq4YV41rxnXjhnHTuGXcNu4Yd417xn3jgfHQeGQ8Np4YT41nxnPjhfHSeGW8Nt4Yb413xnvjg/HR+GR8Nr4YX41vxnfjh/HT+GX8Nv4Yf41/RhKUFCVDyVEKlBKlQqlRGpQWpUPpUQaUEWVCmVEWlBVlQ9lRDpQT5UK5UR6UF+VD+VEMYQggHBGIRBSiEYNYxCEeCUhEEpKRglSkIR1BZCCETGQhGznIRR7yUYBCFKECqCAqhAqjIqgoKoaKoxKoJCqFSqMyqCwqh8qjCqgiqoQqoyqoKqqGqqMaqCaqhWqjOqguqofqowaoIWqEGqMmqClqhpqjFqglaoVaozaoLWqH2qMOqCPqhDqjLqgr6oa6ox6oJ+qFeqM+qC/qh/qjAWggGoQGoyFoKBqGhqMRaCQahUajMWgsGofGowloIpqEJqMpaCqahqajGWgmmoVmozloLpqH5qMFaCFahBajJWgpWoaWoxVoJVqFVqM1aC1ah9ajDWgj2oQ2oy1oK9qGtqMdaCfahXajPWgv2of2owPoIDqEDqMj6Cg6ho6jOBSPTqCT6BQ6jc6gs+gcOo8SUCK6gC6iS+gyuoKuomvoOrqBbqJb6Da6g+6ie+g+eoAeokfoMXqCnqJn6Dl6gV6iV+g1eoPeonfoPfqAPqJP6DP6gr6ib+g7+oF+ol/oN/qD/qJ/KImZ1ExmJjdTmCnNVGZqM42Z1kxnpjczmBnNTGZmM4uZ1cxmZjdzmDnNXGZuM4+Z18xn5jdjJmYCEzcJkzQpkzYZkzU5kzcFUzQlUzYVUzU1UzehaZjINE3LtE3HdE3P9M3ADM3ILGAWNAuZhc0iZlGzmFncLGGWNEuZpc0yZlmznFnerGBWNCuZlc0qZlWzmlndrGHWNGuZtc06Zl2znlnfbGA2NBuZjc0mZlOzmdncbGG2NFuZrc02Zluzndne7GB2NDuZnc0uZlezm9nd7GH2NHuZvc0+Zl+zn9nfHGAONAeZg80h5lBzmDncHGGONEeZo80x5lhznDnenGBONCeZk80p5lRzmjndnGHONGeZs8055lxznjnfXGAuNBeZi80l5lJzmbncXGGuNFeZq8015lpznbne3GBuNDeZm80t5lZzm7nd3GHuNHeZu8095l5zn7nfPGAeNA+Zh80j5lHzmHncjDPjzRPmSfOUedo8Y541z5nnzQQz0bxgXjQvmZfNK+ZV85p53bxh3jRvmbfNO+Zd855533xgPjQfmY/NJ+ZT85n53HxhvjRfma/NN+Zb85353vxgfjQ/mZ/NL+ZX85v53fxh/jR/mb/NP+Zf85+ZxEpqJbOSWymslFYqK7WVxkprpbPSWxmsjFYmK7OVxcpqZbOyWzmsnFYuK7eVx8pr5bPyWzELs4CFW4RFWpRFW4zFWpzFW4IlWpIlW4qlWpqlW9AyLGSZlmXZlmO5lmf5VmCFVmQVsApahazCVhGrqFXMKm6VsEpapazSVhmrrFXOKm9VsCpalazKVhWrqlXNqm7VsGpatazaVh2rrlXPqm81sBpajazGVhOrqdXMam61sFparazWVhurrdXOam91sDpanazOVherq9XN6m71sHpavazeVh+rr9XP6m8NsAZag6zB1hBrqDXMGm6NsEZao6zR1hhrrDXOGm9NsCZak6zJ1hRrqjXNmm7NsGZas6zZ1hxrrjXPmm8tsBZai6zF1hJrqbXMWm6tsFZaq6zV1hprrbXOWm9tsDZam6zN1hZrq7XN2m7tsHZau6zd1h5rr7XP2m8dsA5ah6zD1hHrqHXMOm7FWfHWCeukdco6bZ2xzlrnrPNWgpVoXbAuWpesy9YV66p1zbpu3bBuWres29Yd6651z7pvPbAeWo+sx9YT66n1zHpuvbBeWq+s19Yb6631znpvfbA+Wp+sz9YX66v1zfpu/bB+Wr+s39Yf66/1z0piJ7WT2cntFHZKO5Wd2k5jp7XT2entDHZGO5Od2c5iZ7Wz2dntHHZOO5ed285j57Xz2fntmI3ZwMZtwiZtyqZtxmZtzuZtwRZtyZZtxVZtzdZtaBs2sk3bsm3bsV3bs307sEM7sgvYBe1CdmG7iF3ULmYXt0vYJe1Sdmm7jF3WLmeXtyvYFe1KdmW7il3VrmZXt2vYNe1adm27jl3XrmfXtxvYDe1GdmO7id3UbmY3t1vYLe1Wdmu7jd3Wbme3tzvYHe1Odme7i93V7mZ3t3vYPe1edm+7j93X7mf3twfYA+1B9mB7iD3UHmYPt0fYI+1R9mh7jD3WHmePtyfYE+1J9mR7ij3VnmZPt2fYM+1Z9mx7jj3XnmfPtxfYC+1F9mJ7ib3UXmYvt1fYK+1V9mp7jb3WXmevtzfYG+1N9mZ7i73V3mZvt3fYO+1d9m57j73X3mfvtw/YB+1D9mH7iH3UPmYft+PsePuEfdI+ZZ+2z9hn7XP2eTvBTrQv2BftS/Zl+4p91b5mX7dv2DftW/Zt+459175n37cf2A/tR/Zj+4n91H5mP7df2C/tV/Zr+4391n5nv7c/2B/tT/Zn+4v91f5mf7d/2D/tX/Zv+4/91/5nJ3GSOsmc5E4KJ6WTykntpHHSOumc9E4GJ6OTycnsZHGyOtmc7E4OJ6eTy8nt5HHyOvmc/E7MwRzg4A7hkA7l0A7jsA7n8I7giI7kyI7iqI7m6A50DAc5pmM5tuM4ruM5vhM4oRM5BZyCTiGnsFPEKeoUc4o7JZySTimntFPGKeuUc8o7FZyKTiWnslPFqepUc6o7NZyaTi2ntlPHqevUc+o7DZyGTiOnsdPEaeo0c5o7LZyWTiuntdPGaeu0c9o7HZyOTiens9PF6ep0c7o7PZyeTi+nt9PH6ev0c/o7A5yBziBnsDPEGeoMc4Y7I5yRzihntDPGGeuMc8Y7E5yJziRnsjPFmepMc6Y7M5yZzixntjPHmevMc+Y7C5yFziJnsbPEWeosc5Y7K5yVzipntbPGWeusc9Y7G5yNziZns7PF2epsc7Y7O5ydzi5nt7PH2evsc/Y7B5yDziHnsHPEOeocc447cU68c8I56ZxyTjtnnLPOOee8k+AkOheci84l57JzxbnqXHOuOzecm84t57Zzx7nr3HPuOw+ch84j57HzxHnqPHOeOy+cl84r57XzxnnrvHPeOx+cj84n57PzxfnqfHO+Oz+cn84v57fzx/nr/HOSuEndZG5yN4Wb0k3lpnbTuGnddG56N4Ob0c3kZnazuFndbG52N4eb083l5nbzuHndfG5+N+ZiLnBxl3BJl3Jpl3FZl3N5V3BFV3JlV3FVV3N1F7qGi1zTtVzbdVzX9VzfDdzQjdwCbkG3kFvYLeIWdYu5xd0Sbkm3lFvaLeOWdcu55d0KbkW3klvZreJWdau51d0abk23llvbrePWdeu59d0GbkO3kdvYbeI2dZu5zd0Wbku3ldvabeO2ddu57d0Obke3k9vZ7eJ2dbu53d0ebk+3l9vb7eP2dfu5/d0B7kB3kDvYHeIOdYe5w90R7kh3lDvaHeOOdce5490J7kR3kjvZneJOdae5090Z7kx3ljvbnePOdee5890F7kJ3kbvYXeIudZe5y90V7kp3lbvaXeOudde5690N7kZ3k7vZ3eJudbe5290d7k53l7vb3ePudfe5+90D7kH3kHvYPeIedY+5x904N9494Z50T7mn3TPuWfece95NcBPdC+5F95J72b3iXnWvudfdG+5N95Z7273j3nXvuffdB+5D95H72H3iPnWfuc/dF+5L95X72n3jvnXfue/dD+5H95P72f3ifnW/ud/dH+5P95f72/3j/nX/uUm8pF4yL7mXwkvppfJSe2m8tF46L72XwcvoZfIye1m8rF42L7uXw8vp5fJye3m8vF4+L78X8zAPeLhHeKRHebTHeKzHebwneKInebKneKqneboHPcNDnulZnu05nut5nu8FXuhFXgGvoFfIK+wV8Yp6xbziXgmvpFfKK+2V8cp65bzyXgWvolfJq+xV8ap61bzqXg2vplfLq+3V8ep69bz6XgOvodfIa+w18Zp6zbzmXguvpdfKa+218dp67bz2Xgevo9fJ6+x18bp63bzuXg+vp9fL6+318fp6/bz+3gBvoDfIG+wN8YZ6w7zh3ghvpDfKG+2N8cZ647zx3gRvojfJm+xN8aZ607zp3gxvpjfLm+3N8eZ687z53gJvobfIW+wt8ZZ6y7zl3gpvpbfKW+2t8dZ667z13gZvo7fJ2+xt8bZ627zt3g5vp7fL2+3t8fZ6+7z93gHvoHfIO+wd8Y56x7zjXpwX753wTnqnvNPeGe+sd8477yV4id4F76J3ybvsXfGuete8694N76Z3y7vt3fHueve8+94D76H3yHvsPfGees+8594L76X3ynvtvfHeeu+8994H76P3yfvsffG+et+8794P76f3y/vt/fH+ev+8JH5SP5mf3E/hp/RT+an9NH5aP52f3s/gZ/Qz+Zn9LH5WP5uf3c/h5/Rz+bn9PH5eP5+f34/5mA983Cd80qd82md81ud83hd80Zd82Vd81dd83Ye+4SPf9C3f9h3f9T3f9wM/9CO/gF/QL+QX9ov4Rf1ifnG/hF/SL+WX9sv4Zf1yfnm/gl/Rr+RX9qv4Vf1qfnW/hl/Tr+XX9uv4df16fn2/gd/Qb+Q39pv4Tf1mfnO/hd/Sb+W39tv4bf12fnu/g9/R7+R39rv4Xf1ufne/h9/T7+X39vv4ff1+fn9/gD/QH+QP9of4Q/1h/nB/hD/SH+WP9sf4Y/1x/nh/gj/Rn+RP9qf4U/1p/nR/hj/Tn+XP9uf4c/15/nx/gb/QX+Qv9pf4S/1l/nJ/hb/SX+Wv9tf4a/11/np/g7/R3+Rv9rf4W/1t/nZ/h7/T3+Xv9vf4e/19/n7/gH/QP+Qf9o/4R/1j/nE/zo/3T/gn/VP+af+Mf9Y/55/3E/xE/4J/0b/kX/av+Ff9a/51/4Z/07/l3/bv+Hf9e/59/4H/0H/kP/af+E/9Z/5z/4X/0n/lv/bf+G/9d/57/4P/0f/kf/a/+F/9b/53/4f/0//l//b/+H/9f36SIGmQLEgepAhSBqmC1EGaIG2QLkgfZAgyBpmCzEGWIGuQLcge5AhyBrmC3EGeIG+QL8gfxAIsAAEeEAEZUAEdMAEbcAEfCIEYSIEcKIEaaIEewMAIUGAGVmAHTuAGXuAHQRAGUVAgKBgUCgoHRYKiQbGgeFAiKBmUCkoHZYKyQbmgfFAhqBhUCioHVYKqQbWgelAjqBnUCmoHdYK6Qb2gftAgaBg0ChoHTYKmQbOgedAiaBm0CloHbYK2QbugfdAh6Bh0CjoHXYKuQbege9Aj6Bn0CnoHfYK+Qb+gfzAgGBgMCgYHQ4KhwbBgeDAiGBmMCkYHY4KxwbhgfDAhmBhMCiYHU4KpwbRgejAjmBnMCmYHc4K5wbxgfrAgWBgsChYHS4KlwbJgebAiWBmsClYHa4K1wbpgfbAh2BhsCjYHW4KtwbZge7Aj2BnsCnYHe4K9wb5gf3AgOBgcCg4HR4KjwbHgeBAXxAcngpPBqeB0cCY4G5wLzgcJQWJwIbgYXAouB1eCq8G14HpwI7gZ3ApuB3eCu8G94H7wIHgYPAoeB0+Cp8Gz4HnwIngZvApeB2+Ct8G74H3wIfgYfAo+B1+Cr8G34HvwI/gZ/Ap+B3+Cv8G/IEmYNEwWJg9ThCnDVGHqME2YNkwXpg8zhBnDTGHmMEuYNcwWZg9zhDnDXGHuME+YN8wX5g9jIRaCEA+JkAypkA6ZkA25kA+FUAylUA6VUA21UA9haIQoNEMrtEMndEMv9MMgDMMoLBAWDAuFhcMiYdGwWFg8LBGWDEuFpcMyYdmwXFg+rBBWDCuFlcMqYdWwWlg9rBHWDGuFtcM6Yd2wXlg/bBA2DBuFjcMmYdOwWdg8bBG2DFuFrcM2YduwXdg+7BB2DDuFncMuYdewW9g97BH2DHuFvcM+Yd+wX9g/HBAODAeFg8Mh4dBwWDg8HBGODEeFo8Mx4dhwXDg+nBBODCeFk8Mp4dRwWjg9nBHODGeFs8M54dxwXjg/XBAuDBeFi8Ml4dJwWbg8XBGuDFeFq8M14dpwXbg+3BBuDDeFm8Mt4dZwW7g93BHuDHeFu8M94d5wX7g/PBAeDA+Fh8Mj4dHwWHg8jAvjwxPhyfBUeDo8E54Nz4Xnw4QwMbwQXgwvhZfDK+HV8Fp4PbwR3gxvhbfDO+Hd8F54P3wQPgwfhY/DJ+HT8Fn4PHwRvgxfha/DN+Hb8F34PvwQfgw/hZ/DL+HX8Fv4PfwR/gx/hb/DP+Hf8F+YJEoaJYuSRymilFGqKHWUJkobpYvSRxmijFGmKHOUJcoaZYuyRzminFGuKHeUJ8ob5YvyR7EIi0CER0RERlRER0zERlzER0IkRlIkR0qkRlqkRzAyIhSZkRXZkRO5kRf5URCFURQViApGhaLCUZGoaFQsKh6ViEpGpaLSUZmobFQuKh9ViCpGlaLKUZWoalQtqh7ViGpGtaLaUZ2oblQvqh81iBpGjaLGUZOoadQsah61iFpGraLWUZuobdQuah91iDpGnaLOUZeoa9Qt6h71iHpGvaLeUZ+ob9Qv6h8NiAZGg6LB0ZBoaDQsGh6NiEZGo6LR0ZhobDQuGh9NiCZGk6LJ0ZRoajQtmh7NiGZGs6LZ0ZxobjQvmh8tiBZGi6LF0ZJoabQsWh6tiP4TBA+AdQMBAEBn20Zn2z/JxbnYusy2bbvtbNu2bdu2bby3NLYstjy2IrYytiq2OrYmtja2LrY+tiG2MbYptjm2JbY1ti22PbYjtjO2K7Y7tie2N7Yvtj92IHYwdih2OHYkdjR2LHY8diJ2MnYqdjp2JnY2di52PnYhdjF2KXY5diV2NXYtdj12I3Yzdit2O3Yndjd2L3Y/9iD2MPYo9jj2JPY09iz2PPYi9jL2KvY69ib2NvYu9j72IfYx9in2OfYl9jX2LfY99iP2M/Yr9jv2J/Y39i+WBEuKJcOSYymwlFgqLDWWBkuLpcPSYxmwjFgmLDOWBcuKZcOyYzmwnFguLDeWB8uL5cPyYwWwglghrDBWBCuKxWHFsOJYCawkVgorjZXBymLlsPJYBawiVgmrjFXBqmLVsOpYDawmVgurjdXB6mL1sBiGYThGYAAjMQqjMQZjMQ7jMQGDmIhJmIwpmIppmI4ZmIlZmI05mIt5mI8FWIghLMLqYw2whlgjrDHWBGuKNcOaYy2wllgrrDXWBmuLtcPaYx2wjlgnrDPWBeuKdcO6Yz2wnlgvrDfWB+uL9cP6YwOwgdggbDA2BBuKDcOGYyOwkdgobDQ2BhuLjcPGY/FYApaITcAmYpOwydgUbCo2DZuOzcBmYrOw2dgcbC42D5uPLcAWYouwxdgSbCm2DFuOrcBWYquw1dgabC22DluPbcA2YpuwzdgWbCu2DduO7cB2Yruw3dgebC+2D9uPHcAOYoeww9gR7Ch2DDuOncBOYqew09gZ7Cx2DjuPXcAuYpewy9gV7Cp2DbuO3cBuYrew29gd7C52D7uPPcAeYo+wx9gT7Cn2DHuOvcBeYq+w19gb7C32DnuPfcA+Yp+wz9gX7Cv2DfuO/cB+Yr+w39gf7C/2D0uCJ8WT4cnxFHhKPBWeGk+Dp8XT4enxDHhGPBOeGc+CZ8Wz4dnxHHhOPBeeG8+D58Xz4fnxAnhBvBBeGC+CF8Xj8GJ4cbwEXhIvhZfGy+Bl8XJ4ebwCXhGvhFfGq+BV8Wp4dbwGXhOvhdfG6+B18Xp4DMdwHCdwgJM4hdM4g7M4h/O4gENcxCVcxhVcxTVcxw3cxC3cxh3cxT3cxwM8xBEe4fXxBnhDvBHeGG+CN8Wb4c3xFnhLvBXeGm+Dt8Xb4e3xDnhHvBPeGe+Cd8W74d3xHnhPvBfeG++D98X74f3xAfhAfBA+GB+CD8WH4cPxEfhIfBQ+Gh+Dj8XH4ePxeDwBT8Qn4BPxSfhkfAo+FZ+GT8dn4DPxWfhsfA4+F5+Hz8cX4AvxRfhifAm+FF+GL8dX4CvxVfhqfA2+Fl+Hr8c34BvxTfhmfAu+Fd+Gb8d34DvxXfhufA++F9+H78cP4AfxQ/hh/Ah+FD+GH8dP4CfxU/hp/Ax+Fj+Hn8cv4BfxS/hl/Ap+Fb+GX8dv4DfxW/ht/A5+F7+H38cf4A/xR/hj/An+FH+GP8df4C/xV/hr/A3+Fn+Hv8c/4B/xT/hn/Av+Ff+Gf8d/4D/xX/hv/A/+F/+HJyGSEsmI5EQKIiWRikhNpCHSEumI9EQGIiORichMZCGyEtmI7EQOIieRi8hN5CHyEvmI/EQBoiBRiChMFCGKEnFEMaI4UYIoSZQiShNliLJEOaI8UYGoSFQiKhNViKpENaI6UYOoSdQiahN1iLpEPSJGYAROEAQgSIIiaIIhWIIjeEIgICESEiETCqESGqETBmESFmETDuESHuETARESiIiI+kQDoiHRiGhMNCGaEs2I5kQLoiXRimhNtCHaEu2I9kQHoiPRiehMdCG6Et2I7kQPoifRi+hN9CH6Ev2I/sQAYiAxiBhMDCGGEsOI4cQIYiQxihhNjCHGEuOI8UQ8kUAkEhOIicQkYjIxhZhKTCOmEzOImcQsYjYxh5hLzCPmEwuIhcQiYjGxhFhKLCOWEyuIlcQqYjWxhlhLrCPWExuIjcQmYjOxhdhKbCO2EzuIncQuYjexh9hL7CP2EweIg8Qh4jBxhDhKHCOOEyeIk8Qp4jRxhjhLnCPOExeIi8Ql4jJxhbhKXCOuEzeIm8Qt4jZxh7hL3CPuEw+Ih8Qj4jHxhHhKPCOeEy+Il8Qr4jXxhnhLvCPeEx+Ij8Qn4jPxhfhKfCO+Ez+In8Qv4jfxh/hL/COSgKQgGUgOUoCUIBVIDdKAtCAdSA8ygIwgE8gMsoCsIBvIDnKAnCAXyA3ygLwgH8gPCoCCoBAoDIqAoiAOFAPFQQlQEpQCpUEZUBaUA+VBBVARVAKVQRVQFVQD1UENUBPUArVBHVAX1AMxgAEcEAAAElCABgxgAQd4IAAIRCABGShABRrQgQFMYAEbOMAFHvBBAEKAQATqgwagIWgEGoMmoCloBpqDFqAlaAVagzagLWgH2oMOoCPoBDqDLqAr6Aa6gx6gJ+gFeoM+oC/oB/qDAWAgGAQGgyFgKBgGhoMRYCQYBUaDMWAsGAfGg3iQABLBBDARTAKTwRQwFUwD08EMMBPMArPBHDAXzAPzwQKwECwCi8ESsBQsA8vBCrASrAKrwRqwFqwD68EGsBFsApvBFrAVbAPbwQ6wE+wCu8EesBfsA/vBAXAQHAKHwRFwFBwDx8EJcBKcAqfBGXAWnAPnwQVwEVwCl8EVcBVcA9fBDXAT3AK3wR1wF9wD98ED8BA8Ao/BE/AUPAPPwQvwErwCr8Eb8Ba8A+/BB/ARfAKfwRfwFXwD38EP8BP8Ar/BH/AX/ANJyKRkMjI5mYJMSaYiU5NpyLRkOjI9mYHMSGYiM5NZyKxkNjI7mYPMSeYic5N5yLxkPjI/WYAsSBYiC5NFyKJkHFmMLE6WIEuSpcjSZBmyLFmOLE9WICuSlcjKZBWyKlmNrE7WIGuStcjaZB2yLlmPjJEYiZMECUiSpEiaZEiW5EieFEhIiqREyqRCqqRG6qRBmqRF2qRDuqRH+mRAhiQiI7I+2YBsSDYiG5NNyKZkM7I52YJsSbYiW5NtyLZkO7I92YHsSHYiO5NdyK5kN7I72YPsSfYie5N9yL5kP7I/OYAcSA4iB5NDyKHkMHI4OYIcSY4iR5NjyLHkOHI8GU8mkInkBHIiOYmcTE4hp5LTyOnkDHImOYucTc4h55LzyPnkAnIhuYhcTC4hl5LLyOXkCnIluYpcTa4h15LryPXkBnIjuYncTG4ht5LbyO3kDnInuYvcTe4h95L7yP3kAfIgeYg8TB4hj5LHyOPkCfIkeYo8TZ4hz5LnyPPkBfIieYm8TF4hr5LXyOvkDfImeYu8Td4h75L3yPvkA/Ih+Yh8TD4hn5LPyOfkC/Il+Yp8Tb4h35LvyPfkB/Ij+Yn8TH4hv5LfyO/kD/In+Yv8Tf4h/5L/yCRUUioZlZxKQaWkUlGpqTRUWiodlZ7KQGWkMlGZqSxUVioblZ3KQeWkclG5qTxUXioflZ8qQBWkClGFqSJUUSqOKkYVp0pQJalSVGmqDFWWKkeVpypQFalKVGWqClWVqkZVp2pQNalaVG2qDlWXqkfFKIzCKYICFElRFE0xFEtxFE8JFKRESqJkSqFUSqN0yqBMyqJsyqFcyqN8KqBCClERVZ9qQDWkGlGNqSZUU6oZ1ZxqQbWkWlGtqTZUW6od1Z7qQHWkOlGdqS5UV6ob1Z3qQfWkelG9qT5UX6of1Z8aQA2kBlGDqSHUUGoYNZwaQY2kRlGjqTHUWGocNZ6KpxKoRGoCNZGaRE2mplBTqWnUdGoGNZOaRc2m5lBzqXnUfGoBtZBaRC2mllBLqWXUcmoFtZJaRa2m1lBrqXXUemoDtZHaRG2mtlBbqW3UdmoHtZPaRe2m9lB7qX3UfuoAdZA6RB2mjlBHqWPUceoEdZI6RZ2mzlBnqXPUeeoCdZG6RF2mrlBXqWvUdeoGdZO6Rd2m7lB3qXvUfeoB9ZB6RD2mnlBPqWfUc+oF9ZJ6Rb2m3lBvqXfUe+oD9ZH6RH2mvlBfqW/Ud+oH9ZP6Rf2m/lB/qX9UEjopnYxOTqegU9Kp6NR0GjotnY5OT2egM9KZ6Mx0FjornY3OTuegc9K56Nx0HjovnY/OTxegC9KF6MJ0EbooHUcXo4vTJeiSdCm6NF2GLkuXo8vTFeiKdCW6Ml2FrkpXo6vTNeiadC26Nl2HrkvXo2M0RuM0QQOapCmaphmapTmapwUa0iIt0TKt0Cqt0Tpt0CZt0Tbt0C7t0T4d0CGN6IiuTzegG9KN6MZ0E7op3YxuTregW9Kt6NZ0G7ot3Y5uT3egO9Kd6M50F7or3Y3uTvege9K96N50H7ov3Y/uTw+gB9KD6MH0EHooPYweTo+gR9Kj6NH0GHosPY4eT8fTCXQiPYGeSE+iJ9NT6Kn0NHo6PYOeSc+iZ9Nz6Ln0PHo+vYBeSC+iF9NL6KX0Mno5vYJeSa+iV9Nr6LX0Ono9vYHeSG+iN9Nb6K30Nno7vYPeSe+id9N76L30Pno/fYA+SB+iD9NH6KP0Mfo4fYI+SZ+iT9Nn6LP0Ofo8fYG+SF+iL9NX6Kv0Nfo6fYO+Sd+ib9N36Lv0Pfo+/YB+SD+iH9NP6Kf0M/o5/YJ+Sb+iX9Nv6Lf0O/o9/YH+SH+iP9Nf6K/0N/o7/YP+Sf+if9N/6L/0PzoJk5RJxiRnUjApmVRMaiYNk5ZJx6RnMjAZmUxMZiYLk5XJxmRncjA5mVxMbiYPk5fJx+RnCjAFmUJMYaYIU5SJY4oxxZkSTEmmFFOaKcOUZcox5ZkKTEWmElOZqcJUZaox1ZkaTE2mFlObqcPUZeoxMQZjcIZgAEMyFEMzDMMyHMMzAgMZkZEYmVEYldEYnTEYk7EYm3EYl/EYnwmYkEFMxNRnGjANmUZMY6YJ05RpxjRnWjAtmVZMa6YN05Zpx7RnOjAdmU5MZ6YL05XpxnRnejA9mV5Mb6YP05fpx/RnBjADmUHMYGYIM5QZxgxnRjAjmVHMaGYMM5YZx4xn4pkEJpGZwExkJjGTmSnMVGYaM52ZwcxkZjGzmTnMXGYeM59ZwCxkFjGLmSXMUmYZs5xZwaxkVjGrmTXMWmYds57ZwGxkNjGbmS3MVmYbs53ZwexkdjG7mT3MXmYfs585wBxkDjGHmSPMUeYYc5w5wZxkTjGnmTPMWeYcc565wFxkLjGXmSvMVeYac525wdxkbjG3mTvMXeYec595wDxkHjGPmSfMU+YZ85x5wbxkXjGvmTfMW+Yd8575wHxkPjGfmS/MV+Yb8535wfxkfjG/mT/MX+Yfk4RNyiZjk7Mp2JRsKjY1m4ZNy6Zj07MZ2IxsJjYzm4XNymZjs7M52JxsLjY3m4fNy+Zj87MF2IJsIbYwW4QtysaxxdjibAm2JFuKLc2WYcuy5djybAW2IluJrcxWYauy1djqbA22JluLrc3WYeuy9dgYi7E4S7CAJVmKpVmGZVmO5VmBhazISqzMKqzKaqzOGqzJWqzNOqzLeqzPBmzIIjZi67MN2IZsI7Yx24RtyjZjm7Mt2JZsK7Y124Zty7Zj27Md2I5sJ7Yz24XtynZju7M92J5sL7Y324fty/Zj+7MD2IHsIHYwO4Qdyg5jh7Mj2JHsKHY0O4Ydy45jx7PxbAKbyE5gJ7KT2MnsFHYqO42dzs5gZ7Kz2NnsHHYuO4+dzy5gF7KL2MXsEnYpu4xdzq5gV7Kr2NXsGnYtu45dz25gN7Kb2M3sFnYru43dzu5gd7K72N3sHnYvu4/dzx5gD7KH2MPsEfYoe4w9zp5gT7Kn2NPsGfYse449z15gL7KX2MvsFfYqe429zt5gb7K32NvsHfYue4+9zz5gH7KP2MfsE/Yp+4x9zr5gX7Kv2NfsG/Yt+459z35gP7Kf2M/sF/Yr+439zv5gf7K/2N/sH/Yv+49NwiXlknHJuRRcSi4Vl5pLw6Xl0nHpuQxcRi4Tl5nLwmXlsnHZuRxcTi4Xl5vLw+Xl8nH5uQJcQa4QV5grwhXl4rhiXHGuBFeSK8WV5spwZblyXHmuAleRq8RV5qpwVblqXHWuBleTq8XV5upwdbl6XIzDOJwjOMCRHMXRHMOxHMfxnMBBTuQkTuYUTuU0TucMzuQszuYczuU8zucCLuQQF3H1uQZcQ64R15hrwjXlmnHNuRZcS64V15prw7Xl2nHtuQ5cR64T15nrwnXlunHduR5cT64X15vrw/Xl+nH9uQHcQG4QN5gbwg3lhnHDuRHcSG4UN5obw43lxnHjuXgugUvkJnATuUncZG4KN5Wbxk3nZnAzuVncbG4ON5ebx83nFnALuUXcYm4Jt5Rbxi3nVnAruVXcam4Nt5Zbx63nNnAbuU3cZm4Lt5Xbxm3ndnA7uV3cbm4Pt5fbx+3nDnAHuUPcYe4Id5Q7xh3nTnAnuVPcae4Md5Y7x53nLnAXuUvcZe4Kd5W7xl3nbnA3uVvcbe4Od5e7x93nHnAPuUfcY+4J95R7xj3nXnAvuVfca+4N95Z7x73nPnAfuU/cZ+4L95X7xn3nfnA/uV/cb+4P95f7xyXhk/LJ+OR8Cj4ln4pPzafh0/Lp+PR8Bj4jn4nPzGfhs/LZ+Ox8Dj4nn4vPzefh8/L5+Px8Ab4gX4gvzBfhi/JxfDG+OF+CL8mX4kvzZfiyfDm+PF+Br8hX4ivzVfiqfDW+Ol+Dr8nX4mvzdfi6fD0+xmM8zhM84Eme4mme4Vme43le4CEv8hIv8wqv8hqv8wZv8hZv8w7v8h7v8wEf8oiP+Pp8A74h34hvzDfhm/LN+OZ8C74l34pvzbfh2/Lt+PZ8B74j34nvzHfhu/Ld+O58D74n34vvzffh+/L9+P78AH4gP4gfzA/hh/LD+OH8CH4kP4ofzY/hx/Lj+PF8PJ/AJ/IT+In8JH4yP4Wfyk/jp/Mz+Jn8LH42P4efy8/j5/ML+IX8In4xv4Rfyi/jl/Mr+JX8Kn41v4Zfy6/j1/Mb+I38Jn4zv4Xfym/jt/M7+J38Ln43v4ffy+/j9/MH+IP8If4wf4Q/yh/jj/Mn+JP8Kf40f4Y/y5/jz/MX+Iv8Jf4yf4W/yl/jr/M3+Jv8Lf42f4e/y9/j7/MP+If8I/4x/4R/yj/jn/Mv+Jf8K/41/4Z/y7/j3/Mf+I/8J/4z/4X/yn/jv/M/+J/8L/43/4f/y//jkwhJhWRCciGFkFJIJaQW0ghphXRCeiGDkFHIJGQWsghZhWxCdiGHkFPIJeQW8gh5hXxCfqGAUFAoJBQWighFhTihmFBcKCGUFEoJpYUyQlmhnFBeqCBUFCoJlYUqQlWhmlBdqCHUFGoJtYU6Ql2hnhATMAEXCAEIpEAJtMAIrMAJvCAIUBAFSZAFRVAFTdAFQzAFS7AFR3AFT/CFQAgFJERCfaGB0FBoJDQWmghNhWZCc6GF0FJoJbQW2ghthXZCe6GD0FHoJHQWughdhW5Cd6GH0FPoJfQW+gh9hX5Cf2GAMFAYJAwWhghDhWHCcGGEMFIYJYwWxghjhXHCeCFeSBAShQnCRGGSMFmYIkwVpgnThRnCTGGWMFuYI8wV5gnzhQXCQmGRsFhYIiwVlgnLhRXCSmGVsFpYI6wV1gnrhQ3CRmGTsFnYImwVtgnbhR3CTmGXsFvYI+wV9gn7hQPCQeGQcFg4IhwVjgnHhRPCSeGUcFo4I5wVzgnnhQvCReGScFm4IlwVrgnXhRvCTeGWcFu4I9wV7gn3hQfCQ+GR8Fh4IjwVngnPhRfCS+GV8Fp4I7wV3gnvhQ/CR+GT8Fn4InwVvgnfhR/CT+GX8Fv4I/wV/glJYFKYDCaHKWBKmAqmhmlgWpgOpocZYEaYCWaGWWBWmA1mhzlgTpgL5oZ5YF6YD+aHBWBBWAgWhkVgURgHi8HisAQsCUvB0rAMLAvLwfKwAqwIK8HKsAqsCqvB6rAGrAlrwdqwDqwL68EYxCAOCQggCSlIQwaykIM8FCCEIpSgDBWoQg3q0IAmtKANHehCD/owgCFEMIL1YQPYEDaCjWET2BQ2g81hC9gStoKtYRvYFraD7WEH2BF2gp1hF9gVdoPdYQ/YE/aCvWEf2Bf2g/3hADgQDoKD4RA4FA6Dw+EIOBKOgqPhGDgWjoPjYTxMgIlwApwIJ8HJcAqcCqfB6XAGnAlnwdlwDpwL58H5cAFcCBfBxXAJXAqXweVwBVwJV8HVcA1cC9fB9XAD3Ag3wc1wC9wKt8HtcAfcCXfB3XAP3Av3wf3wADwID8HD8Ag8Co/B4/AEPAlPwdPwDDwLz8Hz8AK8CC/By/AKvAqvwevwBrwJb8Hb8A68C+/B+/ABfAgfwcfwCXwKn8Hn8AV8CV/B1/ANfAvfwffwA/wIP8HP8Av8Cr/B7/AH/Al/wd/wD/wL/8EkYlIxmZhcTCGmFFOJqcU0YloxnZhezCBmFDOJmcUsYlYxm5hdzCHmFHOJucU8Yl4xn5hfLCAWFAuJhcUiYlExTiwmFhdLiCXFUmJpsYxYViwnlhcriBXFSmJlsYpYVawmVhdriDXFWmJtsY5YV6wnxkRMxEVCBCIpUiItMiIrciIvCiIURVESZVERVVETddEQTdESbdERXdETfTEQQxGJkVhfbCA2FBuJjcUmYlOxmdhcbCG2FFuJrcU2Yluxndhe7CB2FDuJncUuYlexm9hd7CH2FHuJvcU+Yl+xn9hfHCAOFAeJg8Uh4lBxmDhcHCGOFEeJo8Ux4lhxnDhejBcTxERxgjhRnCROFqeIU8Vp4nRxhjhTnCXOFueIc8V54nxxgbhQXCQuFpeIS8Vl4nJxhbhSXCWuFteIa8V14npxg7hR3CRuFreIW8Vt4nZxh7hT3CXuFveIe8V94n7xgHhQPCQeFo+IR8Vj4nHxhHhSPCWeFs+IZ8Vz4nnxgnhRvCReFq+IV8Vr4nXxhnhTvCXeFu+Id8V74n3xgfhQfCQ+Fp+IT8Vn4nPxhfhSfCW+Ft+Ib8V34nvxg/hR/CR+Fr+IX8Vv4nfxh/hT/CX+Fv+If8V/YhIpqZRMSi6lkFJKqaTUUhoprZROSi9lkDJKmaTMUhYpq5RNyi7lkHJKuaTcUh4pr5RPyi8VkApKhaTCUhGpqBQnFZOKSyWkklIpqbRURiorlZPKSxWkilIlqbJURaoqVZOqSzWkmlItqbZUR6or1ZNiEibhEiEBiZQoiZYYiZU4iZcECUqiJEmypEiqpEm6ZEimZEm25Eiu5Em+FEihhKRIqi81kBpKjaTGUhOpqdRMai61kFpKraTWUhuprdROai91kDpKnaTOUhepq9RN6i71kHpKvaTeUh+pr9RP6i8NkAZKg6TB0hBpqDRMGi6NkEZKo6TR0hhprDROGi/FSwlSojRBmihNkiZLU6Sp0jRpujRDminNkmZLc6S50jxpvrRAWigtkhZLS6Sl0jJpubRCWimtklZLa6S10jppvbRB2ihtkjZLW6St0jZpu7RD2intknZLe6S90j5pv3RAOigdkg5LR6Sj0jHpuHRCOimdkk5LZ6Sz0jnpvHRBuihdki5LV6Sr0jXpunRDuindkm5Ld6S70j3pvvRAeig9kh5LT6Sn0jPpufRCeim9kl5Lb6S30jvpvfRB+ih9kj5LX6Sv0jfpu/RD+in9kn5Lf6S/0j8piZxUTiYnl1PIKeVUcmo5jZxWTienlzPIGeVMcmY5i5xVziZnl3PIOeVccm45j5xXzifnlwvIBeVCcmG5iFxUjpOLycXlEnJJuZRcWi4jl5XLyeXlCnJFuZJcWa4iV5WrydXlGnJNuZZcW64j15XryTEZk3GZkIFMypRMy4zMypzMy4IMZVGWZFlWZFXWZF02ZFO2ZFt2ZFf2ZF8O5FBGciTXlxvIDeVGcmO5idxUbiY3l1vILeVWcmu5jdxWbie3lzvIHeVOcme5i9xV7iZ3l3vIPeVecm+5j9xX7if3lwfIA+VB8mB5iDxUHiYPl0fII+VR8mh5jDxWHiePl+PlBDlRniBPlCfJk+Up8lR5mjxdniHPlGfJs+U58lx5njxfXiAvlBfJi+Ul8lJ5mbxcXiGvlFfJq+U18lp5nbxe3iBvlDfJm+Ut8lZ5m7xd3iHvlHfJu+U98l55n7xfPiAflA/Jh+Uj8lH5mHxcPiGflE/Jp+Uz8ln5nHxeviBflC/Jl+Ur8lX5mnxdviHflG/Jt+U78l35nnxffiA/lB/Jj+Un8lP5mfxcfiG/lF/Jr+U38lv5nfxe/iB/lD/Jn+Uv8lf5m/xd/iH/lH/Jv+U/8l/5n5xESaokU5IrKZSUSioltZJGSaukU9IrGZSMSiYls5JFyapkU7IrOZScSi4lt5JHyavkU/IrBZSCSiGlsFJEKarEKcWU4koJpaRSSimtlFHKKuWU8koFpaJSSamsVFGqKtWU6koNpaZSS6mt1FHqKvWUmIIpuEIoQCEVSqEVRmEVTuEVQYGKqEiKrCiKqmiKrhiKqViKrTiKq3iKrwRKqCAlUuorDZSGSiOlsdJEaao0U5orLZSWSiultdJGaau0U9orHZSOSiels9JF6ap0U7orPZSeSi+lt9JH6av0U/orA5SByiBlsDJEGaoMU4YrI5SRyihltDJGGauMU8Yr8UqCkqhMUCYqk5TJyhRlqjJNma7MUGYqs5TZyhxlrjJPma8sUBYqi5TFyhJlqbJMWa6sUFYqq5TVyhplrbJOWa9sUDYqm5TNyhZlq7JN2a7sUHYqu5Tdyh5lr7JP2a8cUA4qh5TDyhHlqHJMOa6cUE4qp5TTyhnlrHJOOa9cUC4ql5TLyhXlqnJNua7cUG4qt5Tbyh3lrnJPua88UB4qj5THyhPlqfJMea68UF4qr5TXyhvlrfJOea98UD4qn5TPyhflq/JN+a78UH4qv5Tfyh/lr/JPSaImVZOpydUUako1lZpaTaOmVdOp6dUMakY1k5pZzaJmVbOp2dUcak41l5pbzaPmVfOp+dUCakG1kFpYLaIWVePUYmpxtYRaUi2lllbLqGXVcmp5tYJaUa2kVlarqFXVamp1tYZaU62l1lbrqHXVempMxVRcJVSgkiql0iqjsiqn8qqgQlVUJVVWFVVVNVVXDdVULdVWHdVVPdVXAzVUkRqp9dUGakO1kdpYbaI2VZupzdUWaku1ldpabaO2Vdup7dUOake1k9pZ7aJ2Vbup3dUeak+1l9pb7aP2Vfup/dUB6kB1kDpYHaIOVYepw9UR6kh1lDpaHaOOVcep49V4NUFNVCeoE9VJ6mR1ijpVnaZOV2eoM9VZ6mx1jjpXnafOVxeoC9VF6mJ1ibpUXaYuV1eoK9VV6mp1jbpWXaeuVzeoG9VN6mZ1i7pV3aZuV3eoO9Vd6m51j7pX3afuVw+oB9VD6mH1iHpUPaYeV0+oJ9VT6mn1jHpWPaeeVy+oF9VL6mX1inpVvaZeV2+oN9Vb6m31jnpXvafeVx+oD9VH6mP1ifpUfaY+V1+oL9VX6mv1jfpWfae+Vz+oH9VP6mf1i/pV/aZ+V3+oP9Vf6m/1j/pX/acm0ZJqybTkWgotpZZKS62l0dJq6bT0WgYto5ZJy6xl0bJq2bTsWg4tp5ZLy63l0fJq+bT8WgGtoFZIK6wV0YpqcVoxrbhWQiupldJKa2W0slo5rbxWQauoVdIqa1W0qlo1rbpWQ6up1dJqa3W0ulo9LaZhGq4RGtBIjdJojdFYjdN4TdCgJmqSJmuKpmqapmuGZmqWZmuO5mqe5muBFmpIi7T6WgOtodZIa6w10ZpqzbTmWgutpdZKa6210dpq7bT2Wgeto9ZJ66x10bpq3bTuWg+tp9ZL66310fpq/bT+2gBtoDZIG6wN0YZqw7Th2ghtpDZKG62N0cZq47TxWryWoCVqE7SJ2iRtsjZFm6pN06ZrM7SZ2ixttjZHm6vN0+ZrC7SF2iJtsbZEW6ot05ZrK7SV2ipttbZGW6ut09ZrG7SN2iZts7ZF26pt07ZrO7Sd2i5tt7ZH26vt0/ZrB7SD2iHtsHZEO6od045rJ7ST2inttHZGO6ud085rF7SL2iXtsnZFu6pd065rN7Sb2i3ttnZHu6vd0+5rD7SH2iPtsfZEe6o9055rL7SX2ivttfZGe6u9095rH7SP2ifts/ZF+6p9075rP7Sf2i/tt/ZH+6v905LoSfVkenI9hZ5ST6Wn1tPoafV0eno9g55Rz6Rn1rPoWfVsenY9h55Tz6Xn1vPoefV8en69gF5QL6QX1ovoRfU4vZheXC+hl9RL6aX1MnpZvZxeXq+gV9Qr6ZX1KnpVvZpeXa+h19Rr6bX1OnpdvZ4e0zEd1wkd6KRO6bTO6KzO6bwu6FAXdUmXdUVXdU3XdUM3dUu3dUd3dU/39UAPdaRHen29gd5Qb6Q31pvoTfVmenO9hd5Sb6W31tvobfV2enu9g95R76R31rvoXfVuene9h95T76X31vvoffV+en99gD5QH6QP1ofoQ/Vh+nB9hD5SH6WP1sfoY/Vx+ng9Xk/QE/UJ+kR9kj5Zn6JP1afp0/UZ+kx9lj5bn6PP1efp8/UF+kJ9kb5YX6Iv1Zfpy/UV+kp9lb5aX6Ov1dfp6/UN+kZ9k75Z36Jv1bfp2/Ud+k59l75b36Pv1ffp+/UD+kH9kH5YP6If1Y/px/UT+kn9lH5aP6Of1c/p5/UL+kX9kn5Zv6Jf1a/p1/Ub+k39ln5bv6Pf1e/p9/UH+kP9kf5Yf6I/1Z/pz/UX+kv9lf5af6O/1d/p7/UP+kf9k/5Z/6J/1b/p3/Uf+k/9l/5b/6P/1f/pSYykRjIjuZHCSGmkMlIbaYy0RjojvZHByGhkMjIbWYysRjYju5HDyGnkMnIbeYy8Rj4jv1HAKGgUMgobRYyiRpxRzChulDBKGqWM0kYZo6xRzihvVDAqGpWMykYVo6pRzahu1DBqGrWM2kYdo65Rz4gZmIEbhAEM0qAM2mAM1uAM3hAMaIiGZMiGYqiGZuiGYZiGZdiGY7iGZ/hGYIQGMiKjvtHAaGg0MhobTYymRjOjudHCaGm0MlobbYy2RjujvdHB6Gh0MjobXYyuRjeju9HD6Gn0MnobfYy+Rj+jvzHAGGgMMgYbQ4yhxjBjuDHCGGmMMkYbY4yxxjhjvBFvJBiJxgRjojHJmGxMMaYa04zpxgxjpjHLmG3MMeYa84z5xgJjobHIWGwsMZYay4zlxgpjpbHKWG2sMdYa64z1xgZjo7HJ2GxsMbYa24ztxg5jp7HL2G3sMfYa+4z9xgHjoHHIOGwcMY4ax4zjxgnjpHHKOG2cMc4a54zzxgXjonHJuGxcMa4a14zrxg3jpnHLuG3cMe4a94z7xgPjofHIeGw8MZ4az4znxgvjpfHKeG28Md4a74z3xgfjo/HJ+Gx8Mb4a34zvxg/jp/HL+G38Mf4a/4wkZlIzmZncTGGmNFOZqc00ZloznZnezGBmNDOZmc0sZlYzm5ndzGHmNHOZuc08Zl4zn5nfLGAWNAuZhc0iZlEzzixmFjdLmCXNUmZps4xZ1ixnljcrmBXNSmZls4pZ1axmVjdrmDXNWmZts45Z16xnxkzMxE3CBCZpUiZtMiZrciZvCiY0RVMyZVMxVVMzddMwTdMybdMxXdMzfTMwQxOZkVnfbGA2NBuZjc0mZlOzmdncbGG2NFuZrc02Zluzndne7GB2NDuZnc0uZlezm9nd7GH2NHuZvc0+Zl+zn9nfHGAONAeZg80h5lBzmDncHGGONEeZo80x5lhznDnejDcTzERzgjnRnGRONqeYU81p5nRzhjnTnGXONueYc8155nxzgbnQXGQuNpeYS81l5nJzhbnSXGWuNteYa8115npzg7nR3GRuNreYW81t5nZzh7nT3GXuNveYe8195n7zgHnQPGQeNo+YR81j5nHzhHnSPGWeNs+YZ81z5nnzgnnRvGReNq+YV81r5nXzhnnTvGXeNu+Yd8175n3zgfnQfGQ+Np+YT81n5nPzhfnSfGW+Nt+Yb8135nvzg/nR/GR+Nr+YX81v5nfzh/nT/GX+Nv+Yf81/ZhIrqZXMSm6lsFJaqazUVhorrZXOSm9lsDJamazMVhYrq5XNym7lsHJauazcVh4rr5XPym8VsApahazCVhGrqBVnFbOKWyWsklYpq7RVxiprlbPKWxWsilYlq7JVxapqVbOqWzWsmlYtq7ZVx6pr1bNiFmbhFmEBi7Qoi7YYi7U4i7cEC1qiJVmypViqpVm6ZVimZVm25Viu5Vm+FVihhazIqm81sBpajazGVhOrqdXMam61sFparazWVhurrdXOam91sDpanazOVherq9XN6m71sHpavazeVh+rr9XP6m8NsAZag6zB1hBrqDXMGm6NsEZao6zR1hhrrDXOGm/FWwlWojXBmmhNsiZbU6yp1jRrujXDmmnNsmZbc6y51jxrvrXAWmgtshZbS6yl1jJrubXCWmmtslZba6y11jprvbXB2mhtsjZbW6yt1jZru7XD2mntsnZbe6y91j5rv3XAOmgdsg5bR6yj1jHruHXCOmmdsk5bZ6yz1jnrvHXBumhdsi5bV6yr1jXrunXDumndsm5bd6y71j3rvvXAemg9sh5bT6yn1jPrufXCemm9sl5bb6y31jvrvfXB+mh9sj5bX6yv1jfru/XD+mn9sn5bf6y/1j8riZ3UTmYnt1PYKe1Udmo7jZ3WTmentzPYGe1MdmY7i53VzmZnt3PYOe1cdm47j53XzmfntwvYBe1CdmG7iF3UjrOL2cXtEnZJu5Rd2i5jl7XL2eXtCnZFu5Jd2a5iV7Wr2dXtGnZNu5Zd265j17Xr2TEbs3GbsIFN2pRN24zN2pzN24INbdGWbNlWbNXWbN02bNO2bNt2bNf2bN8O7NBGdmTXtxvYDe1GdmO7id3UbmY3t1vYLe1Wdmu7jd3Wbme3tzvYHe1Odme7i93V7mZ3t3vYPe1edm+7j93X7mf3twfYA+1B9mB7iD3UHmYPt0fYI+1R9mh7jD3WHmePt+PtBDvRnmBPtCfZk+0p9lR7mj3dnmHPtGfZs+059lx7nj3fXmAvtBfZi+0l9lJ7mb3cXmGvtFfZq+019lp7nb3e3mBvtDfZm+0t9lZ7m73d3mHvtHfZu+099l57n73fPmAftA/Zh+0j9lH7mH3cPmGftE/Zp+0z9ln7nH3evmBftC/Zl+0r9lX7mn3dvmHftG/Zt+079l37nn3ffmA/tB/Zj+0n9lP7mf3cfmG/tF/Zr+039lv7nf3e/mB/tD/Zn+0v9lf7m/3d/mH/tH/Zv+0/9l/7n53ESeokc5I7KZyUTiontZPGSeukc9I7GZyMTiYns5PFyepkc7I7OZycTi4nt5PHyevkc/I7BZyCTiGnsFPEKerEOcWc4k4Jp6RTyintlHHKOuWc8k4Fp6JTyansVHGqOtWc6k4Np6ZTy6nt1HHqOvWcmIM5uEM4wCEdyqEdxmEdzuEdwYGO6EiO7CiO6miO7hiO6ViO7TiO63iO7wRO6CAncuo7DZyGTiOnsdPEaeo0c5o7LZyWTiuntdPGaeu0c9o7HZyOTiens9PF6ep0c7o7PZyeTi+nt9PH6ev0c/o7A5yBziBnsDPEGeoMc4Y7I5yRzihntDPGGeuMc8Y78U6Ck+hMcCY6k5zJzhRnqjPNme7McGY6s5zZzhxnrjPPme8scBY6i5zFzhJnqbPMWe6scFY6q5zVzhpnrbPOWe9scDY6m5zNzhZnq7PN2e7scHY6u5zdzh5nr7PP2e8ccA46h5zDzhHnqHPMOe6ccE46p5zTzhnnrHPOOe9ccC46l5zLzhXnqnPNue7ccG46t5zbzh3nrnPPue88cB46j5zHzhPnqfPMee68cF46r5zXzhvnrfPOee98cD46n5zPzhfnq/PN+e78cH46v5zfzh/nr/PPSeImdZO5yd0Ubko3lZvaTeOmddO56d0MbkY3k5vZzeJmdbO52d0cbk43l5vbzePmdfO5+d0CbkG3kFvYLeIWdePcYm5xt4Rb0i3llnbLuGXdcm55t4Jb0a3kVnaruFXdam51t4Zb063l1nbruHXdem7MxVzcJVzgki7l0i7jsi7n8q7gQld0JVd2FVd1NVd3Ddd0Ldd2Hdd1Pdd3Azd0kRu59d0GbkO3kdvYbeI2dZu5zd0Wbku3ldvabeO2ddu57d0Obke3k9vZ7eJ2dbu53d0ebk+3l9vb7eP2dfu5/d0B7kB3kDvYHeIOdYe5w90R7kh3lDvaHeOOdce54914N8FNdCe4E91J7mR3ijvVneZOd2e4M91Z7mx3jjvXnefOdxe4C91F7mJ3ibvUXeYud1e4K91V7mp3jbvWXeeudze4G91N7mZ3i7vV3eZud3e4O91d7m53j7vX3efudw+4B91D7mH3iHvUPeYed0+4J91T7mn3jHvWPeeedy+4F91L7mX3invVveZed2+4N91b7m33jnvXvefedx+4D91H7mP3ifvUfeY+d1+4L91X7mv3jfvWfee+dz+4H91P7mf3i/vV/eZ+d3+4P91f7m/3j/vX/ecm8ZJ6ybzkXgovpZfKS+2l8dJ66bz0XgYvo5fJy+xl8bJ62bzsXg4vp5fLy+3l8fJ6+bz8XgGvoFfIK+wV8Yp6cV4xr7hXwivplfJKe2W8sl45r7xXwavoVfIqe1W8ql41r7pXw6vp1fJqe3W8ul49L+ZhHu4RHvBIj/Joj/FYj/N4T/CgJ3qSJ3uKp3qap3uGZ3qWZ3uO53qe53uBF3rIi7z6XgOvodfIa+w18Zp6zbzmXguvpdfKa+218dp67bz2Xgevo9fJ6+x18bp63bzuXg+vp9fL6+318fp6/bz+3gBvoDfIG+wN8YZ6w7zh3ghvpDfKG+2N8cZ647zxXryX4CV6E7yJ3iRvsjfFm+pN86Z7M7yZ3ixvtjfHm+vN8+Z7C7yF3iJvsbfEW+ot85Z7K7yV3ipvtbfGW+ut89Z7G7yN3iZvs7fF2+pt87Z7O7yd3i5vt7fH2+vt8/Z7B7yD3iHvsHfEO+od8457J7yT3invtHfGO+ud8857F7yL3iXvsnfFu+pd8657N7yb3i3vtnfHu+vd8+57D7yH3iPvsffEe+o98557L7yX3ivvtffGe+u98957H7yP3ifvs/fF++p98757P7yf3i/vt/fH++v985L4Sf1kfnI/hZ/ST+Wn9tP4af10fno/g5/Rz+Rn9rP4Wf1sfnY/h5/Tz+Xn9vP4ef18fn6/gF/QL+QX9ov4Rf04v5hf3C/hl/RL+aX9Mn5Zv5xf3q/gV/Qr+ZX9Kn5Vv5pf3a/h1/Rr+bX9On5dv54f8zEf9wkf+KRP+bTP+KzP+bwv+NAXfcmXfcVXfc3XfcM3fcu3fcd3fc/3/cAPfeRHfn2/gd/Qb+Q39pv4Tf1mfnO/hd/Sb+W39tv4bf12fnu/g9/R7+R39rv4Xf1ufne/h9/T7+X39vv4ff1+fn9/gD/QH+QP9of4Q/1h/nB/hD/SH+WP9sf4Y/1x/ng/3k/wE/0J/kR/kj/Zn+JP9af50/0Z/kx/lj/bn+PP9ef58/0F/kJ/kb/YX+Iv9Zf5y/0V/kp/lb/aX+Ov9df56/0N/kZ/k7/Z3+Jv9bf52/0d/k5/l7/b3+Pv9ff5+/0D/kH/kH/YP+If9Y/5x/0T/kn/lH/aP+Of9c/55/0L/kX/kn/Zv+Jf9a/51/0b/k3/ln/bv+Pf9e/59/0H/kP/kf/Yf+I/9Z/5z/0X/kv/lf/af+O/9d/57/0P/kf/k//Z/+J/9b/53/0f/k//l//b/+P/9f/5SYKkQbIgeZAiSBmkClIHaYK0QbogfZAhyBhkCjIHWYKsQbYge5AjyBnkCnIHeYK8Qb4gf1AgKBgUCgoHRYKiQVxQLCgelAhKBqWC0kGZoGxQLigfVAgqBpWCykGVoGpQLage1AhqBrWC2kGdoG5QL4gFWIAHRAACMqACOmACNuACPhACGIiBFMiBEqiBFuiBEZiBFdiBE7iBF/hBEIQBCqKgftAgaBg0ChoHTYKmQbOgedAiaBm0CloHbYK2QbugfdAh6Bh0CjoHXYKuQbege9Aj6Bn0CnoHfYK+Qb+gfzAgGBgMCgYHQ4KhwbBgeDAiGBmMCkYHY4KxwbhgfBAfJASJwYRgYjApmBxMCaYG04LpwYxgZjArmB3MCeYG84L5wYJgYbAoWBwsCZYGy4LlwYpgZbAqWB2sCdYG64L1wYZgY7Ap2BxsCbYG24LtwY5gZ7Ar2B3sCfYG+4L9wYHgYHAoOBwcCY4Gx4LjwYngZHAqOB2cCc4G54LzwYXgYnApuBxcCa4G14LrwY3gZnAruB3cCe4G94L7wYPgYfAoeBw8CZ4Gz4LnwYvgZfAqeB28Cd4G74L3wYfgY/Ap+Bx8Cb4G34LvwY/gZ/Ar+B38Cf4G/4IkYdIwWZg8TBGmDFOFqcM0YdowXZg+zBBmDDOFmcMsYdYwW5g9zBHmDHOFucM8Yd4wX5g/LBAWDAuFhcMiYdEwLiwWFg9LhCXDUmHpsExYNiwXlg8rhBXDSmHlsEpYNawWVg9rhDXDWmHtsE5YN6wXxkIsxEMiBCEZUiEdMiEbciEfCiEMxVAK5VAJ1VAL9dAIzdAK7dAJ3dAL/TAIwxCFUVg/bBA2DBuFjcMmYdOwWdg8bBG2DFuFrcM2YduwXdg+7BB2DDuFncMuYdewW9g97BH2DHuFvcM+Yd+wX9g/HBAODAeFg8Mh4dBwWDg8HBGODEeFo8Mx4dhwXDg+jA8TwsRwQjgxnBRODqeEU8Np4fRwRjgznBXODueEc8N54fxwQbgwXBQuDpeES8Nl4fJwRbgyXBWuDteEa8N14fpwQ7gx3BRuDreEW8Nt4fZwR7gz3BXuDveEe8N94f7wQHgwPBQeDo+ER8Nj4fHwRHgyPBWeDs+EZ8Nz4fnwQngxvBReDq+EV8Nr4fXwRngzvBXeDu+Ed8N74f3wQfgwfBQ+Dp+ET8Nn4fPwRfgyfBW+Dt+Eb8N34fvwQ/gx/BR+Dr+EX8Nv4ffwR/gz/BX+Dv+Ef8N/YRKUFCVDyVEKlBKlQqlRGpQWpUPpUQaUEWVCmVEWlBVlQ9lRDpQT5UK5UR6UF+VD+VEBVBAVQoVREVQUxaFiqDgqgUqiUqg0KoPKonKoPKqAKqJKqDKqgqqiaqg6qoFqolqoNqqD6qJ6KIYwhCMCAUQiCtGIQSziEI8EBJGIJCQjBalIQzoykIksZCMHuchDPgpQiBCKUH3UADVEjVBj1AQ1Rc1Qc9QCtUStUGvUBrVF7VB71AF1RJ1QZ9QFdUXdUHfUA/VEvVBv1Af1Rf1QfzQADUSD0GA0BA1Fw9BwNAKNRKPQaDQGjUXj0HgUjxJQIpqAJqJJaDKagqaiaWg6moFmolloNpqD5qJ5aD5agBaiRWgxWoKWomVoOVqBVqJVaDVag9aidWg92oA2ok1oM9qCtqJtaDvagXaiXWg32oP2on1oPzqADqJD6DA6go6iY+g4OoFOolPoNDqDzqJz6Dy6gC6iS+gyuoKuomvoOrqBbqJb6Da6g+6ie+g+eoAeokfoMXqCnqJn6Dl6gV6iV+g1eoPeonfoPfqAPqJP6DP6gr6ib+g7+oF+ol/oN/qD/qJ/KEmUNEoWJY9SRCmjVFHqKE2UNkoXpY8yRBmjTFHmKEuUNcoWZY9yRDmjXFHuKE+UN8oX5Y8KRAWjQlHhqEhUNIqLikXFoxJRyahUVDoqE5WNykXlowpRxahSVDmqElWNqkXVoxpRzahWVDuqE9WN6kWxCIvwiIhAREZUREdMxEZcxEdCBCMxkiI5UiI10iI9MiIzsiI7ciI38iI/CqIwQlEU1Y8aRA2jRlHjqEnUNGoWNY9aRC2jVlHrqE3UNmoXtY86RB2jTlHnqEvUNeoWdY96RD2jXlHvqE/UN+oX9Y8GRAOjQdHgaEg0NBoWDY9GRCOjUdHoaEw0NhoXjY/io4QoMZoQTYwmRZOjKdHUaFo0PZoRzYxmRbOjOdHcaF40P1oQLYwWRYujJf8JggfAuoEAAKDzOm+dbdv2Otv4cS7WxZdkNjrbtm3btm3b78WWxpbFlsdWxFbGVsVWx9bE1sbWxdbHNsQ2xjbFNse2xLbGtsW2x3bEdsZ2xXbH9sT2xvbF9scOxA7GDsUOx47EjsaOxY7HTsROxk7FTsfOxM7GzsXOxy7ELsYuxS7HrsSuxq7FrsduxG7GbsVux+7E7sbuxe7HHsQexh7FHseexJ7GnsWex17EXsZexV7H3sText7F3sc+xD7GPsU+x77Evsa+xb7HfsR+xn7Ffsf+xP7G/sWSYEmxZFhyLAWWEkuFpcbisDRYWiwdlh7LgGXEMmGZsSxYPJYVy4Zlx3JgObFcWG4sD5YXy4flxwpgBbFCWGGsCFYUK4YVx0pgJbFSWGmsDFYWK4eVxypgFbFKWGWsClYVq4ZVx2pgNbFaWG2sDlYXq4fVxxpgDbFGWGOsCdYUa4YlYM2xFlhLrBXWGmuDtcXaYe2xDlhHrBPWGeuCdcW6Yd2xHlhPrBfWG+uDxTAMwzECIzEKozEGYzGAcRiPCZiISZiMKZiKaZiOGRjETMzCbMzBXMzDfAxhARZiEdYX64f1xwZgA7FB2GBsCDYUG4YNx0ZgI7FR2GhsDJaIjcXGYeOxCdhEbBI2GZuCTcWmYdOxGdhMbBY2G5uDzcXmYfOxBdhCbBG2GFuCLcWWYcuxFdhKbBW2GluDrcXWYeuxDdhGbBO2GduCbcW2YduxHdhObBe2G9uD7cX2YfuxA9hB7BB2GDuCHcWOYcexE9hJ7BR2GjuDncXOYeexC9hF7BJ2GbuCXcWuYdexG9hN7BZ2G7uD3cXuYfexB9hD7BH2GHuCPcWeYc+xF9hL7BX2GnuDvcXeYe+xD9hH7BP2GfuCfcW+Yd+xH9hP7Bf2G/uD/cX+YUnwpHgyPDmeAk+Jp8JT43F4Gjwtng5Pj2fAM+KZ8Mx4Fjwez4pnw7PjOfCceC48N54Hz4vnw/PjBfCCeCG8MF4EL4oXw4vjJfCSeCm8NF4GL4uXw8vjFfCKeCW8Ml4Fr4pXw6vjNfCaeC28Nl4Hr4vXw+vjDfCGeCO8Md4Eb4o3wxPw5ngLvCXeCm+Nt8Hb4u3w9ngHvCPeCe+Md8G74t3w7ngPvCfeC++N98FjOIbjOIGTOIXTOIOzOMA5nMcFXMQlXMYVXMU1XMcNHOImbuE27uAu7uE+jvAAD/EI74v3w/vjA/CB+CB8MD4EH4oPw4fjI/CR+Ch8ND4GT8TH4uPw8fgEfCI+CZ+MT8Gn4tPw6fgMfCY+C5+Nz8Hn4vPw+fgCfCG+CF+ML8GX4svw5fgKfCW+Cl+Nr8HX4uvw9fgGfCO+Cd+Mb8G34tvw7fgOfCe+C9+N78H34vvw/fgB/CB+CD+MH8GP4sfw4/gJ/CR+Cj+Nn8HP4ufw8/gF/CJ+Cb+MX8Gv4tfw6/gN/CZ+C7+N38Hv4vfw+/gD/CH+CH+MP8Gf4s/w5/gL/CX+Cn+Nv8Hf4u/w9/gH/CP+Cf+Mf8G/4t/w7/gP/Cf+C/+N/8H/4v/wJERSIhmRnEhBpCRSEamJOCINkZZIR6QnMhAZiUxEZiILEU9kJbIR2YkcRE4iF5GbyEPkJfIR+YkCREGiEFGYKEIUJYoRxYkSREmiFFGaKEOUJcoR5YkKREWiElGZqEJUJaoR1YkaRE2iFlGbqEPUJeoR9YkGREOiEdGYaEI0JZoRCURzogXRkmhFtCbaEG2JdkR7ogPRkehEdCa6EF2JbkR3ogfRk+hF9Cb6EDECI3CCIEiCImiCIVgCEBzBEwIhEhIhEwqhEhqhEwYBCZOwCJtwCJfwCJ9ARECERET0JfoR/YkBxEBiEDGYGEIMJYYRw4kRxEhiFDGaGEMkEmOJccR4YgIxkZhETCamEFOJacR0YgYxk5hFzCbmEHOJecR8YgGxkFhELCaWEEuJZcRyYgWxklhFrCbWEGuJdcR6YgOxkdhEbCa2EFuJbcR2Ygexk9hF7Cb2EHuJfcR+4gBxkDhEHCaOEEeJY8Rx4gRxkjhFnCbOEGeJc8R54gJxkbhEXCauEFeJa8R14gZxk7hF3CbuEHeJe8R94gHxkHhEPCaeEE+JZ8Rz4gXxknhFvCbeEG+Jd8R74gPxkfhEfCa+EF+Jb8R34gfxk/hF/Cb+EH+Jf0QSMimZjExOpiBTkqnI1GQcmYZMS6Yj05MZyIxkJjIzmYWMJ7OS2cjsZA4yJ5mLzE3mIfOS+cj8ZAGyIFmILEwWIYuSxcjiZAmyJFmKLE2WIcuS5cjyZAWyIlmJrExWIauS1cjqZA2yJlmLrE3WIeuS9cj6ZAOyIdmIbEw2IZuSzcgEsjnZgmxJtiJbk23ItmQ7sj3ZgexIdiI7k13IrmQ3sjvZg+xJ9iJ7k33IGImROEmQJEmRNMmQLAlIjuRJgRRJiZRJhVRJjdRJg4SkSVqkTTqkS3qkTyIyIEMyIvuS/cj+5AByIDmIHEwOIYeSw8jh5AhyJDmKHE2OIRPJseQ4cjw5gZxITiInk1PIqeQ0cjo5g5xJziJnk3PIueQ8cj65gFxILiIXk0vIpeQycjm5glxJriJXk2vIteQ6cj25gdxIbiI3k1vIreQ2cju5g9xJ7iJ3k3vIveQ+cj95gDxIHiIPk0fIo+Qx8jh5gjxJniJPk2fIs+Q58jx5gbxIXiIvk1fIq+Q18jp5g7xJ3iJvk3fIu+Q98j75gHxIPiIfk0/Ip+Qz8jn5gnxJviJfk2/It+Q78j35gfxIfiI/k1/Ir+Q38jv5g/xJ/iJ/k3/Iv+Q/MgmVlEpGJadSUCmpVFRqKo5KQ6Wl0lHpqQxURioTlZnKQsVTWalsVHYqB5WTykXlpvJQeal8VH6qAFWQKkQVpopQRaliVHGqBFWSKkWVpspQZalyVHmqAlWRqkRVpqpQValqVHWqBlWTqkXVpupQdal6VH2qAdWQakQ1pppQTalmVALVnGpBtaRaUa2pNlRbqh3VnupAdaQ6UZ2pLlRXqhvVnepB9aR6Ub2pPlSMwiicIiiSoiiaYiiWAhRH8ZRAiZREyZRCqZRG6ZRBQcqkLMqmHMqlPMqnEBVQIRVRfal+VH9qADWQGkQNpoZQQ6lh1HBqBDWSGkWNpsZQidRYahw1nppATaQmUZOpKdRUaho1nZpBzaRmUbOpOdRcah41n1pALaQWUYupJdRSahm1nFpBraRWUaupNdRaah21ntpAbaQ2UZupLdRWahu1ndpB7aR2UbupPdReah+1nzpAHaQOUYepI9RR6hh1nDpBnaROUaepM9RZ6hx1nrpAXaQuUZepK9RV6hp1nbpB3aRuUbepO9Rd6h51n3pAPaQeUY+pJ9RT6hn1nHpBvaReUa+pN9Rb6h31nvpAfaQ+UZ+pL9RX6hv1nfpB/aR+Ub+pP9Rf6h+VhE5KJ6OT0ynolHQqOjUdR6eh09Lp6PR0BjojnYnOTGeh4+msdDY6O52DzknnonPTeei8dD46P12ALkgXogvTReiidDG6OF2CLkmXokvTZeiydDm6PF2BrkhXoivTVeiqdDW6Ol2DrknXomvTdei6dD26Pt2Abkg3ohvTTeimdDM6gW5Ot6Bb0q3o1nQbui3djm5Pd6A70p3oznQXuivdje5O96B70r3o3nQfOkZjNE4TNElTNE0zNEsDmqN5WqBFWqJlWqFVWqN12qAhbdIWbdMO7dIe7dOIDuiQjui+dD+6Pz2AHkgPogfTQ+ih9DB6OD2CHkmPokfTY+hEeiw9jh5PT6An0pPoyfQUeio9jZ5Oz6Bn0rPo2fQcei49j55PL6AX0ovoxfQSeim9jF5Or6BX0qvo1fQaei29jl5Pb6A30pvozfQWeiu9jd5O76B30rvo3fQeei+9j95PH6AP0ofow/QR+ih9jD5On6BP0qfo0/QZ+ix9jj5PX6Av0pfoy/QV+ip9jb5O36Bv0rfo2/Qd+i59j75PP6Af0o/ox/QT+in9jH5Ov6Bf0q/o1/Qb+i39jn5Pf6A/0p/oz/QX+iv9jf5O/6B/0r/o3/Qf+i/9j07CJGWSMcmZFExKJhWTmolj0jBpmXRMeiYDk5HJxGRmsjDxTFYmG5OdycHkZHIxuZk8TF4mH5OfKcAUZAoxhZkiTFGmGFOcKcGUZEoxpZkyTFmmHFOeqcBUZCoxlZkqTFWmGlOdqcHUZGoxtZk6TF2mHlOfacA0ZBoxjZkmTFOmGZPANGdaMC2ZVkxrpg3TlmnHtGc6MB2ZTkxnpgvTlenGdGd6MD2ZXkxvpg8TYzAGZwiGZCiGZhiGZQDDMTwjMCIjMTKjMCqjMTpjMJAxGYuxGYdxGY/xGcQETMhETF+mH9OfGcAMZAYxg5khzFBmGDOcGcGMZEYxo5kxTCIzlhnHjGcmMBOZScxkZgozlZnGTGdmMDOZWcxsZg4zl5nHzGcWMAuZRcxiZgmzlFnGLGdWMCuZVcxqZg2zllnHrGc2MBuZTcxmZguzldnGbGd2MDuZXcxuZg+zl9nH7GcOMAeZQ8xh5ghzlDnGHGdOMCeZU8xp5gxzljnHnGcuMBeZS8xl5gpzlbnGXGduMDeZW8xt5g5zl7nH3GceMA+ZR8xj5gnzlHnGPGdeMC+ZV8xr5g3zlnnHvGc+MB+ZT8xn5gvzlfnGfGd+MD+ZX8xv5g/zl/nHJGGTssnY5GwKNiWbik3NxrFp2LRsOjY9m4HNyGZiM7NZ2Hg2K5uNzc7mYHOyudjcbB42L5uPzc8WYAuyhdjCbBG2KFuMLc6WYEuypdjSbBm2LFuOLc9WYCuyldjKbBW2KluNrc7WYGuytdjabB22LluPrc82YBuyjdjGbBO2KduMTWCbsy3YlmwrtjXbhm3LtmPbsx3YjmwntjPbhe3KdmO7sz3Ynmwvtjfbh42xGIuzBEuyFEuzDMuygOVYnhVYkZVYmVVYldVYnTVYyJqsxdqsw7qsx/osYgM2ZCO2L9uP7c8OYAeyg9jB7BB2KDuMHc6OYEeyo9jR7Bg2kR3LjmPHsxPYiewkdjI7hZ3KTmOnszPYmewsdjY7h53LzmPnswvYhewidjG7hF3KLmOXsyvYlewqdjW7hl3LrmPXsxvYjewmdjO7hd3KbmO3szvYnewudje7h93L7mP3swfYg+wh9jB7hD3KHmOPsyfYk+wp9jR7hj3LnmPPsxfYi+wl9jJ7hb3KXmOvszfYm+wt9jZ7h73L3mPvsw/Yh+wj9jH7hH3KPmOfsy/Yl+wr9jX7hn3LvmPfsx/Yj+wn9jP7hf3KfmO/sz/Yn+wv9jf7h/3L/mOTgKQgGUgOUoCUIBVIDeJAGpAWpAPpQQaQEWQCmUEWEA+ygmwgO8gBcoJcIDfIA/KCfCA/KAAKgkKgMCgCioJioDgoAUqCUqA0KAPKgnKgPKgAKoJKoDKoAqqCaqA6qAFqglqgNqgD6oJ6oD5oABqCRqAxaAKagmYgATQHLUBL0Aq0Bm1AW9AOtAcdQEfQCXQGXUBX0A10Bz1AT9AL9AZ9QAxgAAcEIAEFaMAAFgDAAR4IQAQSkIECVKABHRgAAhNYwAYOcIEHfIBAAEIQgb6gH+gPBoCBYBAYDIaAoWAYGA5GgJFgFBgNxoBEMBaMA+PBBDARTAKTwRQwFUwD08EMMBPMArPBHDAXzAPzwQKwECwCi8ESsBQsA8vBCrASrAKrwRqwFqwD68EGsBFsApvBFrAVbAPbwQ6wE+wCu8EesBfsA/vBAXAQHAKHwRFwFBwDx8EJcBKcAqfBGXAWnAPnwQVwEVwCl8EVcBVcA9fBDXAT3AK3wR1wF9wD98ED8BA8Ao/BE/AUPAPPwQvwErwCr8Eb8Ba8A+/BB/ARfAKfwRfwFXwD38EP8BP8Ar/BH/AX/ANJuKRcMi45l4JLyaXiUnNxXBouLZeOS89l4DJymbjMXBYunsvKZeOyczm4nFwuLjeXh8vL5ePycwW4glwhrjBXhCvKFeOKcyW4klwprjRXhivLlePKcxW4ilwlrjJXhavKVeOqczW4mlwtrjZXh6vL1ePqcw24hlwjrjHXhGvKNeMSuOZcC64l14przbXh2nLtuPZcB64j14nrzHXhunLduO5cD64n14vrzfXhYhzG4RzBkRzF0RzDsRzgOI7nBE7kJE7mFE7lNE7nDA5yJmdxNudwLudxPoe4gAu5iOvL9eP6cwO4gdwgbjA3hBvKDeOGcyO4kdwobjQ3hkvkxnLjuPHcBG4iN4mbzE3hpnLTuOncDG4mN4ubzc3h5nLzuPncAm4ht4hbzC3hlnLLuOXcCm4lt4pbza3h1nLruPXcBm4jt4nbzG3htnLbuO3cDm4nt4vbze3h9nL7uP3cAe4gd4g7zB3hjnLHuOPcCe4kd4o7zZ3hznLnuPPcBe4id4m7zF3hrnLXuOvcDe4md4u7zd3h7nL3uPvcA+4h94h7zD3hnnLPuOfcC+4l94p7zb3h3nLvuPfcB+4j94n7zH3hvnLfuO/cD+4n94v7zf3h/nL/uCR8Uj4Zn5xPwafkU/Gp+Tg+DZ+WT8en5zPwGflMfGY+Cx/PZ+Wz8dn5HHxOPhefm8/D5+Xz8fn5AnxBvhBfmC/CF+WL8cX5EnxJvhRfmi/Dl+XL8eX5CnxFvhJfma/CV+Wr8dX5GnxNvhZfm6/D1+Xr8fX5BnxDvhHfmG/CN+Wb8Ql8c74F35Jvxbfm2/Bt+XZ8e74D35HvxHfmu/Bd+W58d74H35Pvxffm+/AxHuNxnuBJnuJpnuFZHvAcz/MCL/ISL/MKr/Iar/MGD3mTt3ibd3iX93ifR3zAh3zE9+X78f35AfxAfhA/mB/CD+WH8cP5EfxIfhQ/mh/DJ/Jj+XH8eH4CP5GfxE/mp/BT+Wn8dH4GP5Ofxc/m5/Bz+Xn8fH4Bv5BfxC/ml/BL+WX8cn4Fv5Jfxa/m1/Br+XX8en4Dv5HfxG/mt/Bb+W38dn4Hv5Pfxe/m9/B7+X38fv4Af5A/xB/mj/BH+WP8cf4Ef5I/xZ/mz/Bn+XP8ef4Cf5G/xF/mr/BX+Wv8df4Gf5O/xd/m7/B3+Xv8ff4B/5B/xD/mn/BP+Wf8c/4F/5J/xb/m3/Bv+Xf8e/4D/5H/xH/mv/Bf+W/8d/4H/5P/xf/m//B/+X98EiGpkExILqQQUgqphNRCnJBGSCukE9ILGYSMQiYhs5BFiBeyCtmE7EIOIaeQS8gt5BHyCvmE/EIBoaBQSCgsFBGKCsWE4kIJoaRQSigtlBHKCuWE8kIFoaJQSagsVBGqCtWE6kINoaZQS6gt1BHqCvWE+kIDoaHQSGgsNBGaCs2EBKG50EJoKbQSWgtthLZCO6G90EHoKHQSOgtdhK5CN6G70EPoKfQSegt9hJiACbhACKRACbTACKwABE7gBUEQBUmQBUVQBU3QBUOAgilYgi04git4gi8gIRBCIRL6Cv2E/sIAYaAwSBgsDBGGCsOE4cIIYaQwShgtjBEShbHCOGG8MEGYKEwSJgtThKnCNGG6MEOYKcwSZgtzhLnCPGG+sEBYKCwSFgtLhKXCMmG5sEJYKawSVgtrhLXCOmG9sEHYKGwSNgtbhK3CNmG7sEPYKewSdgt7hL3CPmG/cEA4KBwSDgtHhKPCMeG4cEI4KZwSTgtnhLPCOeG8cEG4KFwSLgtXhKvCNeG6cEO4KdwSbgt3hLvCPeG+8EB4KDwSHgtPhKfCM+G58EJ4KbwSXgtvhLfCO+G98EH4KHwSPgtfhK/CN+G78EP4KfwSfgt/hL/CPyGJmFRMJiYXU4gpxVRiajFOTCOmFdOJ6cUMYkYxk5hZzCLGi1nFbGJ2MYeYU8wl5hbziHnFfGJ+sYBYUCwkFhaLiEXFYmJxsYRYUiwllhbLiGXFcmJ5sYJYUawkVhariFXFamJ1sYZYU6wl1hbriHXFemJ9sYHYUGwkNhabiE3FZmKC2FxsIbYUW4mtxTZiW7Gd2F7sIHYUO4mdxS5iV7Gb2F3sIfYUe4m9xT5iTMREXCREUqREWmREVgQiJ/KiIIqiJMqiIqqiJuqiIULRFC3RFh3RFT3RF5EYiKEYiX3FfmJ/cYA4UBwkDhaHiEPFYeJwcYQ4UhwljhbHiIniWHGcOF6cIE4UJ4mTxSniVHGaOF2cIc4UZ4mzxTniXHGeOF9cIC4UF4mLxSXiUnGZuFxcIa4UV4mrxTXiWnGduF7cIG4UN4mbxS3iVnGbuF3cIe4Ud4m7xT3iXnGfuF88IB4UD4mHxSPiUfGYeFw8IZ4UT4mnxTPiWfGceF68IF4UL4mXxSviVfGaeF28Id4Ub4m3xTviXfGeeF98ID4UH4mPxSfiU/GZ+Fx8Ib4UX4mvxTfiW/Gd+F78IH4UP4mfxS/iV/Gb+F38If4Uf4m/xT/iX/GfmERKKiWTkksppJRSKim1FCelkdJK6aT0UgYpo5RJyixlkeKlrFI2KbuUQ8op5ZJyS3mkvFI+Kb9UQCooFZIKS0WkolIxqbhUQioplZJKS2WkslI5qbxUQaooVZIqS1WkqlI1qbpUQ6op1ZJqS3WkulI9qb7UQGooNZIaS02kplIzKUFqLrWQWkqtpNZSG6mt1E5qL3WQOkqdpM5SF6mr1E3qLvWQekq9pN5SHykmYRIuERIpURItMRIrAYmTeEmQREmSZEmRVEmTdMmQoGRKlmRLjuRKnuRLSAqkUIqkvlI/qb80QBooDZIGS0OkodIwabg0QhopjZJGS2OkRGmsNE4aL02QJkqTpMnSFGmqNE2aLs2QZkqzpNnSHGmuNE+aLy2QFkqLpMXSEmmptExaLq2QVkqrpNXSGmmttE5aL22QNkqbpM3SFmmrtE3aLu2Qdkq7pN3SHmmvtE/aLx2QDkqHpMPSEemodEw6Lp2QTkqnpNPSGemsdE46L12QLkqXpMvSFemqdE26Lt2Qbkq3pNvSHemudE+6Lz2QHkqPpMfSE+mp9Ex6Lr2QXkqvpNfSG+mt9E56L32QPkqfpM/SF+mr9E36Lv2Qfkq/pN/SH+mv9E9KIieVk8nJ5RRySjmVnFqOk9PIaeV0cno5g5xRziRnlrPI8XJWOZucXc4h55RzybnlPHJeOZ+cXy4gF5QLyYXlInJRuZhcXC4hl5RLyaXlMnJZuZxcXq4gV5QryZXlKnJVuZpcXa4h15RrybXlOnJduZ5cX24gN5QbyY3lJnJTuZmcIDeXW8gt5VZya7mN3FZuJ7eXO8gd5U5yZ7mL3FXuJneXe8g95V5yb7mPHJMxGZcJmZQpmZYZmZWBzMm8LMiiLMmyrMiqrMm6bMhQNmVLtmVHdmVP9mUkB3IoR3JfuZ/cXx4gD5QHyYPlIfJQeZg8XB4hj5RHyaPlMXKiPFYeJ4+XJ8gT5UnyZHmKPFWeJk+XZ8gz5VnybHmOPFeeJ8+XF8gL5UXyYnmJvFReJi+XV8gr5VXyanmNvFZeJ6+XN8gb5U3yZnmLvFXeJm+Xd8g75V3ybnmPvFfeJ++XD8gH5UPyYfmIfFQ+Jh+XT8gn5VPyafmMfFY+J5+XL8gX5UvyZfmKfFW+Jl+Xb8g35VvybfmOfFe+J9+XH8gP5UfyY/mJ/FR+Jj+XX8gv5Vfya/mN/FZ+J7+XP8gf5U/yZ/mL/FX+Jn+Xf8g/5V/yb/mP/Ff+JydRkirJlORKCiWlkkpJrcQpaZS0SjolvZJByahkUjIrWZR4JauSTcmu5FByKrmU3EoeJa+ST8mvFFAKKoWUwkoRpahSTCmulFBKKqWU0koZpaxSTimvVFAqKpWUykoVpapSTamu1FBqKrWU2kodpa5ST6mvNFAaKo2UxkoTpanSTElQmistlJZKK6W10kZpq7RT2isdlI5KJ6Wz0kXpqnRTuis9lJ5KL6W30keJKZiCK4RCKpRCK4zCKkDhFF4RFFGRFFlRFFXRFF0xFKiYiqXYiqO4iqf4ClICJVQipa/ST+mvDFAGKoOUwcoQZagyTBmujFBGKqOU0coYJVEZq4xTxisTlInKJGWyMkWZqkxTpiszlJnKLGW2MkeZq8xT5isLlIXKImWxskRZqixTlisrlJXKKmW1skZZq6xT1isblI3KJmWzskXZqmxTtis7lJ3KLmW3skfZq+xT9isHlIPKIeWwckQ5qhxTjisnlJPKKeW0ckY5q5xTzisXlIvKJeWyckW5qlxTris3lJvKLeW2cke5q9xT7isPlIfKI+Wx8kR5qjxTnisvlJfKK+W18kZ5q7xT3isflI/KJ+Wz8kX5qnxTvis/lJ/KL+W38kf5q/xTkqhJ1WRqcjWFmlJNpaZW49Q0alo1nZpezaBmVDOpmdUsaryaVc2mZldzqDnVXGpuNY+aV82n5lcLqAXVQmphtYhaVC2mFldLqCXVUmpptYxaVi2nllcrqBXVSmpltYpaVa2mVldrqDXVWmpttY5aV62n1lcbqA3VRmpjtYnaVG2mJqjN1RZqS7WV2lpto7ZV26nt1Q5qR7WT2lntonZVu6nd1R5qT7WX2lvto8ZUTMVVQiVVSqVVRmVVoHIqrwqqqEqqrCqqqmqqrhoqVE3VUm3VUV3VU30VqYEaqpHaV+2n9lcHqAPVQepgdYg6VB2mDldHqCPVUepodYyaqI5Vx6nj1QnqRHWSOlmdok5Vp6nT1RnqTHWWOludo85V56nz1QXqQnWRulhdoi5Vl6nL1RXqSnWVulpdo65V16nr1Q3qRnWTulndom5Vt6nb1R3qTnWXulvdo+5V96n71QPqQfWQelg9oh5Vj6nH1RPqSfWUelo9o55Vz6nn1QvqRfWSelm9ol5Vr6nX1RvqTfWWelu9o95V76n31QfqQ/WR+lh9oj5Vn6nP1RfqS/WV+lp9o75V36nv1Q/qR/WT+ln9on5Vv6nf1R/qT/WX+lv9o/5V/6lJtKRaMi25lkJLqaXSUmtxWhotrZZOS69l0DJqmbTMWhYtXsuqZdOyazm0nFouLbeWR8ur5dPyawW0glohrbBWRCuqFdOKayW0kloprbRWRiurldPKaxW0ilolrbJWRauqVdOqazW0mlotrbZWR6ur1dPqaw20hlojrbHWRGuqNdMStOZaC62l1kprrbXR2mrttPZaB62j1knrrHXRumrdtO5aD62n1kvrrfXRYhqm4RqhkRql0RqjsRrQOI3XBE3UJE3WFE3VNE3XDA1qpmZptuZoruZpvoa0QAu1SOur9dP6awO0gdogbbA2RBuqDdOGayO0kdoobbQ2RkvUxmrjtPHaBG2iNkmbrE3RpmrTtOnaDG2mNkubrc3R5mrztPnaAm2htkhbrC3RlmrLtOXaCm2ltkpbra3R1mrrtPXaBm2jtknbrG3RtmrbtO3aDm2ntkvbre3R9mr7tP3aAe2gdkg7rB3RjmrHtOPaCe2kdko7rZ3RzmrntPPaBe2idkm7rF3RrmrXtOvaDe2mdku7rd3R7mr3tPvaA+2h9kh7rD3RnmrPtOfaC+2l9kp7rb3R3mrvtPfaB+2j9kn7rH3RvmrftO/aD+2n9kv7rf3R/mr/tCR6Uj2ZnlxPoafUU+mp9Tg9jZ5WT6en1zPoGfVMemY9ix6vZ9Wz6dn1HHpOPZeeW8+j59Xz6fn1AnpBvZBeWC+iF9WL6cX1EnpJvZReWi+jl9XL6eX1CnpFvZJeWa+iV9Wr6dX1GnpNvZZeW6+j19Xr6fX1BnpDvZHeWG+iN9Wb6Ql6c72F3lJvpbfW2+ht9XZ6e72D3lHvpHfWu+hd9W56d72H3lPvpffW++gxHdNxndBJndJpndFZHeiczuuCLuqSLuuKruqaruuGDnVTt3Rbd3RX93RfR3qgh3qk99X76f31AfpAfZA+WB+iD9WH6cP1EfpIfZQ+Wh+jJ+pj9XH6eH2CPlGfpE/Wp+hT9Wn6dH2GPlOfpc/W5+hz9Xn6fH2BvlBfpC/Wl+hL9WX6cn2FvlJfpa/W1+hr9XX6en2DvlHfpG/Wt+hb9W36dn2HvlPfpe/W9+h79X36fv2AflA/pB/Wj+hH9WP6cf2EflI/pZ/Wz+hn9XP6ef2CflG/pF/Wr+hX9Wv6df2GflO/pd/W7+h39Xv6ff2B/lB/pD/Wn+hP9Wf6c/2F/lJ/pb/W3+hv9Xf6e/2D/lH/pH/Wv+hf9W/6d/2H/lP/pf/W/+h/9X96EiOpkcxIbqQwUhqpjNRGnJHGSGukM9IbGYyMRiYjs5HFiDeyGtmM7EYOI6eRy8ht5DHyGvmM/EYBo6BRyChsFDGKGsWM4kYJo6RRyihtlDHKGuWM8kYFo6JRyahsVDGqGtWM6kYNo6ZRy6ht1DHqGvWM+kYDo6HRyGhsNDGaGs2MBKO50cJoabQyWhttjLZGO6O90cHoaHQyOhtdjK5GN6O70cPoafQyeht9jJiBGbhBGKRBGbTBGKwBDM7gDcEQDcmQDcVQDc3QDcOAhmlYhm04hmt4hm8gIzBCIzL6Gv2M/sYAY6AxyBhsDDGGGsOM4cYIY6QxyhhtjDESjbHGOGO8McGYaEwyJhtTjKnGNGO6McOYacwyZhtzjLnGPGO+scBYaCwyFhtLjKXGMmO5scJYaawyVhtrjLXGOmO9scHYaGwyNhtbjK3GNmO7scPYaewydht7jL3GPmO/ccA4aBwyDhtHjKPGMeO4ccI4aZwyThtnjLPGOeO8ccG4aFwyLhtXjKvGNeO6ccO4adwybht3jLvGPeO+8cB4aDwyHhtPjKfGM+O58cJ4abwyXhtvjLfGO+O98cH4aHwyPhtfjK/GN+O78cP4afwyfht/jL/GPyMJTAqTweQwBUwJU8HUMA6mgWlhOpgeZoAZYSaYGWaB8TArzAazwxwwJ8wFc8M8MC/MB/PDArAgLAQLwyKwKCwGi8MSsCQsBUvDMrAsLAfLwwqwIqwEK8MqsCqsBqvDGrAmrAVrwzqwLqwH68MGsCFsBBvDJrApbAYTYHPYAraErWBr2Aa2he1ge9gBdoSdYGfYBXaF3WB32AP2hL1gb9gHxiAGcUhAElKQhgxkIYAc5KEARShBGSpQhRrUoQEhNKEFbehAF3rQhwgGMIQR7Av7wf5wABwIB8HBcAgcCofB4XAEHAlHwdFwDEyEY+E4OB5OgBPhJDgZToFT4TQ4Hc6AM+EsOBvOgXPhPDgfLoAL4SK4GC6BS+EyuByugCvhKrgaroFr4Tq4Hm6AG+EmuBlugVvhNrgd7oA74S64G+6Be+E+uB8egAfhIXgYHoFH4TF4HJ6AJ+EpeBqegWfhOXgeXoAX4SV4GV6BV+E1eB3egDfhLXgb3oF34T14Hz6AD+Ej+Bg+gU/hM/gcvoAv4Sv4Gr6Bb+E7+B5+gB/hJ/gZfoFf4Tf4Hf6AP+Ev+Bv+gX/hP5jETGomM5ObKcyUZioztRlnpjHTmunM9GYGM6OZycxsZjHjzaxmNjO7mcPMaeYyc5t5zLxmPjO/WcAsaBYyC5tFzKJmMbO4WcIsaZYyS5tlzLJmObO8WcGsaFYyK5tVzKpmNbO6WcOsadYya5t1zLpmPbO+2cBsaDYyG5tNzKZmMzPBbG62MFuarczWZhuzrdnObG92MDuanczOZhezq9nN7G72MHuavczeZh8zZmImbhImaVImbTImawKTM3lTMEVTMmVTMVVTM3XTMKFpmpZpm47pmp7pm8gMzNCMzL5mP7O/OcAcaA4yB5tDzKHmMHO4OcIcaY4yR5tjzERzrDnOHG9OMCeak8zJ5hRzqjnNnG7OMGeas8zZ5hxzrjnPnG8uMBeai8zF5hJzqbnMXG6uMFeaq8zV5hpzrbnOXG9uMDeam8zN5hZzq7nN3G7uMHeau8zd5h5zr7nP3G8eMA+ah8zD5hHzqHnMPG6eME+ap8zT5hnzrHnOPG9eMC+al8zL5hXzqnnNvG7eMG+at8zb5h3zrnnPvG8+MB+aj8zH5hPzqfnMfG6+MF+ar8zX5hvzrfnOfG9+MD+an8zP5hfzq/nN/G7+MH+av8zf5h/zr/nPTGIltZJZya0UVkorlZXairPSWGmtdFZ6K4OV0cpkZbayWPFWViubld3KYeW0clm5rTxWXiufld8qYBW0ClmFrSJWUauYVdwqYZW0SlmlrTJWWaucVd6qYFW0KlmVrSpWVauaVd2qYdW0alm1rTpWXaueVd9qYDW0GlmNrSZWU6uZlWA1t1pYLa1WVmurjdXWame1tzpYHa1OVmeri9XV6mZ1t3pYPa1eVm+rjxWzMAu3CIu0KIu2GIu1gMVZvCVYoiVZsqVYqqVZumVY0DIty7Itx3Itz/ItZAVWaEVWX6uf1d8aYA20BlmDrSHWUGuYNdwaYY20RlmjrTFWojXWGmeNtyZYE61J1mRrijXVmmZNt2ZYM61Z1mxrjjXXmmfNtxZYC61F1mJribXUWmYtt1ZYK61V1mprjbXWWmettzZYG61N1mZri7XV2mZtt3ZYO61d1m5rj7XX2mfttw5YB61D1mHriHXUOmYdt05YJ61T1mnrjHXWOmedty5YF61L1mXrinXVumZdt25YN61b1m3rjnXXumfdtx5YD61H1mPrifXUemY9t15YL61X1mvrjfXWeme9tz5YH61P1mfri/XV+mZ9t35YP61f1m/rj/XX+mclsZPayezkdgo7pZ3KTm3H2WnstHY6O72dwc5oZ7Iz21nseDurnc3Obuewc9q57Nx2Hjuvnc/ObxewC9qF7MJ2EbuoXcwubpewS9ql7NJ2GbusXc4ub1ewK9qV7Mp2FbuqXc2ubtewa9q17Np2HbuuXc+ubzewG9qN7MZ2E7up3cxOsJvbLeyWdiu7td3Gbmu3s9vbHeyOdie7s93F7mp3s7vbPeyedi+7t93HjtmYjduETdqUTduMzdrA5mzeFmzRlmzZVmzV1mzdNmxom7Zl27Zju7Zn+zayAzu0I7uv3c/ubw+wB9qD7MH2EHuoPcwebo+wR9qj7NH2GDvRHmuPs8fbE+yJ9iR7sj3FnmpPs6fbM+yZ9ix7tj3HnmvPs+fbC+yF9iJ7sb3EXmovs5fbK+yV9ip7tb3GXmuvs9fbG+yN9iZ7s73F3mpvs7fbO+yd9i57t73H3mvvs/fbB+yD9iH7sH3EPmofs4/bJ+yT9in7tH3GPmufs8/bF+yL9iX7sn3Fvmpfs6/bN+yb9i37tn3Hvmvfs+/bD+yH9iP7sf3Efmo/s5/bL+yX9iv7tf3Gfmu/s9/bH+yP9if7s/3F/mp/s7/bP+yf9i/7t/3H/mv/s5M4SZ1kTnInhZPSSeWkduKcNE5aJ52T3sngZHQyOZmdLE68k9XJ5mR3cjg5nVxObiePk9fJ5+R3CjgFnUJOYaeIU9Qp5hR3SjglnVJOaaeMU9Yp55R3KjgVnUpOZaeKU9Wp5lR3ajg1nVpObaeOU9ep59R3GjgNnUZOY6eJ09Rp5iQ4zZ0WTkunldPaaeO0ddo57Z0OTkenk9PZ6eJ0dbo53Z0eTk+nl9Pb6ePEHMzBHcIhHcqhHcZhHeBwDu8IjuhIjuwojupoju4YDnRMx3Jsx3Fcx3N8BzmBEzqR09fp5/R3BjgDnUHOYGeIM9QZ5gx3RjgjnVHOaGeMk+iMdcY5450JzkRnkjPZmeJMdaY5050ZzkxnljPbmePMdeY5850FzkJnkbPYWeIsdZY5y50VzkpnlbPaWeOsddY5650NzkZnk7PZ2eJsdbY5250dzk5nl7Pb2ePsdfY5+50DzkHnkHPYOeIcdY45x50TzknnlHPaOeOcdc45550LzkXnknPZueJcda45150bzk3nlnPbuePcde45950HzkPnkfPYeeI8dZ45z50XzkvnlfPaeeO8dd45750Pzkfnk/PZ+eJ8db45350fzk/nl/Pb+eP8df45SdykbjI3uZvCTemmclO7cW4aN62bzk3vZnAzupnczG4WN97N6mZzs7s53JxuLje3m8fN6+Zz87sF3IJuIbewW8Qt6hZzi7sl3JJuKbe0W8Yt65Zzy7sV3IpuJbeyW8Wt6lZzq7s13JpuLbe2W8et69Zz67sN3IZuI7ex28Rt6jZzE9zmbgu3pdvKbe22cdu67dz2bge3o9vJ7ex2cbu63dzubg+3p9vL7e32cWMu5uIu4ZIu5dIu47IucDmXdwVXdCVXdhVXdTVXdw0XuqZrubbruK7rub6L3MAN3cjt6/Zz+7sD3IHuIHewO8Qd6g5zh7sj3JHuKHe0O8ZNdMe649zx7gR3ojvJnexOcae609zp7gx3pjvLne3Ocee689z57gJ3obvIXewucZe6y9zl7gp3pbvKXe2ucde669z17gZ3o7vJ3exucbe629zt7g53p7vL3e3ucfe6+9z97gH3oHvIPewecY+6x9zj7gn3pHvKPe2ecc+659zz7gX3onvJvexeca+619zr7g33pnvLve3ece+699z77gP3ofvIfew+cZ+6z9zn7gv3pfvKfe2+cd+679z37gf3o/vJ/ex+cb+639zv7g/3p/vL/e3+cf+6/9wkXlIvmZfcS+Gl9FJ5qb04L42X1kvnpfcyeBm9TF5mL4sX72X1snnZvRxeTi+Xl9vL4+X18nn5vQJeQa+QV9gr4hX1innFvRJeSa+UV9or45X1ynnlvQpeRa+SV9mr4lX1qnnVvRpeTa+WV9ur49X16nn1vQZeQ6+R19hr4jX1mnkJXnOvhdfSa+W19tp4bb12Xnuvg9fR6+R19rp4Xb1uXnevh9fT6+X19vp4MQ/zcI/wSI/yaI/xWA94nMd7gid6kid7iqd6mqd7hgc907M823M81/M830Ne4IVe5PX1+nn9vQHeQG+QN9gb4g31hnnDvRHeSG+UN9ob4yV6Y71x3nhvgjfRm+RN9qZ4U71p3nRvhjfTm+XN9uZ4c7153nxvgbfQW+Qt9pZ4S71l3nJvhbfSW+Wt9tZ4a7113npvg7fR2+Rt9rZ4W71t3nZvh7fT2+Xt9vZ4e7193n7vgHfQO+Qd9o54R71j3nHvhHfSO+Wd9s54Z71z3nnvgnfRu+Rd9q54V71r3nXvhnfTu+Xd9u54d7173n3vgffQe+Q99p54T71n3nPvhffSe+W99t54b7133nvvg/fR++R99r54X71v3nfvh/fT++X99v54f71/XhI/qZ/MT+6n8FP6qfzUfpyfxk/rp/PT+xn8jH4mP7OfxY/3s/rZ/Ox+Dj+nn8vP7efx8/r5/Px+Ab+gX8gv7Bfxi/rF/OJ+Cb+kX8ov7Zfxy/rl/PJ+Bb+iX8mv7Ffxq/rV/Op+Db+mX8uv7dfx6/r1/Pp+A7+h38hv7Dfxm/rN/AS/ud/Cb+m38lv7bfy2fju/vd/B7+h38jv7Xfyufje/u9/D7+n38nv7ffyYj/m4T/ikT/m0z/isD3zO533BF33Jl33FV33N133Dh77pW77tO77re77vIz/wQz/y+/r9/P7+AH+gP8gf7A/xh/rD/OH+CH+kP8of7Y/xE/2x/jh/vD/Bn+hP8if7U/yp/jR/uj/Dn+nP8mf7c/y5/jx/vr/AX+gv8hf7S/yl/jJ/ub/CX+mv8lf7a/y1/jp/vb/B3+hv8jf7W/yt/jZ/u7/D3+nv8nf7e/y9/j5/v3/AP+gf8g/7R/yj/jH/uH/CP+mf8k/7Z/yz/jn/vH/Bv+hf8i/7V/yr/jX/un/Dv+nf8m/7d/y7/j3/vv/Af+g/8h/7T/yn/jP/uf/Cf+m/8l/7b/y3/jv/vf/B/+h/8j/7X/yv/jf/u//D/+n/8n/7f/y//j8/CUqKkqHkKAVKiVKh1CgOpUFpUTqUHmVAGVEmlBllQfEoK8qGsqMcKCfKhXKjPCgvyofyowKoICqECqMiqCgqhoqjEqgkKoVKozKoLCqHyqMKqCKqhCqjKqgqqoaqoxqoJqqFaqM6qC6qh+qjBqghaoQaoyaoKWqGElBz1AK1RK1Qa9QGtUXtUHvUAXVEnVBn1AV1Rd1Qd9QD9US9UG/UB8UQhnBEIBJRiEYMYhFAHOKRgEQkIRkpSEUa0pGBIDKRhWzkIBd5yEcIBShEEeqL+qH+aAAaiAahwWgIGoqGoeFoBBqJRqHRaAxKRGPRODQeTUAT0SQ0GU1BU9E0NB3NQDPRLDQbzUFz0Tw0Hy1AC9EitBgtQUvRMrQcrUAr0Sq0Gq1Ba9E6tB5tQBvRJrQZbUFb0Ta0He1AO9EutBvtQXvRPrQfHUAH0SF0GB1BR9ExdBydQCfRKXQanUFn0Tl0Hl1AF9EldBldQVfRNXQd3UA30S10G91Bd9E9dB89QA/RI/QYPUFP0TP0HL1AL9Er9Bq9QW/RO/QefUAf0Sf0GX1BX9E39B39QD/RL/Qb/UF/0T+UJEgaJAuSBymClEGqIHUQF6QJ0gbpgvRBhiBjkCnIHGQJ4oOsQbYge5AjyBnkCnIHeYK8Qb4gf1AgKBgUCgoHRYKiQbGgeFAiKBmUCkoHZYKyQbmgfFAhqBhUCioHVYKqQbWgelAjqBnUCmoHdYK6Qb2gftAgaBg0ChoHTYKmQbMgIWgetAhaBq2C1kGboG3QLmgfdAg6Bp2CzkGXoGvQLege9Ah6Br2C3kGfIBZgAR4QARlQAR0wARuAgAv4QAjEQArkQAnUQAv0wAhgYAZWYAdO4AZe4AcoCIIwiIK+Qb+gfzAgGBgMCgYHQ4KhwbBgeDAiGBmMCkYHY4LEYGwwLhgfTAgmBpOCycGUYGowLZgezAhmBrOC2cGcYG4wL5gfLAgWBouCxcGSYGmwLFgerAhWBquC1cGaYG2wLlgfbAg2BpuCzcGWYGuwLdge7Ah2BruC3cGeYG+wL9gfHAgOBoeCw8GR4GhwLDgenAhOBqeC08GZ4GxwLjgfXAguBpeCy8GV4GpwLbge3AhuBreC28Gd4G5wL7gfPAgeBo+Cx8GT4GnwLHgevAheBq+C18Gb4G3wLngffAg+Bp+Cz8GX4GvwLfge/Ah+Br+C38Gf4G/wL0gSJg2ThcnDFGHKMFWYOowL04Rpw3Rh+jBDmDHMFGYOs4TxYdYwW5g9zBHmDHOFucM8Yd4wX5g/LBAWDAuFhcMiYdGwWFg8LBGWDEuFpcMyYdmwXFg+rBBWDCuFlcMqYdWwWlg9rBHWDGuFtcM6Yd2wXlg/bBA2DBuFjcMmYdOwWZgQNg9bhC3DVmHrsE3YNmwXtg87hB3DTmHnsEvYNewWdg97hD3DXmHvsE8YC7EQD4mQDKmQDpmQDUHIhXwohGIohXKohGqohXpohDA0Qyu0Qyd0Qy/0QxQGYRhGYd+wX9g/HBAODAeFg8Mh4dBwWDg8HBGODEeFo8MxYWI4NhwXjg8nhBPDSeHkcEo4NZwWTg9nhDPDWeHscE44N5wXzg8XhAvDReHicEm4NFwWLg9XhCvDVeHqcE24NlwXrg83hBvDTeHmcEu4NdwWbg93hDvDXeHucE+4N9wX7g8PhAfDQ+Hh8Eh4NDwWHg9PhCfDU+Hp8Ex4NjwXng8vhBfDS+Hl8Ep4NbwWXg9vhDfDW+Ht8E54N7wX3g8fhA/DR+Hj8En4NHwWPg9fhC/DV+Hr8E34NnwXvg8/hB/DT+Hn8Ev4NfwWfg9/hD/DX+Hv8E/4N/wXJomSRsmi5FGKKGWUKkodxUVporRRuih9lCHKGGWKMkdZovgoa5Qtyh7liHJGuaLcUZ4ob5Qvyh8ViApGhaLCUZGoaFQsKh6ViEpGpaLSUZmobFQuKh9ViCpGlaLKUZWoalQtqh7ViGpGtaLaUZ2oblQvqh81iBpGjaLGUZOoadQsSoiaRy2illGrqHXUJmobtYvaRx2ijlGnqHPUJeoadYu6Rz2inlGvqHfUJ4pFWIRHRERGVERHTMRGIOIiPhIiMZIiOVIiNdIiPTIiGJmRFdmRE7mRF/kRioIojKKob9Qv6h8NiAZGg6LB0ZBoaDQsGh6NiEZGo6LR0ZgoMRobjYvGRxOiidGkaHI0JZoaTYumRzOimdGsaHY0J5obzYvmRwuihdGiaHH0nyB4AKwbCAAAOts2Otu22s62bXv7sS7G5eLZtm3btm3jvSWxpbFlseWxFbGVsVWx1bE1sbWxdbH1sQ2xjbFNsc2xLbGtsW2x7bEdsZ2xXbHdsT2xvbF9sf2xA7GDsUOxw7EjsaOxY7HjsROxk7FTsdOxM7GzsXOx87ELsYuxS7HLsSuxq7FrseuxG7GbsVux27E7sbuxe7H7sQexh7FHscexJ7GnsWex57EXsZexV7HXsText7F3sfexD7GPsU+xz7Evsa+xb7HvsR+xn7Ffsd+xP7G/sX+xJFhSLBmWHEuBpcRSYamxNFhaLB2WHsuAZcQyYZmxLFhWLBuWHcuB5cRyYbmxPFheLB+WHyuAFcQKYYWxIlhRLA4rhhXHSmAlsVJYaawMVhYrh5XHKmAVsUpYZawKVhWrhlXHamA1sVpYbawOVherh9XHGmANsUZYY6wJ1hRrhjXHWmDxWAKWiLXEWmGtsTZYW6wd1h7rgHXEOmGdsS5YV6wb1h3rgfXEemG9sT5YX6wf1h8bgA3EBmGDsSHYUGwYNhwbgY3ERmGjsTHYWGwcNh6bgE3EJmGTsSnYVGwaNh2bgc3EZmGzsRiGYThGYCRGYTTGYCzGYTwmYAATMQmTMQVTMQ3TMQMzMQuDmI0hzMFczMN8LMBCLMLmYHOxedh8bAG2EFuELcaWYEuxZdhybAW2EluFrcbWYGuxddh6bAO2EduEbca2YFuxbdh2bAe2E9uF7cb2YHuxfdh+7AB2EDuEHcaOYEexY9hx7AR2EjuFncbOYGexc9h57AJ2EbuEXcauYFexa9h17AZ2E7uF3cbuYHexe9h97AH2EHuEPcaeYE+xZ9hz7AX2EnuFvcbeYG+xd9h77AP2EfuEfca+YF+xb9h37Af2E/uF/cb+YH+xf1gSPCmeDE+Op8BT4qnw1HgaPC2eDk+PZ8Az4pnwzHgWPCueDc+O58Bz4rnw3HgePC+eD8+PF8AL4oXwwngRvCgehxfDi+Ml8JJ4Kbw0XgYvi5fDy+MV8Ip4JbwyXgWvilfDq+M18Jp4Lbw2Xgevi9fD6+MN8IZ4I7wx3gRvijfDm+Mt8Hg8AU/EW+Kt8NZ4G7wt3g5vj3fAO+Kd8M54F7wr3g3vjvfAe+K98N54H7wv3g/vjw/AB+KD8MH4EHwoPgwfjo/AR+Kj8NH4GHwsPg4fj0/AJ+KT8Mn4FHwqPg2fjs/AZ+Kz8Nl4DMdwHCdwEqdwGmdwFudwHhdwgIu4hMu4gqu4huu4gZu4hUPcxhHu4C7u4T4e4CEe4XPwufg8fD6+AF+IL8IX40vwpfgyfDm+Al+Jr8JX42vwtfg6fD2+Ad+Ib8I341vwrfg2fDu+A9+J78J343vwvfg+fD9+AD+IH8IP40fwo/gx/Dh+Aj+Jn8JP42fws/g5/Dx+Ab+IX8Iv41fwq/g1/Dp+A7+J38Jv43fwu/g9/D7+AH+IP8If40/wp/gz/Dn+An+Jv8Jf42/wt/g7/D3+Af+If8I/41/wr/g3/Dv+A/+J/8J/43/wv/g/PAmRlEhGJCdSECmJVERqIg2RlkhHpCcyEBmJTERmIguRlchGZCdyEDmJXERuIg+Rl8hH5CcKEAWJQkRhoghRlIgjihHFiRJESaIUUZooQ5QlyhHliQpERaISUZmoQlQlqhHViRpETaIWUZuoQ9Ql6hH1iQZEQ6IR0ZhoQjQlmhHNiRZEPJFAJBItiVZEa6IN0ZZoR7QnOhAdiU5EZ6IL0ZXoRnQnehA9iV5Eb6IP0ZfoR/QnBhADiUHEYGIIMZQYRgwnRhAjiVHEaGIMMZYYR4wnJhATiUnEZGIKMZWYRkwnZhAziVnEbCJGYAROEARJUARNMARLcARPCAQgREIiZEIhVEIjdMIgTMIiIGETiHAIl/AInwiIkIiIOcRcYh4xn1hALCQWEYuJJcRSYhmxnFhBrCRWEauJNcRaYh2xnthAbCQ2EZuJLcRWYhuxndhB7CR2EbuJPcReYh+xnzhAHCQOEYeJI8RR4hhxnDhBnCROEaeJM8RZ4hxxnrhAXCQuEZeJK8RV4hpxnbhB3CRuEbeJO8Rd4h5xn3hAPCQeEY+JJ8RT4hnxnHhBvCReEa+JN8Rb4h3xnvhAfCQ+EZ+JL8RX4hvxnfhB/CR+Eb+JP8Rf4h+RhExKJiOTkynIlGQqMjWZhkxLpiPTkxnIjGQmMjOZhcxKZiOzkznInGQuMjeZh8xL5iPzkwXIgmQhsjBZhCxKxpHFyOJkCbIkWYosTZYhy5LlyPJkBbIiWYmsTFYhq5LVyOpkDbImWYusTdYh65L1yPpkA7Ih2YhsTDYhm5LNyOZkCzKeTCATyZZkK7I12YZsS7Yj25MdyI5kJ7Iz2YXsSnYju5M9yJ5kL7I32YfsS/Yj+5MDyIHkIHIwOYQcSg4jh5MjyJHkKHI0OYYcS44jx5MTyInkJHIyOYWcSk4jp5MzyJnkLHI2GSMxEicJkiQpkiYZkiU5kicFEpAiKZEyqZAqqZE6aZAmaZGQtElEOqRLeqRPBmRIRuQcci45j5xPLiAXkovIxeQScim5jFxOriBXkqvI1eQaci25jlxPbiA3kpvIzeQWciu5jdxO7iB3krvI3eQeci+5j9xPHiAPkofIw+QR8ih5jDxOniBPkqfI0+QZ8ix5jjxPXiAvkpfIy+QV8ip5jbxO3iBvkrfI2+Qd8i55j7xPPiAfko/Ix+QT8in5jHxOviBfkq/I1+Qb8i35jnxPfiA/kp/Iz+QX8iv5jfxO/iB/kr/I3+Qf8i/5j0xCJaWSUcmpFFRKKhWVmkpDpaXSUempDFRGKhOVmcpCZaWyUdmpHFROKheVm8pD5aXyUfmpAlRBqhBVmCpCFaXiqGJUcaoEVZIqRZWmylBlqXJUeaoCVZGqRFWmqlBVqWpUdaoGVZOqRdWm6lB1qXpUfaoB1ZBqRDWmmlBNqWZUc6oFFU8lUIlUS6oV1ZpqQ7Wl2lHtqQ5UR6oT1ZnqQnWlulHdqR5UT6oX1ZvqQ/Wl+lH9qQHUQGoQNZgaQg2lhlHDqRHUSGoUNZoaQ42lxlHjqQnURGoSNZmaQk2lplHTqRnUTGoWNZuKURiFUwRFUhRFUwzFUhzFUwIFKJGSKJlSKJXSKJ0yKJOyKEjZFKIcyqU8yqcCKqQiag41l5pHzacWUAupRdRiagm1lFpGLadWUCupVdRqag21llpHrac2UBupTdRmagu1ldpGbad2UDupXdRuag+1l9pH7acOUAepQ9Rh6gh1lDpGHadOUCepU9Rp6gx1ljpHnacuUBepS9Rl6gp1lbpGXaduUDepW9Rt6g51l7pH3aceUA+pR9Rj6gn1lHpGPadeUC+pV9Rr6g31lnpHvac+UB+pT9Rn6gv1lfpGfad+UD+pX9Rv6g/1l/pHJaGT0sno5HQKOiWdik5Np6HT0uno9HQGOiOdic5MZ6Gz0tno7HQOOiedi85N56Hz0vno/HQBuiBdiC5MF6GL0nF0Mbo4XYIuSZeiS9Nl6LJ0Obo8XYGuSFeiK9NV6Kp0Nbo6XYOuSdeia9N16Lp0Pbo+3YBuSDeiG9NN6KZ0M7o53YKOpxPoRLol3YpuTbeh29Lt6PZ0B7oj3YnuTHehu9Ld6O50D7on3YvuTfeh+9L96P70AHogPYgeTA+hh9LD6OH0CHokPYoeTY+hx9Lj6PH0BHoiPYmeTE+hp9LT6On0DHomPYueTcdojMZpgiZpiqZphmZpjuZpgQa0SEu0TCu0Smu0Thu0SVs0pG0a0Q7t0h7t0wEd0hE9h55Lz6Pn0wvohfQiejG9hF5KL6OX0yvolfQqejW9hl5Lr6PX0xvojfQmejO9hd5Kb6O30zvonfQueje9h95L76P30wfog/Qh+jB9hD5KH6OP0yfok/Qp+jR9hj5Ln6PP0xfoi/Ql+jJ9hb5KX6Ov0zfom/Qt+jZ9h75L36Pv0w/oh/Qj+jH9hH5KP6Of0y/ol/Qr+jX9hn5Lv6Pf0x/oj/Qn+jP9hf5Kf6O/0z/on/Qv+jf9h/5L/6OTMEmZZExyJgWTkknFpGbSMGmZdEx6JgOTkcnEZGayMFmZbEx2JgeTk8nF5GbyMHmZfEx+pgBTkCnEFGaKMEWZOKYYU5wpwZRkSjGlmTJMWaYcU56pwFRkKjGVmSpMVaYaU52pwdRkajG1mTpMXaYeU59pwDRkGjGNmSZMU6YZ05xpwcQzCUwi05JpxbRm2jBtmXZMe6YD05HpxHRmujBdmW5Md6YH05PpxfRm+jB9mX5Mf2YAM5AZxAxmhjBDmWHMcGYEM5IZxYxmxjBjmXHMeGYCM5GZxExmpjBTmWnMdGYGM5OZxcxmYgzG4AzBkAzF0AzDsAzH8IzAAEZkJEZmFEZlNEZnDMZkLAYyNoMYh3EZj/GZgAmZiJnDzGXmMfOZBcxCZhGzmFnCLGWWMcuZFcxKZhWzmlnDrGXWMeuZDcxGZhOzmdnCbGW2MduZHcxOZhezm9nD7GX2MfuZA8xB5hBzmDnCHGWOMceZE8xJ5hRzmjnDnGXOMeeZC8xF5hJzmbnCXGWuMdeZG8xN5hZzm7nD3GXuMfeZB8xD5hHzmHnCPGWeMc+ZF8xL5hXzmnnDvGXeMe+ZD8xH5hPzmfnCfGW+Md+ZH8xP5hfzm/nD/GX+MUnYpGwyNjmbgk3JpmJTs2nYtGw6Nj2bgc3IZmIzs1nYrGw2Njubg83J5mJzs3nYvGw+Nj9bgC3IFmILs0XYomwcW4wtzpZgS7Kl2NJsGbYsW44tz1ZgK7KV2MpsFbYqW42tztZga7K12NpsHbYuW4+tzzZgG7KN2MZsE7Yp24xtzrZg49kENpFtybZiW7Nt2LZsO7Y924HtyHZiO7Nd2K5sN7Y724PtyfZie7N92L5sP7Y/O4AdyA5iB7ND2KHsMHY4O4IdyY5iR7Nj2LHsOHY8O4GdyE5iJ7NT2KnsNHY6O4Odyc5iZ7MxFmNxlmBJlmJplmFZlmN5VmABK7ISK7MKq7Iaq7MGa7IWC1mbRazDuqzH+mzAhmzEzmHnsvPY+ewCdiG7iF3MLmGXssvY5ewKdiW7il3NrmHXsuvY9ewGdiO7id3MbmG3stvY7ewOdie7i93N7mH3svvY/ewB9iB7iD3MHmGPssfY4+wJ9iR7ij3NnmHPsufY8+wF9iJ7ib3MXmGvstfY6+wN9iZ7i73N3mHvsvfY++wD9iH7iH3MPmGfss/Y5+wL9iX7in3NvmHfsu/Y9+wH9iP7if3MfmG/st/Y7+wP9if7i/3N/mH/sv/YJFxSLhmXnEvBpeRScam5NFxaLh2XnsvAZeQycZm5LFxWLhuXncvB5eRycbm5PFxeLh+XnyvAFeQKcYW5IlxRLo4rxhXnSnAluVJcaa4MV5Yrx5XnKnAVuUpcZa4KV5WrxlXnanA1uVpcba4OV5erx9XnGnANuUZcY64J15RrxjXnWnDxXAKXyLXkWnGtuTZcW64d157rwHXkOnGduS5cV64b153rwfXkenG9uT5cX64f158bwA3kBnGDuSHcUG4YN5wbwY3kRnGjuTHcWG4cN56bwE3kJnGTuSncVG4aN52bwc3kZnGzuRiHcThHcCRHcTTHcCzHcTwncIATOYmTOYVTOY3TOYMzOYuDnM0hzuFczuN8LuBCLuLmcHO5edx8bgG3kFvELeaWcEu5ZdxybgW3klvFrebWcGu5ddx6bgO3kdvEbea2cFu5bdx2bge3k9vF7eb2cHu5fdx+7gB3kDvEHeaOcEe5Y9xx7gR3kjvFnebOcGe5c9x57gJ3kbvEXeaucFe5a9x17gZ3k7vF3ebucHe5e9x97gH3kHvEPeaecE+5Z9xz7gX3knvFvebecG+5d9x77gP3kfvEfea+cF+5b9x37gf3k/vF/eb+cH+5f1wSPimfjE/Op+BT8qn41HwaPi2fjk/PZ+Az8pn4zHwWPiufjc/O5+Bz8rn43HwePi+fj8/PF+AL8oX4wnwRvigfxxfji/Ml+JJ8Kb40X4Yvy5fjy/MV+Ip8Jb4yX4Wvylfjq/M1+Jp8Lb42X4evy9fj6/MN+IZ8I74x34Rvyjfjm/Mt+Hg+gU/kW/Kt+NZ8G74t345vz3fgO/Kd+M58F74r343vzvfge/K9+N58H74v34/vzw/gB/KD+MH8EH4oP4wfzo/gR/Kj+NH8GH4sP44fz0/gJ/KT+Mn8FH4qP42fzs/gZ/Kz+Nl8jMd4nCd4kqd4mmd4lud4nhd4wIu8xMu8wqu8xuu8wZu8xUPe5hHv8C7v8T4f8CEf8XP4ufw8fj6/gF/IL+IX80v4pfwyfjm/gl/Jr+JX82v4tfw6fj2/gd/Ib+I381v4rfw2fju/g9/J7+J383v4vfw+fj9/gD/IH+IP80f4o/wx/jh/gj/Jn+JP82f4s/w5/jx/gb/IX+Iv81f4q/w1/jp/g7/J3+Jv83f4u/w9/j7/gH/IP+If80/4p/wz/jn/gn/Jv+Jf82/4t/w7/j3/gf/If+I/81/4r/w3/jv/g//J/+J/83/4v/w/PomQVEgmJBdSCCmFVEJqIY2QVkgnpBcyCBmFTEJmIYuQVcgmZBdyCDmFXEJuIY+QV8gn5BcKCAWFQkJhoYhQVIgTignFhRJCSaGUUFooI5QVygnlhQpCRaGSUFmoIlQVqgnVhRpCTaGWUFuoI9QV6gn1hQZCQ6GR0FhoIjQVmgnNhRZCvJAgJAothVZCa6GN0FZoJ7QXOggdhU5CZ6GL0FXoJnQXegg9hV5Cb6GP0FfoJ/QXBggDhUHCYGGIMFQYJgwXRggjhVHCaGGMMFYYJ4wXJggThUnCZGGKMFWYJkwXZggzhVnCbCEmYAIuEAIpUAItMAIrcAIvCAIQREESZEERVEETdMEQTMESoGALSHAEV/AEXwiEUIiEOcJcYZ4wX1ggLBQWCYuFJcJSYZmwXFghrBRWCauFNcJaYZ2wXtggbBQ2CZuFLcJWYZuwXdgh7BR2CbuFPcJeYZ+wXzggHBQOCYeFI8JR4ZhwXDghnBROCaeFM8JZ4ZxwXrggXBQuCZeFK8JV4ZpwXbgh3BRuCbeFO8Jd4Z5wX3ggPBQeCY+FJ8JT4ZnwXHghvBReCa+FN8Jb4Z3wXvggfBQ+CZ+FL8JX4ZvwXfgh/BR+Cb+FP8Jf4Z+QBCQFyUBykAKkBKlAapAGpAXpQHqQAWQEmUBmkAVkBdlAdpAD5AS5QG6QB+QF+UB+UAAUBIVAYVAEFAVxoBgoDkqAkqAUKA3KgLKgHCgPKoCKoBKoDKqAqqAaqA5qgJqgFqgN6oC6oB6oDxqAhqARaAyagKagGWgOWoB4kAASQUvQCrQGbUBb0A60Bx1AR9AJdAZdQFfQDXQHPUBP0Av0Bn1AX9AP9AcDwEAwCAwGQ8BQMAwMByPASDAKjAZjwFgwDowHE8BEMAlMBlPAVDANTAczwEwwC8wGMYABHBCABBSgAQNYwAEeCAAAEUhABgpQgQZ0YAATWAACGyDgABd4wAcBCEEE5oC5YB6YDxaAhWARWAyWgKVgGVgOVoCVYBVYDdaAtWAdWA82gI1gE9gMtoCtYBvYDnaAnWAX2A32gL1gH9gPDoCD4BA4DI6Ao+AYOA5OgJPgFDgNzoCz4Bw4Dy6Ai+ASuAyugKvgGrgOboCb4Ba4De6Au+AeuA8egIfgEXgMnoCn4Bl4Dl6Al+AVeA3egLfgHXgPPoCP4BP4DL6Ar+Ab+A5+gJ/gF/gN/oC/4B9IIiYVk4nJxRRiSjGVmFpMI6YV04npxQxiRjGTmFnMImYVs4nZxRxiTjGXmFvMI+YV84n5xQJiQbGQWFgsIhYV48RiYnGxhFhSLCWWFsuIZcVyYnmxglhRrCRWFquIVcVqYnWxhlhTrCXWFuuIdcV6Yn2xgdhQbCQ2FpuITcVmYnOxhRgvJoiJYkuxldhabCO2FduJ7cUOYkexk9hZ7CJ2FbuJ3cUeYk+xl9hb7CP2FfuJ/cUB4kBxkDhYHCIOFYeJw8UR4khxlDhaHCOOFceJ48UJ4kRxkjhZnCJOFaeJ08UZ4kxxljhbjImYiIuESIqUSIuMyIqcyIuCCERRlERZVERV1ERdNERTtEQo2iISHdEVPdEXAzEUI3GOOFecJ84XF4gLxUXiYnGJuFRcJi4XV4grxVXianGNuFZcJ64XN4gbxU3iZnGLuFXcJm4Xd4g7xV3ibnGPuFfcJ+4XD4gHxUPiYfGIeFQ8Jh4XT4gnxVPiafGMeFY8J54XL4gXxUviZfGKeFW8Jl4Xb4g3xVvibfGOeFe8J94XH4gPxUfiY/GJ+FR8Jj4XX4gvxVfia/GN+FZ8J74XP4gfxU/iZ/GL+FX8Jn4Xf4g/xV/ib/GP+Ff8JyaRkkrJpORSCimllEpKLaWR0krppPRSBimjlEnKLGWRskrZpOxSDimnlEvKLeWR8kr5pPxSAamgVEgqLBWRikpxUjGpuFRCKimVkkpLZaSyUjmpvFRBqihVkipLVaSqUjWpulRDqinVkmpLdaS6Uj2pvtRAaig1khpLTaSmUjOpudRCipcSpESppdRKai21kdpK7aT2Ugepo9RJ6ix1kbpK3aTuUg+pp9RL6i31kfpK/aT+0gBpoDRIGiwNkYZKw6Th0ghppDRKGi2NkcZK46Tx0gRpojRJmixNkaZK06Tp0gxppjRLmi3FJEzCJUIiJUqiJUZiJU7iJUECkihJkiwpkippki4ZkilZEpRsCUmO5Eqe5EuBFEqRNEeaK82T5ksLpIXSImmxtERaKi2TlksrpJXSKmm1tEZaK62T1ksbpI3SJmmztEXaKm2Ttks7pJ3SLmm3tEfaK+2T9ksHpIPSIemwdEQ6Kh2TjksnpJPSKem0dEY6K52TzksXpIvSJemydEW6Kl2Trks3pJvSLem2dEe6K92T7ksPpIfSI+mx9ER6Kj2TnksvpJfSK+m19EZ6K72T3ksfpI/SJ+mz9EX6Kn2Tvks/pJ/SL+m39Ef6K/2TkshJ5WRycjmFnFJOJaeW08hp5XRyejmDnFHOJGeWs8hZ5WxydjmHnFPOJeeW88h55XxyfrmAXFAuJBeWi8hF5Ti5mFxcLiGXlEvJpeUyclm5nFxeriBXlCvJleUqclW5mlxdriHXlGvJteU6cl25nlxfbiA3lBvJjeUmclO5mdxcbiHHywlyotxSbiW3ltvIbeV2cnu5g9xR7iR3lrvIXeVucne5h9xT7iX3lvvIfeV+cn95gDxQHiQPlofIQ+Vh8nB5hDxSHiWPlsfIY+Vx8nh5gjxRniRPlqfIU+Vp8nR5hjxTniXPlmMyJuMyIZMyJdMyI7MyJ/OyIANZlCVZlhVZlTVZlw3ZlC0ZyraMZEd2ZU/25UAO5UieI8+V58nz5QXyQnmRvFheIi+Vl8nL5RXySnmVvFpeI6+V18nr5Q3yRnmTvFneIm+Vt8nb5R3yTnmXvFveI++V98n75QPyQfmQfFg+Ih+Vj8nH5RPySfmUfFo+I5+Vz8nn5QvyRfmSfFm+Il+Vr8nX5RvyTfmWfFu+I9+V78n35QfyQ/mR/Fh+Ij+Vn8nP5RfyS/mV/Fp+I7+V38nv5Q/yR/mT/Fn+In+Vv8nf5R/yT/mX/Fv+I/+V/8lJlKRKMiW5kkJJqaRSUitplLRKOiW9kkHJqGRSMitZlKxKNiW7kkPJqeRScit5lLxKPiW/UkApqBRSCitFlKJKnFJMKa6UUEoqpZTSShmlrFJOKa9UUCoqlZTKShWlqlJNqa7UUGoqtZTaSh2lrlJPqa80UBoqjZTGShOlqdJMaa60UOKVBCVRaam0UlorbZS2SjulvdJB6ah0UjorXZSuSjelu9JD6an0UnorfZS+Sj+lvzJAGagMUgYrQ5ShyjBluDJCGamMUkYrY5SxyjhlvDJBmahMUiYrU5SpyjRlujJDmanMUmYrMQVTcIVQSIVSaIVRWIVTeEVQgCIqkiIriqIqmqIrhmIqlgIVW0GKo7iKp/hKoIRKpMxR5irzlPnKAmWhskhZrCxRlirLlOXKCmWlskpZraxR1irrlPXKBmWjsknZrGxRtirblO3KDmWnskvZrexR9ir7lP3KAeWgckg5rBxRjirHlOPKCeWkcko5rZxRzirnlPPKBeWickm5rFxRrirXlOvKDeWmcku5rdxR7ir3lPvKA+Wh8kh5rDxRnirPlOfKC+Wl8kp5rbxR3irvlPfKB+Wj8kn5rHxRvirflO/KD+Wn8kv5rfxR/ir/lCRqUjWZmlxNoaZUU6mp1TRqWjWdml7NoGZUM6mZ1SxqVjWbml3NoeZUc6m51TxqXjWfml8toBZUC6mF1SJqUTVOLaYWV0uoJdVSamm1jFpWLaeWVyuoFdVKamW1ilpVraZWV2uoNdVaam21jlpXrafWVxuoDdVGamO1idpUbaY2V1uo8WqCmqi2VFuprdU2alu1ndpe7aB2VDupndUuale1m9pd7aH2VHupvdU+al+1n9pfHaAOVAepg9Uh6lB1mDpcHaGOVEepo9Ux6lh1nDpenaBOVCepk9Up6lR1mjpdnaHOVGeps9WYiqm4SqikSqm0yqisyqm8KqhAFVVJlVVFVVVN1VVDNVVLhaqtItVRXdVTfTVQQzVS56hz1XnqfHWBulBdpC5Wl6hL1WXqcnWFulJdpa5W16hr1XXqenWDulHdpG5Wt6hb1W3qdnWHulPdpe5W96h71X3qfvWAelA9pB5Wj6hH1WPqcfWEelI9pZ5Wz6hn1XPqefWCelG9pF5Wr6hX1WvqdfWGelO9pd5W76h31XvqffWB+lB9pD5Wn6hP1Wfqc/WF+lJ9pb5W36hv1Xfqe/WD+lH9pH5Wv6hf1W/qd/WH+lP9pf5W/6h/1X9qEi2plkxLrqXQUmqptNRaGi2tlk5Lr2XQMmqZtMxaFi2rlk3LruXQcmq5tNxaHi2vlk/LrxXQCmqFtMJaEa2oFqcV04prJbSSWimttFZGK6uV08prFbSKWiWtslZFq6pV06prNbSaWi2ttlZHq6vV0+prDbSGWiOtsdZEa6o105prLbR4LUFL1FpqrbTWWhutrdZOa6910DpqnbTOWhetq9ZN66710HpqvbTeWh+tr9ZP668N0AZqg7TB2hBtqDZMG66N0EZqo7TR2hhtrDZOG69N0CZqk7TJ2hRtqjZNm67N0GZqs7TZWkzDNFwjNFKjNFpjNFbjNF4TNKCJmqTJmqKpmqbpmqGZmqVBzdaQ5miu5mm+FmihFmlztLnaPG2+tkBbqC3SFmtLtKXaMm25tkJbqa3SVmtrtLXaOm29tkHbqG3SNmtbtK3aNm27tkPbqe3Sdmt7tL3aPm2/dkA7qB3SDmtHtKPaMe24dkI7qZ3STmtntLPaOe28dkG7qF3SLmtXtKvaNe26dkO7qd3Sbmt3tLvaPe2+9kB7qD3SHmtPtKfaM+259kJ7qb3SXmtvtLfaO+299kH7qH3SPmtftK/aN+279kP7qf3Sfmt/tL/aPy2JnlRPpifXU+gp9VR6aj2NnlZPp6fXM+gZ9Ux6Zj2LnlXPpmfXc+g59Vx6bj2PnlfPp+fXC+gF9UJ6Yb2IXlSP04vpxfUSekm9lF5aL6OX1cvp5fUKekW9kl5Zr6JX1avp1fUaek29ll5br6PX1evp9fUGekO9kd5Yb6I31ZvpzfUWeryeoCfqLfVWemu9jd5Wb6e31zvoHfVOeme9i95V76Z313voPfVeem+9j95X76f31wfoA/VB+mB9iD5UH6YP10foI/VR+mh9jD5WH6eP1yfoE/VJ+mR9ij5Vn6ZP12foM/VZ+mw9pmM6rhM6qVM6rTM6q3M6rws60EVd0mVd0VVd03Xd0E3d0qFu60h3dFf3dF8P9FCP9Dn6XH2ePl9foC/UF+mL9SX6Un2Zvlxfoa/UV+mr9TX6Wn2dvl7foG/UN+mb9S36Vn2bvl3foe/Ud+m79T36Xn2fvl8/oB/UD+mH9SP6Uf2Yflw/oZ/UT+mn9TP6Wf2cfl6/oF/UL+mX9Sv6Vf2afl2/od/Ub+m39Tv6Xf2efl9/oD/UH+mP9Sf6U/2Z/lx/ob/UX+mv9Tf6W/2d/l7/oH/UP+mf9S/6V/2b/l3/of/Uf+m/9T/6X/2fnsRIaiQzkhspjJRGKiO1kcZIa6Qz0hsZjIxGJiOzkcXIamQzshs5jJxGLiO3kcfIa+Qz8hsFjIJGIaOwUcQoasQZxYziRgmjpFHKKG2UMcoa5YzyRgWjolHJqGxUMaoa1YzqRg2jplHLqG3UMeoa9Yz6RgOjodHIaGw0MZoazYzmRgsj3kgwEo2WRiujtdHGaGu0M9obHYyORiejs9HF6Gp0M7obPYyeRi+jt9HH6Gv0M/obA4yBxiBjsDHEGGoMM4YbI4yRxihjtDHGGGuMM8YbE4yJxiRjsjHFmGpMM6YbM4yZxixjthEzMAM3CIM0KIM2GIM1OIM3BAMYoiEZsqEYqqEZumEYpmEZ0LANZDiGa3iGbwRGaETGHGOuMc+YbywwFhqLjMXGEmOpscxYbqwwVhqrjNXGGmOtsc5Yb2wwNhqbjM3GFmOrsc3Ybuwwdhq7jN3GHmOvsc/YbxwwDhqHjMPGEeOoccw4bpwwThqnjNPGGeOscc44b1wwLhqXjMvGFeOqcc24btwwbhq3jNvGHeOucc+4bzwwHhqPjMfGE+Op8cx4brwwXhqvjNfGG+Ot8c54b3wwPhqfjM/GF+Or8c34bvwwfhq/jN/GH+Ov8c9IYiY1k5nJzRRmSjOVmdpMY6Y105npzQxmRjOTmdnMYmY1s5nZzRxmTjOXmdvMY+Y185n5zQJmQbOQWdgsYhY148xiZnGzhFnSLGWWNsuYZc1yZnmzglnRrGRWNquYVc1qZnWzhlnTrGXWNuuYdc16Zn2zgdnQbGQ2NpuYTc1mZnOzhRlvJpiJZkuzldnabGO2NduZ7c0OZkezk9nZ7GJ2NbuZ3c0eZk+zl9nb7GP2NfuZ/c0B5kBzkDnYHGIONYeZw80R5khzlDnaHGOONceZ480J5kRzkjnZnGJONaeZ080Z5kxzljnbjJmYiZuESZqUSZuMyZqcyZuCCUzRlEzZVEzV1EzdNEzTtExo2iYyHdM1PdM3AzM0I3OOOdecZ843F5gLzUXmYnOJudRcZi43V5grzVXmanONudZcZ643N5gbzU3mZnOLudXcZm43d5g7zV3mbnOPudfcZ+43D5gHzUPmYfOIedQ8Zh43T5gnzVPmafOMedY8Z543L5gXzUvmZfOKedW8Zl43b5g3zVvmbfOOede8Z943H5gPzUfmY/OJ+dR8Zj43X5gvzVfma/ON+dZ8Z743P5gfzU/mZ/OL+dX8Zn43f5g/zV/mb/OP+df8ZyaxklrJrORWCiullcpKbaWx0lrprPRWBiujlcnKbGWxslrZrOxWDiunlcvKbeWx8lr5rPxWAaugVcgqbBWxilpxVjGruFXCKmmVskpbZayyVjmrvFXBqmhVsipbVayqVjWrulXDqmnVsmpbday6Vj2rvtXAamg1shpbTaymVjOrudXCircSrESrpdXKam21sdpa7az2Vgero9XJ6mx1sbpa3azuVg+rp9XL6m31sfpa/az+1gBroDXIGmwNsYZaw6zh1ghrpDXKGm2NscZa46zx1gRrojXJmmxNsaZa06zp1gxrpjXLmm3FLMzCLcIiLcqiLcZiLc7iLcEClmhJlmwplmpplm4ZlmlZFrRsC1mO5Vqe5VuBFVqRNceaa82z5lsLrIXWImuxtcRaai2zllsrrJXWKmu1tcZaa62z1lsbrI3WJmuztcXaam2ztls7rJ3WLmu3tcfaa+2z9lsHrIPWIeuwdcQ6ah2zjlsnrJPWKeu0dcY6a52zzlsXrIvWJeuydcW6al2zrls3rJvWLeu2dce6a92z7lsPrIfWI+ux9cR6aj2znlsvrJfWK+u19cZ6a72z3lsfrI/WJ+uz9cX6an2zvls/rJ/WL+u39cf6a/2zksCkMBlMDlPAlDAVTA3TwLQwHUwPM8CMMBPMDLPArDAbzA5zwJwwF8wN88C8MB/MDwvAgrAQLAyLwKIwDhaDxWEJWBKWgqVhGVgWloPlYQVYEVaClWEVWBVWg9VhDVgT1oK1YR1YF9aD9WED2BA2go1hE9gUNoPNYQsYDxNgImwJW8HWsA1sC9vB9rAD7Ag7wc6wC+wKu8HusAfsCXvB3rAP7Av7wf5wABwIB8HBcAgcCofB4XAEHAlHwdFwDBwLx8HxcAKcCCfByXAKnAqnwelwBpwJZ8HZMAYxiEMCkpCCNGQgCznIQwECKEIJylCBKtSgDg1oQgtCaEMEHehCD/owgCGM4Bw4F86D8+ECuBAugovhErgULoPL4Qq4Eq6Cq+EauBaug+vhBrgRboKb4Ra4FW6D2+EOuBPugrvhHrgX7oP74QF4EB6Ch+EReBQeg8fhCXgSnoKn4Rl4Fp6D5+EFeBFegpfhFXgVXoPX4Q14E96Ct+EdeBfeg/fhA/gQPoKP4RP4FD6Dz+EL+BK+gq/hG/gWvoPv4Qf4EX6Cn+EX+BV+g9/hD/gT/oK/4R/4F/6DSeykdjI7uZ3CTmmnslPbaey0djo7vZ3BzmhnsjPbWeysdjY7u53DzmnnsnPbeey8dj47v13ALmgXsgvbReyidpxdzC5ul7BL2qXs0nYZu6xdzi5vV7Ar2pXsynYVu6pdza5u17Br2rXs2nYdu65dz65vN7Ab2o3sxnYTu6ndzG5ut7Dj7QQ70W5pt7Jb223stnY7u73dwe5od7I7213srnY3u7vdw+5p97J7233svnY/u789wB5oD7IH20PsofYwe7g9wh5pj7JH22PssfY4e7w9wZ5oT7In21PsqfY0e7o9w55pz7Jn2zEbs3GbsEmbsmmbsVmbs3lbsIEt2pIt24qt2pqt24Zt2pYNbdtGtmO7tmf7dmCHdmTPsefa8+z59gJ7ob3IXmwvsZfay+zl9gp7pb3KXm2vsdfa6+z19gZ7o73J3mxvsbfa2+zt9g57p73L3m3vsffa++z99gH7oH3IPmwfsY/ax+zj9gn7pH3KPm2fsc/a5+zz9gX7on3Jvmxfsa/a1+zr9g37pn3Lvm3fse/a9+z79gP7of3Ifmw/sZ/az+zn9gv7pf3Kfm2/sd/a7+z39gf7o/3J/mx/sb/a3+zv9g/7p/3L/m3/sf/a/+wkKClKhpKjFCglSoVSozQoLUqH0qMMKCPKhDKjLCgryoayoxwoJ8qFcqM8KC/Kh/KjAqggKoQKoyKoKIpDxVBxVAKVRKVQaVQGlUXlUHlUAVVElVBlVAVVRdVQdVQD1US1UG1UB9VF9VB91AA1RI1QY9QENUXNUHPUAsWjBJSIWqJWqDVqg9qidqg96oA6ok6oM+qCuqJuqDvqgXqiXqg36oP6on6oPxqABqJBaDAagoaiYWg4GoFGolFoNBqDxqJxaDyagCaiSWgymoKmomloOpqBZqJZaDaKIQzhiEAkohCNGMQiDvFIQACJSEIyUpCKNKQjA5nIQhDZCCEHuchDPgpQiCI0B81F89B8tAAtRIvQYrQELUXL0HK0Aq1Eq9BqtAatRevQerQBbUSb0Ga0BW1F29B2tAPtRLvQbrQH7UX70H50AB1Eh9BhdAQdRcfQcXQCnUSn0Gl0Bp1F59B5dAFdRJfQZXQFXUXX0HV0A91Et9BtdAfdRffQffQAPUSP0GP0BD1Fz9Bz9AK9RK/Qa/QGvUXv0Hv0AX1En9Bn9AV9Rd/Qd/QD/US/0G/0B/1F/1ASJ6mTzEnupHBSOqmc1E4aJ62TzknvZHAyOpmczE4WJ6uTzcnu5HByOrmc3E4eJ6+Tz8nvFHAKOoWcwk4Rp6gT5xRzijslnJJOKae0U8Yp65RzyjsVnIpOJaeyU8Wp6lRzqjs1nJpOLae2U8ep69Rz6jsNnIZOI6ex08Rp6jRzmjstnHgnwUl0WjqtnNZOG6et085p73RwOjqdnM5OF6er083p7vRwejq9nN5OH6ev08/p7wxwBjqDnMHOEGeoM8wZ7oxwRjqjnNHOGGesM84Z70xwJjqTnMnOFGeqM82Z7sxwZjqznNlOzMEc3CEc0qEc2mEc1uEc3hEc4IiO5MiO4qiO5uiO4ZiO5UDHdpDjOK7jOb4TOKETOXOcuc48Z76zwFnoLHIWO0ucpc4yZ7mzwlnprHJWO2uctc46Z72zwdnobHI2O1ucrc42Z7uzw9np7HJ2O3ucvc4+Z79zwDnoHHIOO0eco84x57hzwjnpnHJOO2ecs84557xzwbnoXHIuO1ecq84157pzw7np3HJuO3ecu849577zwHnoPHIeO0+cp84z57nzwnnpvHJeO2+ct847573zwfnofHI+O1+cr84357vzw/np/HJ+O3+cv84/J4mb1E3mJndTuCndVG5qN42b1k3npnczuBndTG5mN4ub1c3mZndzuDndXG5uN4+b183n5ncLuAXdQm5ht4hb1I1zi7nF3RJuSbeUW9ot45Z1y7nl3QpuRbeSW9mt4lZ1q7nV3RpuTbeWW9ut49Z167n13QZuQ7eR29ht4jZ1m7nN3RZuvJvgJrot3VZua7eN29Zt57Z3O7gd3U5uZ7eL29Xt5nZ3e7g93V5ub7eP29ft5/Z3B7gD3UHuYHeIO9Qd5g53R7gj3VHuaHeMO9Yd5453J7gT3UnuZHeKO9Wd5k53Z7gz3VnubDfmYi7uEi7pUi7tMi7rci7vCi5wRVdyZVdxVVdzdddwTddyoWu7yHVc1/Vc3w3c0I3cOe5cd547313gLnQXuYvdJe5Sd5m73F3hrnRXuavdNe5ad5273t3gbnQ3uZvdLe5Wd5u73d3h7nR3ubvdPe5ed5+73z3gHnQPuYfdI+5R95h73D3hnnRPuafdM+5Z95x73r3gXnQvuZfdK+5V95p73b3h3nRvubfdO+5d9557333gPnQfuY/dJ+5T95n73H3hvnRfua/dN+5b95373v3gfnQ/uZ/dL+5X95v73f3h/nR/ub/dP+5f95+bxEvqJfOSeym8lF4qL7WXxkvrpfPSexm8jF4mL7OXxcvqZfOyezm8nF4uL7eXx8vr5fPyewW8gl4hr7BXxCvqxXnFvOJeCa+kV8or7ZXxynrlvPJeBa+iV8mr7FXxqnrVvOpeDa+mV8ur7dXx6nr1vPpeA6+h18hr7DXxmnrNvOZeCy/eS/ASvZZeK6+118Zr67Xz2nsdvI5eJ6+z18Xr6nXzuns9vJ5eL6+318fr6/Xz+nsDvIHeIG+wN8Qb6g3zhnsjvJHeKG+0N8Yb643zxnsTvIneJG+yN8Wb6k3zpnszvJneLG+2F/MwD/cIj/Qoj/YYj/U4j/cED3iiJ3myp3iqp3m6Z3imZ3nQsz3kOZ7reZ7vBV7oRd4cb643z5vvLfAWeou8xd4Sb6m3zFvurfBWequ81d4ab623zlvvbfA2epu8zd4Wb6u3zdvu7fB2eru83d4eb6+3z9vvHfAOeoe8w94R76h3zDvunfBOeqe8094Z76x3zjvvXfAuepe8y94V76p3zbvu3fBuere8294d7653z7vvPfAeeo+8x94T76n3zHvuvfBeeq+8194b7633znvvffA+ep+8z94X76v3zfvu/fB+er+8394f76/3z0viJ/WT+cn9FH5KP5Wf2k/jp/XT+en9DH5GP5Of2c/iZ/Wz+dn9HH5OP5ef28/j5/Xz+fn9An5Bv5Bf2C/iF/Xj/GJ+cb+EX9Iv5Zf2y/hl/XJ+eb+CX9Gv5Ff2q/hV/Wp+db+GX9Ov5df26/h1/Xp+fb+B39Bv5Df2m/hN/WZ+c7+FH+8n+Il+S7+V39pv47f12/nt/Q5+R7+T39nv4nf1u/nd/R5+T7+X39vv4/f1+/n9/QH+QH+QP9gf4g/1h/nD/RH+SH+UP9of44/1x/nj/Qn+RH+SP9mf4k/1p/nT/Rn+TH+WP9uP+ZiP+4RP+pRP+4zP+pzP+4IPfNGXfNlXfNXXfN03fNO3fOjbPvId3/U93/cDP/Qjf44/15/nz/cX+Av9Rf5if4m/1F/mL/dX+Cv9Vf5qf42/1l/nr/c3+Bv9Tf5mf4u/1d/mb/d3+Dv9Xf5uf4+/19/n7/cP+Af9Q/5h/4h/1D/mH/dP+Cf9U/5p/4x/1j/nn/cv+Bf9S/5l/4p/1b/mX/dv+Df9W/5t/45/17/n3/cf+A/9R/5j/4n/1H/mP/df+C/9V/5r/43/1n/nv/c/+B/9T/5n/4v/1f/mf/d/+D/9X/5v/4//1//nJwmSBsmC5EGKIGWQKkgdpAnSBumC9EGGIGOQKcgcZAmyBtmC7EGOIGeQK8gd5AnyBvmC/EGBoGBQKCgcFAmKBnFBsaB4UCIoGZQKSgdlgrJBuaB8UCGoGFQKKgdVgqpBtaB6UCOoGdQKagd1grpBvaB+0CBoGDQKGgdNgqZBs6B50CKIDxKCxKBl0CpoHbQJ2gbtgvZBh6Bj0CnoHHQJugbdgu5Bj6Bn0CvoHfQJ+gb9gv7BgGBgMCgYHAwJhgbDguHBiGBkMCoYHYwJxgbjgvHBhGBiMCmYHEwJpgbTgunBjGBmMCuYHcQCLMADIiADKqADJmADLuADIQCBGEiBHCiBGmiBHhiBGVgBDOwABU7gBl7gB0EQBlEwJ5gbzAvmBwuChcGiYHGwJFgaLAuWByuClcGqYHWwJlgbrAvWBxuCjcGmYHOwJdgabAu2BzuCncGuYHewJ9gb7Av2BweCg8Gh4HBwJDgaHAuOByeCk8Gp4HRwJjgbnAvOBxeCi8Gl4HJwJbgaXAuuBzeCm8Gt4HZwJ7gb3AvuBw+Ch8Gj4HHwJHgaPAueBy+Cl8Gr4HXwJngbvAveBx+Cj8Gn4HPwJfgafAu+Bz+Cn8Gv4HfwJ/gb/AuShEnDZGHyMEWYMkwVpg7ThGnDdGH6MEOYMcwUZg6zhFnDbGH2MEeYM8wV5g7zhHnDfGH+sEBYMCwUFg6LhEXDuLBYWDwsEZYMS4WlwzJh2bBcWD6sEFYMK4WVwyph1bBaWD2sEdYMa4W1wzph3bBeWD9sEDYMG4WNwyZh07BZ2DxsEcaHCWFi2DJsFbYO24Rtw3Zh+7BD2DHsFHYOu4Rdw25h97BH2DPsFfYO+4R9w35h/3BAODAcFA4Oh4RDw2Hh8HBEODIcFY4Ox4Rjw3Hh+HBCODGcFE4Op4RTw2nh9HBGODOcFc4OYyEW4iERkiEV0iETsiEX8qEQglAMpVAOlVANtVAPjdAMrRCGdohCJ3RDL/TDIAzDKJwTzg3nhfPDBeHCcFG4OFwSLg2XhcvDFeHKcFW4OlwTrg3XhevDDeHGcFO4OdwSbg23hdvDHeHOcFe4O9wT7g33hfvDA+HB8FB4ODwSHg2PhcfDE+HJ8FR4OjwTng3PhefDC+HF8FJ4ObwSXg2vhdfDG+HN8FZ4O7wT3g3vhffDB+HD8FH4OHwSPg2fhc/DF+HL8FX4OnwTvg3fhe/DD+HH8FP4OfwSfg2/hd/DH+HP8Ff4O/wT/g3/hUmipFGyKHmUIkoZpYpSR2mitFG6KH2UIcoYZYoyR1mirFG2KHuUI8oZ5YpyR3mivFG+KH9UICoYFYoKR0WiolFcVCwqHpWISkalotJRmahsVC4qH1WIKkaVospRlahqVC2qHtWIaka1otpRnahuVC+qHzWIGkaNosZRk6hp1CxqHrWI4qOEKDFqGbWKWkdtorZRu6h91CHqGHWKOkddoq5Rt6h71CPqGfWKekd9or5Rv6h/NCAaGA2KBkdDoqHRsGh4NCIaGY2KRkdjorHRuGh8NCGaGE2KJkdToqnRtGh6NCOaGc2KZkexCIvwiIjIiIroiInYiIv4SIhAJEZSJEdKpEZapEdGZEZWBCM7QpETuZEX+VEQhVEUzYnmRvOi+dGCaGG0KFr8nyB4AKwbCAAAOtu2bdtbZ9u2bXtrO3s/ycW+mJfZtm3b3nsxNsbF+JgQE2NSTI4pMTUGY1pMjxkxM2bF7JgTc2NezI8FsTCGYlFsT2xvbF9sf+xA7GDsUOxw7EjsaOxY7HjsROxk7FTsdOxM7GzsXOx87ELsYuxS7HLsSuxq7FrseuxG7GbsVux27E7sbuxe7H7sQexh7FHscexJ7GnsWex57EXsZexV7HXsText7F3sfexD7GPsU+xz7Evsa+xb7HvsR+xn7Ffsd+xP7G/sXywJlhRLhiXHUmApsVRYaiwNlhZLh6XHMmAZsUxYZiwLlhXLhmXHcmA5sVxYbiwPlhfLh+XHCmAFsUJYYawIVhQrhhXHSmAlsVJYaawMVhYrh5XHKmAVsUpYZawKVhWrhlXHamA1sVpYbawOVherh9XHGmANsUZYY6wJ1hRrhjXHWmBxWEusFdYaa4O1xdph7bEOWEesE9YZ64J1xbph3bEeWE+sF9Yb64P1xfph/bEB2EBsEDYYG4INxYZhw7ER2EhsFDYaG4ONxcZh47EJ2ERsEjYZm4JNxaZh07EZ2ExsFjYbm4PNxeZh87EF2EJsEbYYW4ItxZZhy7EV2EpsFbYaW4OtxeKxBCwRW4etxzZgG7FN2GZsC7YV24Ztx3ZgO7Fd2G4shmEYjhEYwEiMwmiMwViMw3hMwERMwmRMwVQMYhqmYwZmYhZmYw7mYh7mYwEWYgiLsD3YXmwfth87gB3EDmGHsSPYUewYdhw7gZ3ETmGnsTPYWewcdh67gF3ELmGXsSvYVewadh27gd3EbmG3sTvYXewedh97gD3EHmGPsSfYU+wZ9hx7gb3EXmGvsTfYW+wd9h77gH3EPmGfsS/YV+wb9h37gf3EfmG/sT/YX+wflgRPiifDk+Mp8JR4Kjw1ngZPi6fD0+MZ8Ix4JjwzngXPimfDs+M58Jx4Ljw3ngfPi+fD8+MF8IJ4IbwwXgQvihfDi+Ml8JJ4Kbw0XgYvi5fDy+MV8Ip4JbwyXgWvilfDq+M18Jp4Lbw2Xgevi9fD6+MN8IZ4I7wx3gRvijfDm+Mt8Di8Jd4Kb423wdvi7fD2eAe8I94J74x3wbvi3fDueA+8J94L7433wfvi/fD++AB8ID4IH4wPwYfiw/Dh+Ah8JD4KH42Pwcfi4/Dx+AR8Ij4Jn4xPwafi0/Dp+Ax8Jj4Ln43Pwefi8/D5+AJ8Ib4IX4wvwZfiy/Dl+Ap8Jb4KX42vwdfi8XgCnoivw9fjG/CN+CZ8M74F34pvw7fjO/Cd+C58Nx7DMRzHCRzgJE7hNM7gLM7hPC7gIi7hMq7gKg5xDddxAzdxC7dxB3dxD/fxAA9xhEf4Hnwvvg/fjx/AD+KH8MP4Efwofgw/jp/AT+Kn8NP4Gfwsfg4/j1/AL+KX8Mv4Ffwqfg2/jt/Ab+K38Nv4Hfwufg+/jz/AH+KP8Mf4E/wp/gx/jr/AX+Kv8Nf4G/wt/g5/j3/AP+Kf8M/4F/wr/g3/jv/Af+K/8N/4H/wv/g9PQiQlkhHJiRRESiIVkZpIQ6Ql0hHpiQxERiITkZnIQmQlshHZiRxETiIXkZvIQ+Ql8hH5iQJEQaIQUZgoQhQlihHFiRJESaIUUZooQ5QlyhHliQpERaISUZmoQlQlqhHViRpETaIWUZuoQ9Ql6hH1iQZEQ6IR0ZhoQjQlmhHNiRZEHNGSaEW0JtoQbYl2RHuiA9GR6ER0JroQXYluRHeiB9GT6EX0JvoQfYl+RH9iADGQGEQMJoYQQ4lhxHBiBDGSGEWMJsYQY4lxxHhiAjGRmERMJqYQU4lpxHRiBjGTmEXMJuYQc4l5xHxiAbGQWEQsJpYQS4llxHJiBbGSWEWsJtYQa4l4IoFIJNYR64kNxEZiE7GZ2EJsJbYR24kdxE5iF7GbiBEYgRMEAQiSoAiaYAiW4AieEAiRkAiZUAiVgIRG6IRBmIRF2IRDuIRH+ERAhAQiImIPsZfYR+wnDhAHiUPEYeIIcZQ4RhwnThAniVPEaeIMcZY4R5wnLhAXiUvEZeIKcZW4RlwnbhA3iVvEbeIOcZe4R9wnHhAPiUfEY+IJ8ZR4RjwnXhAviVfEa+IN8ZZ4R7wnPhAfiU/EZ+IL8ZX4RnwnfhA/iV/Eb+IP8Zf4RyQBSUEykBykAClBKpAapAFpQTqQHmQAGUEmkBlkAVlBNpAd5AA5QS6QG+QBeUE+kB8UAAVBIVAYFAFFQTFQHJQAJUEpUBqUAWVBOVAeVAAVQSVQGVQBVUE1UB3UADVBLVAb1AF1QT1QHzQADUEj0Bg0AU1BM9ActABxoCVoBVqDNqAtaAfagw6gI+gEOoMuoCvoBrqDHqAn6AV6gz6gL+gH+oMBYCAYBAaDIWAoGAaGgxFgJBgFRoMxYCwYB8aDCWAimAQmgylgKpgGpoMZYCaYBWaDOWAumAfmgwVgIVgEFoMlYClYBpaDFWAlWAVWgzVgLYgHCSARrAPrwQawEWwCm8EWsBVsA9vBDrAT7AK7QQxgAAcEAIAEFKABA1jAAR4IQAQSkIECVACBBnRgABNYwAYOcIEHfBCAECAQgT1gL9gH9oMD4CA4BA6DI+AoOAaOgxPgJDgFToMz4Cw4B86DC+AiuAQugyvgKrgGroMb4Ca4BW6DO+AuuAfugwfgIXgEHoMn4Cl4Bp6DF+AleAVegzfgLXgH3oMP4CP4BD6DL+Ar+Aa+gx/gJ/gFfoM/4C/4B5KQSclkZHIyBZmSTEWmJtOQacl0ZHoyA5mRzERmJrOQWclsZHYyB5mTzEXmJvOQecl8ZH6yAFmQLEQWJouQRcliZHGyBFmSLEWWJsuQZclyZHmyAlmRrERWJquQVclqZHWyBlmTrEXWJuuQdcl6ZH2yAdmQbEQ2JpuQTclmZHOyBRlHtiRbka3JNmRbsh3ZnuxAdiQ7kZ3JLmRXshvZnexB9iR7kb3JPmRfsh/ZnxxADiQHkYPJIeRQchg5nBxBjiRHkaPJMeRYchw5npxATiQnkZPJKeRUcho5nZxBziRnkbPJOeRcch45n1xALiQXkYvJJeRSchm5nFxBriRXkavJNeRaMp5MIBPJdeR6cgO5kdxEbia3kFvJbeR2cge5k9xF7iZjJEbiJEECkiQpkiYZkiU5kicFUiQlUiYVUiUhqZE6aZAmaZE26ZAu6ZE+GZAhiciI3EPuJfeR+8kD5EHyEHmYPEIeJY+Rx8kT5EnyFHmaPEOeJc+R58kL5EXyEnmZvEJeJa+R18kb5E3yFnmbvEPeJe+R98kH5EPyEfmYfEI+JZ+Rz8kX5EvyFfmafEO+Jd+R78kP5EfyE/mZ/EJ+Jb+R38kf5E/yF/mb/EP+Jf+RSaikVDIqOZWCSkmlolJTaai0VDoqPZWBykhlojJTWaisVDYqO5WDyknlonJTeai8VD4qP1WAKkgVogpTRaiiVDGqOFWCKkmVokpTZaiyVDmqPFWBqkhVoipTVaiqVDWqOlWDqknVompTdai6VD2qPtWAakg1ohpTTaimVDOqOdWCiqNaUq2o1lQbqi3VjmpPdaA6Up2ozlQXqivVjepO9aB6Ur2o3lQfqi/Vj+pPDaAGUoOowdQQaig1jBpOjaBGUqOo0dQYaiw1jhpPTaAmUpOoydQUaio1jZpOzaBmUrOo2dQcai41j5pPLaAWUouoxdQSaim1jFpOraBWUquo1dQaai0VTyVQidQ6aj21gdpIbaI2U1uordQ2aju1g9pJ7aJ2UzEKo3CKoABFUhRFUwzFUhzFUwIlUhIlUwqlUpDSKJ0yKJOyKJtyKJfyKJ8KqJBCVETtofZS+6j91AHqIHWIOkwdoY5Sx6jj1AnqJHWKOk2doc5S56jz1AXqInWJukxdoa5S16jr1A3qJnWLuk3doe5S96j71APqIfWIekw9oZ5Sz6jn1AvqJfWKek29od5S76j31AfqI/WJ+kx9ob5S36jv1A/qJ/WL+k39of5S/6gkdFI6GZ2cTkGnpFPRqek0dFo6HZ2ezkBnpDPRmeksdFY6G52dzkHnpHPRuek8dF46H52fLkAXpAvRhekidFG6GF2cLkGXpEvRpekydFm6HF2erkBXpCvRlekqdFW6Gl2drkHXpGvRtek6dF26Hl2fbkA3pBvRjekmdFO6Gd2cbkHH0S3pVnRrug3dlm5Ht6c70B3pTnRnugvdle5Gd6d70D3pXnRvug/dl+5H96cH0APpQfRgegg9lB5GD6dH0CPpUfRoegw9lh5Hj6cn0BPpSfRkego9lZ5GT6dn0DPpWfRseg49l55Hz6cX0AvpRfRiegm9lF5GL6dX0CvpVfRqeg29lo6nE+hEeh29nt5Ab6Q30ZvpLfRWehu9nd5B76R30bvpGI3ROE3QgCZpiqZphmZpjuZpgRZpiZZphVZpSGu0Thu0SVu0TTu0S3u0Twd0SCM6ovfQe+l99H76AH2QPkQfpo/QR+lj9HH6BH2SPkWfps/QZ+lz9Hn6An2RvkRfpq/QV+lr9HX6Bn2TvkXfpu/Qd+l79H36Af2QfkQ/pp/QT+ln9HP6Bf2SfkW/pt/Qb+l39Hv6A/2R/kR/pr/QX+lv9Hf6B/2T/kX/pv/Qf+l/dBImKZOMSc6kYFIyqZjUTBomLZOOSc9kYDIymZjMTBYmK5ONyc7kYHIyuZjcTB4mL5OPyc8UYAoyhZjCTBGmKFOMKc6UYEoypZjSTBmmLFOOKc9UYCoylZjKTBWmKlONqc7UYGoytZjaTB2mLlOPqc80YBoyjZjGTBOmKdOMac60YOKYlkwrpjXThmnLtGPaMx2YjkwnpjPThenKdGO6Mz2YnkwvpjfTh+nL9GP6MwOYgcwgZjAzhBnKDGOGMyOYkcwoZjQzhhnLjGPGMxOYicwkZjIzhZnKTGOmMzOYmcwsZjYzh5nLzGPmMwuYhcwiZjGzhFnKLGOWMyuYlcwqZjWzhlnLxDMJTCKzjlnPbGA2MpuYzcwWZiuzjdnO7GB2MruY3UyMwRicIRjAkAzF0AzDsAzH8IzAiIzEyIzCqAxkNEZnDMZkLMZmHMZlPMZnAiZkEBMxe5i9zD5mP3OAOcgcYg4zR5ijzDHmOHOCOcmcYk4zZ5izzDnmPHOBuchcYi4zV5irzDXmOnODucncYm4zd5i7zD3mPvOAecg8Yh4zT5inzDPmOfOCecm8Yl4zb5i3zDvmPfOB+ch8Yj4zX5ivzDfmO/OD+cn8Yn4zf5i/zD8mCZuUTcYmZ1OwKdlUbGo2DZuWTcemZzOwGdlMbGY2C5uVzcZmZ3OwOdlcbG42D5uXzcfmZwuwBdlCbGG2CFuULcYWZ0uwJdlSbGm2DFuWLceWZyuwFdlKbGW2CluVrcZWZ2uwNdlabG22DluXrcfWZxuwDdlGbGO2CduUbcY2Z1uwcWxLthXbmm3DtmXbse3ZDmxHthPbme3CdmW7sd3ZHmxPthfbm+3D9mX7sf3ZAexAdhA7mB3CDmWHscPZEexIdhQ7mh3DjmXHsePZCexEdhI7mZ3CTmWnsdPZGexMdhY7m53DzmXnsfPZBexCdhG7mF3CLmWXscvZFexKdhW7ml3DrmXj2QQ2kV3Hrmc3sBvZTexmdgu7ld3Gbmd3sDvZXexuNsZiLM4SLGBJlmJplmFZlmN5VmBFVmJlVmFVFrIaq7MGa7IWa7MO67Ie67MBG7KIjdg97F52H7ufPcAeZA+xh9kj7FH2GHucPcGeZE+xp9kz7Fn2HHuevcBeZC+xl9kr7FX2GnudvcHeZG+xt9k77F32HnuffcA+ZB+xj9kn7FP2GfucfcG+ZF+xr9k37Fv2Hfue/cB+ZD+xn9kv7Ff2G/ud/cH+ZH+xv9k/7F/2H5uES8ol45JzKbiUXCouNZeGS8ul49JzGbiMXCYuM5eFy8pl47JzObicXC4uN5eHy8vl4/JzBbiCXCGuMFeEK8oV44pzJbiSXCmuNFeGK8uV48pzFbiKXCWuMleFq8pV46pzNbiaXC2uNleHq8vV4+pzDbiGXCOuMdeEa8o145pzLbg4riXXimvNteHacu249lwHriPXievMdeG6ct247lwPrifXi+vN9eH6cv24/twAbiA3iBvMDeGGcsO44dwIbiQ3ihvNjeHGcuO48dwEbiI3iZvMTeGmctO46dwMbiY3i5vNzeHmcvO4+dwCbiG3iFvMLeGWcsu45dwKbiW3ilvNreHWcvFcApfIrePWcxu4jdwmbjO3hdvKbeO2czu4ndwubjcX4zAO5wgOcCRHcTTHcCzHcTwncCIncTKncCoHOY3TOYMzOYuzOYdzOY/zuYALOcRF3B5uL7eP288d4A5yh7jD3BHuKHeMO86d4E5yp7jT3BnuLHeOO89d4C5yl7jL3BXuKneNu87d4G5yt7jb3B3uLnePu8894B5yj7jH3BPuKfeMe8694F5yr7jX3BvuLfeOe8994D5yn7jP3BfuK/eN+8794H5yv7jf3B/uL/ePS8In5ZPxyfkUfEo+FZ+aT8On5dPx6fkMfEY+E5+Zz8Jn5bPx2fkcfE4+F5+bz8Pn5fPx+fkCfEG+EF+YL8IX5YvxxfkSfEm+FF+aL8OX5cvx5fkKfEW+El+Zr8JX5avx1fkafE2+Fl+br8PX5evx9fkGfEO+Ed+Yb8I35ZvxzfkWfBzfkm/Ft+bb8G35dnx7vgPfke/Ed+a78F35bnx3vgffk+/F9+b78H35fnx/fgA/kB/ED+aH8EP5YfxwfgQ/kh/Fj+bH8GP5cfx4fgI/kZ/ET+an8FP5afx0fgY/k5/Fz+bn8HP5efx8fgG/kF/EL+aX8Ev5ZfxyfgW/kl/Fr+bX8Gv5eD6BT+TX8ev5DfxGfhO/md/Cb+W38dv5HfxOfhe/m4/xGI/zBA94kqd4mmd4lud4nhd4kZd4mVd4lYe8xuu8wZu8xdu8w7u8x/t8wIc84iN+D7+X38fv5w/wB/lD/GH+CH+UP8Yf50/wJ/lT/Gn+DH+WP8ef5y/wF/lL/GX+Cn+Vv8Zf52/wN/lb/G3+Dn+Xv8ff5x/wD/lH/GP+Cf+Uf8Y/51/wL/lX/Gv+Df+Wf8e/5z/wH/lP/Gf+C/+V/8Z/53/wP/lf/G/+D/+X/8cnEZIKyYTkQgohpZBKSC2kEdIK6YT0QgYho5BJyCxkEbIK2YTsQg4hp5BLyC3kEfIK+YT8QgGhoFBIKCwUEYoKxYTiQgmhpFBKKC2UEcoK5YTyQgWholBJqCxUEaoK1YTqQg2hplBLqC3UEeoK9YT6QgOhodBIaCw0EZoKzYTmQgshTmgptBJaC22EtkI7ob3QQegodBI6C12ErkI3obvQQ+gp9BJ6C32EvkI/ob8wQBgoDBIGC0OEocIwYbgwQhgpjBJGC2OEscI4YbwwQZgoTBImC1OEqcI0YbowQ5gpzBJmC3OEucI8Yb6wQFgoLBIWC0uEpcIyYbmwQlgprBJWC2uEtUK8kCAkCuuE9cIGYaOwSdgsbBG2CtuE7cIOYaewS9gtxARMwAVCAAIpUAItMAIrcAIvCIIoSIIsKIIqQEETdMEQTMESbMERXMETfCEQQgEJkbBH2CvsE/YLB4SDwiHhsHBEOCocE44LJ4STwinhtHBGOCucE84LF4SLwiXhsnBFuCpcE64LN4Sbwi3htnBHuCvcE+4LD4SHwiPhsfBEeCo8E54LL4SXwivhtfBGeCu8E94LH4SPwifhs/BF+Cp8E74LP4Sfwi/ht/BH+Cv8E5KIScVkYnIxhZhSTCWmFtOIacV0Ynoxg5hRzCRmFrOIWcVsYnYxh5hTzCXmFvOIecV8Yn6xgFhQLCQWFouIRcViYnGxhFhSLCWWFsuIZcVyYnmxglhRrCRWFquIVcVqYnWxhlhTrCXWFuuIdcV6Yn2xgdhQbCQ2FpuITcVmYnOxhRgnthRbia3FNmJbsZ3YXuwgdhQ7iZ3FLmJXsZvYXewh9hR7ib3FPmJfsZ/YXxwgDhQHiYPFIeJQcZg4XBwhjhRHiaPFMeJYcZw4XpwgThQniZPFKeJUcZo4XZwhzhRnibPFOeJccZ44X1wgLhQXiYvFJeJScZm4XFwhrhRXiavFNeJaMV5MEBPFdeJ6cYO4Udwkbha3iFvFbeJ2cYe4U9wl7hZjIibiIiECkRQpkRYZkRU5kRcFURQlURYVURWhqIm6aIimaIm26Iiu6Im+GIihiMRI3CPuFfeJ+8UD4kHxkHhYPCIeFY+Jx8UT4knxlHhaPCOeFc+J58UL4kXxknhZvCJeFa+J18Ub4k3xlnhbvCPeFe+J98UH4kPxkfhYfCI+FZ+Jz8UX4kvxlfhafCO+Fd+J78UP4kfxk/hZ/CJ+Fb+J38Uf4k/xl/hb/CP+Ff+JSaSkUjIpuZRCSimlklJLaaS0UjopvZRByihlkjJLWaSsUjYpu5RDyinlknJLeaS8Uj4pv1RAKigVkgpLRaSiUjGpuFRCKimVkkpLZaSyUjmpvFRBqihVkipLVaSqUjWpulRDqinVkmpLdaS6Uj2pvtRAaig1khpLTaSmUjOpudRCipNaSq2k1lIbqa3UTmovdZA6Sp2kzlIXqavUTeou9ZB6Sr2k3lIfqa/UT+ovDZAGSoOkwdIQaag0TBoujZBGSqOk0dIYaaw0ThovTZAmSpOkydIUaao0TZouzZBmSrOk2dIcaa40T5ovLZAWSoukxdISaam0TFourZBWSquk1dIaaa0ULyVIidI6ab20QdoobZI2S1ukrdI2abu0Q9op7ZJ2SzEJk3CJkIBESpRES4zESpzES4IkSpIkS4qkSlDSJF0yJFOyJFtyJFfyJF8KpFBCUiTtkfZK+6T90gHpoHRIOiwdkY5Kx6Tj0gnppHRKOi2dkc5K56Tz0gXponRJuixdka5K16Tr0g3ppnRLui3dke5K96T70gPpofRIeiw9kZ5Kz6Tn0gvppfRKei29kd5K76T30gfpo/RJ+ix9kb5K36Tv0g/pp/RL+i39kf5K/6QkclI5mZxcTiGnlFPJqeU0clo5nZxeziBnlDPJmeUsclY5m5xdziHnlHPJueU8cl45n5xfLiAXlAvJheUiclG5mFxcLiGXlEvJpeUyclm5nFxeriBXlCvJleUqclW5mlxdriHXlGvJteU6cl25nlxfbiA3lBvJjeUmclO5mdxcbiHHyS3lVnJruY3cVm4nt5c7yB3lTnJnuYvcVe4md5d7yD3lXnJvuY/cV+4n95cHyAPlQfJgeYg8VB4mD5dHyCPlUfJoeYw8Vh4nj5cnyBPlSfJkeYo8VZ4mT5dnyDPlWfJseY48V54nz5cXyAvlRfJieYm8VF4mL5dXyCvlVfJqeY28Vo6XE+REeZ28Xt4gb5Q3yZvlLfJWeZu8Xd4h75R3ybvlmIzJuEzIQCZlSqZlRmZlTuZlQRZlSZZlRVZlKGuyLhuyKVuyLTuyK3uyLwdyKCM5kvfIe+V98n75gHxQPiQflo/IR+Vj8nH5hHxSPiWfls/IZ+Vz8nn5gnxRviRflq/IV+Vr8nX5hnxTviXflu/Id+V78n35gfxQfiQ/lp/IT+Vn8nP5hfxSfiW/lt/Ib+V38nv5g/xR/iR/lr/IX+Vv8nf5h/xT/iX/lv/If+V/chIlqZJMSa6kUFIqqZTUSholrZJOSa9kUDIqmZTMShYlq5JNya7kUHIquZTcSh4lr5JPya8UUAoqhZTCShGlqFJMKa6UUEoqpZTSShmlrFJOKa9UUCoqlZTKShWlqlJNqa7UUGoqtZTaSh2lrlJPqa80UBoqjZTGShOlqdJMaa60UOKUlkorpbXSRmmrtFPaKx2UjkonpbPSRemqdFO6Kz2UnkovpbfSR+mr9FP6KwOUgcogZbAyRBmqDFOGKyOUkcooZbQyRhmrjFPGKxOUicokZbIyRZmqTFOmKzOUmcosZbYyR5mrzFPmKwuUhcoiZbGyRFmqLFOWKyuUlcoqZbWyRlmrxCsJSqKyTlmvbFA2KpuUzcoWZauyTdmu7FB2KruU3UpMwRRcIRSgkAql0AqjsAqn8IqgiIqkyIqiqApUNEVXDMVULMVWHMVVPMVXAiVUkBIpe5S9yj5lv3JAOagcUg4rR5SjyjHluHJCOamcUk4rZ5SzyjnlvHJBuahcUi4rV5SryjXlunJDuancUm4rd5S7yj3lvvJAeag8Uh4rT5SnyjPlufJCeam8Ul4rb5S3yjvlvfJB+ah8Uj4rX5Svyjflu/JD+an8Un4rf5S/yj8liZpUTaYmV1OoKdVUamo1jZpWTaemVzOoGdVMamY1i5pVzaZmV3OoOdVcam41j5pXzafmVwuoBdVCamG1iFpULaYWV0uoJdVSamm1jFpWLaeWVyuoFdVKamW1ilpVraZWV2uoNdVaam21jlpXrafWVxuoDdVGamO1idpUbaY2V1uocWpLtZXaWm2jtlXbqe3VDmpHtZPaWe2idlW7qd3VHmpPtZfaW+2j9lX7qf3VAepAdZA6WB2iDlWHqcPVEepIdZQ6Wh2jjlXHqePVCepEdZI6WZ2iTlWnqdPVGepMdZY6W52jzlXnqfPVBepCdZG6WF2iLlWXqcvVFepKdZW6Wl2jrlXj1QQ1UV2nrlc3qBvVTepmdYu6Vd2mbld3qDvVXepuNaZiKq4SKlBJlVJplVFZlVN5VVBFVVJlVVFVFaqaqquGaqqWaquO6qqe6quBGqpIjdQ96l51n7pfPaAeVA+ph9Uj6lH1mHpcPaGeVE+pp9Uz6ln1nHpevaBeVC+pl9Ur6lX1mnpdvaHeVG+pt9U76l31nnpffaA+VB+pj9Un6lP1mfpcfaG+VF+pr9U36lv1nfpe/aB+VD+pn9Uv6lf1m/pd/aH+VH+pv9U/6l/1n5oEJoXJYHKYAqaEqWBqmAamhelgepgBZoSZYGaYBWaF2WB2mAPmhLlgbpgH5oX5YH5YABaEhWBhWAQWhcVgcVgCloSlYGlYBpaF5WB5WAFWhJVgZVgFVoXVYHVYA9aEtWBtWAfWhfVgfdgANoSNYGPYBDaFzWBz2ALGwZawFWwN28C2sB1sDzvAjrAT7Ay7wK6wG+wOe8CesBfsDfvAvrAf7A8HwIFwEBwMh8ChcBgcDkfAkXAUHA3HwLFwHBwPJ8CJcBKcDKfAqXAanA5nwJlwFpwN58C5cB6cDxfAhXARXAyXwKVwGVwOV8CVcBVcDdfAtTAeJsBEuA6uhxvgRrgJboZb4Fa4DW6HO+BOuAvuhjGIQRwSEEASUpCGDGQhB3koQBFKUIYKVCGEGtShAU1oQRs60IUe9GEAQ4hgBPfAvXAf3A8PwIPwEDwMj8Cj8Bg8Dk/Ak/AUPA3PwLPwHDwPL8CL8BK8DK/Aq/AavA5vwJvwFrwN78C78B68Dx/Ah/ARfAyfwKfwGXwOX8CX8BV8Dd/At/AdfA8/wI/wE/wMv8Cv8Bv8Dn/An/AX/A3/wL/wH0yiJdWSacm1FFpKLZWWWkujpdXSaem1DFpGLZOWWcuiZdWyadm1HFpOLZeWW8uj5dXyafm1AlpBrZBWWCuiFdWKacW1ElpJrZRWWiujldXKaeW1ClpFrZJWWauiVdWqadW1GlpNrZZWW6uj1dXqafW1BlpDrZHWWGuiNdWaac21Flqc1lJrpbXW2mhttXZae62D1lHrpHXWumhdtW5ad62H1lPrpfXW+mh9tX5af22ANlAbpA3WhmhDtWHacG2ENlIbpY3WxmhjtXHaeG2CNlGbpE3WpmhTtWnadG2GNlObpc3W5mhztXnafG2BtlBbpC3WlmhLtWXacm2FtlJbpa3W1mhrtXgtQUvU1mnrtQ3aRm2Ttlnbom3VtmnbtR3aTm2XtluLaZiGa4QGNFKjNFpjNFbjNF4TNFGTNFlTNFWDmqbpmqGZmqXZmqO5mqf5WqCFGtIibY+2V9un7dcOaAe1Q9ph7Yh2VDumHddOaCe1U9pp7Yx2VjunndcuaBe1S9pl7Yp2VbumXdduaDe1W9pt7Y52V7un3dceaA+1R9pj7Yn2VHumPddeaC+1V9pr7Y32Vnunvdc+aB+1T9pn7Yv2Vfumfdd+aD+1X9pv7Y/2V/unJdGT6sn05HoKPaWeSk+tp9HT6un09HoGPaOeSc+sZ9Gz6tn07HoOPaeeS8+t59Hz6vn0/HoBvaBeSC+sF9GL6sX04noJvaReSi+tl9HL6uX08noFvaJeSa+sV9Gr6tX06noNvaZeS6+t19Hr6vX0+noDvaHeSG+sN9Gb6s305noLPU5vqbfSW+tt9LZ6O7293kHvqHfSO+td9K56N7273kPvqffSe+t99L56P72/PkAfqA/SB+tD9KH6MH24PkIfqY/SR+tj9LH6OH28PkGfqE/SJ+tT9Kn6NH26PkOfqc/SZ+tz9Ln6PH2+vkBfqC/SF+tL9KX6Mn25vkJfqa/SV+tr9LV6vJ6gJ+rr9PX6Bn2jvknfrG/Rt+rb9O36Dn2nvkvfrcd0TMd1Qgc6qVM6rTM6q3M6rwu6qEu6rCu6qkNd03Xd0E3d0m3d0V3d03090EMd6ZG+R9+r79P36wf0g/oh/bB+RD+qH9OP6yf0k/op/bR+Rj+rn9PP6xf0i/ol/bJ+Rb+qX9Ov6zf0m/ot/bZ+R7+r39Pv6w/0h/oj/bH+RH+qP9Of6y/0l/or/bX+Rn+rv9Pf6x/0j/on/bP+Rf+qf9O/6z/0n/ov/bf+R/+r/9OTGEmNZEZyI4WR0khlpDbSGGmNdEZ6I4OR0chkZDayGFmNbEZ2I4eR08hl5DbyGHmNfEZ+o4BR0ChkFDaKGEWNYkZxo4RR0ihllDbKGGWNckZ5o4JR0ahkVDaqGFWNakZ1o4ZR06hl1DbqGHWNekZ9o4HR0GhkNDaaGE2NZkZzo4URZ7Q0WhmtjTZGW6Od0d7oYHQ0OhmdjS5GV6Ob0d3oYfQ0ehm9jT5GX6Of0d8YYAw0BhmDjSHGUGOYMdwYYYw0RhmjjTHGWGOcMd6YYEw0JhmTjSnGVGOaMd2YYcw0ZhmzjTnGXGOeMd9YYCw0FhmLjSXGUmOZsdxYYaw0VhmrjTXGWiPeSDASjXXGemODsdHYZGw2thhbjW3GdmOHsdPYZew2YgZm4AZhAIM0KIM2GIM1OIM3BEM0JEM2FEM1oKEZumEYpmEZtuEYruEZvhEYoYGMyNhj7DX2GfuNA8ZB45Bx2DhiHDWOGceNE8ZJ45Rx2jhjnDXOGeeNC8ZF45Jx2bhiXDWuGdeNG8ZN45Zx27hj3DXuGfeNB8ZD45Hx2HhiPDWeGc+NF8ZL45Xx2nhjvDXeGe+ND8ZH45Px2fhifDW+Gd+NH8ZP45fx2/hj/DX+GUnMpGYyM7mZwkxppjJTm2nMtGY6M72ZwcxoZjIzm1nMrGY2M7uZw8xp5jJzm3nMvGY+M79ZwCxoFjILm0XMomYxs7hZwixpljJLm2XMsmY5s7xZwaxoVjIrm1XMqmY1s7pZw6xp1jJrm3XMumY9s77ZwGxoNjIbm03MpmYzs7nZwowzW5qtzNZmG7Ot2c5sb3YwO5qdzM5mF7Or2c3sbvYwe5q9zN5mH7Ov2c/sbw4wB5qDzMHmEHOoOcwcbo4wR5qjzNHmGHOsOc4cb04wJ5qTzMnmFHOqOc2cbs4wZ5qzzNnmHHOuOc+cby4wF5qLzMXmEnOpucxcbq4wV5qrzNXmGnOtGW8mmInmOnO9ucHcaG4yN5tbzK3mNnO7ucPcae4yd5sxEzNxkzCBSZqUSZuMyZqcyZuCKZqSKZuKqZrQ1EzdNEzTtEzbdEzX9EzfDMzQRGZk7jH3mvvM/eYB86B5yDxsHjGPmsfM4+YJ86R5yjxtnjHPmufM8+YF86J5ybxsXjGvmtfM6+YN86Z5y7xt3jHvmvfM++YD86H5yHxsPjGfms/M5+YL86X5ynxtvjHfmu/M9+YH86P5yfxsfjG/mt/M7+YP86f5y/xt/jH/mv/MJFZSK5mV3EphpbRSWamtNFZaK52V3spgZbQyWZmtLFZWK5uV3cph5bRyWbmtPFZeK5+V3ypgFbQKWYWtIlZRq5hV3CphlbRKWaWtMlZZq5xV3qpgVbQqWZWtKlZVq5pV3aph1bRqWbWtOlZdq55V32pgNbQaWY2tJlZTq5nV3GphxVktrVZWa6uN1dZqZ7W3OlgdrU5WZ6uL1dXqZnW3elg9rV5Wb6uP1dfqZ/W3BlgDrUHWYGuINdQaZg23RlgjrVHWaGuMNdYaZ423JlgTrUnWZGuKNdWaZk23ZlgzrVnWbGuONdeaZ823FlgLrUXWYmuJtdRaZi23VlgrrVXWamuNtdaKtxKsRGudtd7aYG20NlmbrS3WVmubtd3aYe20dlm7rZiFWbhFWMAiLcqiLcZiLc7iLcESLcmSLcVSLWhplm4ZlmlZlm05lmt5lm8FVmghK7L2WHutfdZ+64B10DpkHbaOWEetY9Zx64R10jplnbbOWGetc9Z564J10bpkXbauWFeta9Z164Z107pl3bbuWHete9Z964H10HpkPbaeWE+tZ9Zz64X10nplvbbeWG+td9Z764P10fpkfba+WF+tb9Z364f10/pl/bb+WH+tf1YSO6mdzE5up7BT2qns1HYaO62dzk5vZ7Az2pnszHYWO6udzc5u57Bz2rns3HYeO6+dz85vF7AL2oXswnYRu6hdzC5ul7BL2qXs0nYZu6xdzi5vV7Ar2pXsynYVu6pdza5u17Br2rXs2nYdu65dz65vN7Ab2o3sxnYTu6ndzG5ut7Dj7JZ2K7u13cZua7ez29sd7I52J7uz3cXuanezu9s97J52L7u33cfua/ez+9sD7IH2IHuwPcQeag+zh9sj7JH2KHu0PcYea4+zx9sT7In2JHuyPcWeak+zp9sz7Jn2LHu2Pceea8+z59sL7IX2InuxvcReai+zl9sr7JX2Knu1vcZea8fbCXaivc5eb2+wN9qb7M32Fnurvc3ebu+wd9q77N12zMZs3CZsYJM2ZdM2Y7M2Z/O2YIu2ZMu2Yqs2tDVbtw3btC3bth3btT3btwM7tJEd2XvsvfY+e799wD5oH7IP20fso/Yx+7h9wj5pn7JP22fss/Y5+7x9wb5oX7Iv21fsq/Y1+7p9w75p37Jv23fsu/Y9+779wH5oP7If20/sp/Yz+7n9wn5pv7Jf22/st/Y7+739wf5of7I/21/sr/Y3+7v9w/5p/7J/23/sv/Y/O4mT1EnmJHdSOCmdVE5qJ42T1knnpHcyOBmdTE5mJ4uT1cnmZHdyODmdXE5uJ4+T18nn5HcKOAWdQk5hp4hT1CnmFHdKOCWdUk5pp4xT1innlHcqOBWdSk5lp4pT1anmVHdqODWdWk5tp45T16nn1HcaOA2dRk5jp4nT1GnmNHdaOHFOS6eV09pp47R12jntnQ5OR6eT09np4nR1ujndnR5OT6eX09vp4/R1+jn9nQHOQGeQM9gZ4gx1hjnDnRHOSGeUM9oZ44x1xjnjnQnORGeSM9mZ4kx1pjnTnRnOTGeWM9uZ48x15jnznQXOQmeRs9hZ4ix1ljnLnRXOSmeVs9pZ46x14p0EJ9FZ56x3NjgbnU3OZmeLs9XZ5mx3djg7nV3ObifmYA7uEA5wSIdyaIdxWIdzeEdwREdyZEdxVAc6mqM7hmM6lmM7juM6nuM7gRM6yImcPc5eZ5+z3zngHHQOOYedI85R55hz3DnhnHROOaedM85Z55xz3rngXHQuOZedK85V55pz3bnh3HRuObedO85d555z33ngPHQeOY+dJ85T55nz3HnhvHReOa+dN85b553z3vngfHQ+OZ+dL85X55vz3fnh/HR+Ob+dP85f55+TxE3qJnOTuynclG4qN7Wbxk3rpnPTuxncjG4mN7Obxc3qZnOzuzncnG4uN7ebx83r5nPzuwXcgm4ht7BbxC3qFnOLuyXckm4pt7Rbxi3rlnPLuxXcim4lt7Jbxa3qVnOruzXcmm4tt7Zbx63r1nPruw3chm4jt7HbxG3qNnObuy3cOLel28pt7bZx27rt3PZuB7ej28nt7HZxu7rd3O5uD7en28vt7fZx+7r93P7uAHegO8gd7A5xh7rD3OHuCHekO8od7Y5xx7rj3PHuBHeiO8md7E5xp7rT3OnuDHemO8ud7c5x57rz3PnuAnehu8hd7C5xl7rL3OXuCnelu8pd7a5x17rxboKb6K5z17sb3I3uJnezu8Xd6m5zt7s73J3uLne3G3MxF3cJF7ikS7m0y7isy7m8K7iiK7myq7iqC13N1V3DNV3LtV3HdV3P9d3ADV3kRu4ed6+7z93vHnAPuofcw+4R96h7zD3unnBPuqfc0+4Z96x7zj3vXnAvupfcy+4V96p7zb3u3nBvurfc2+4d9657z73vPnAfuo/cx+4T96n7zH3uvnBfuq/c1+4b9637zn3vfnA/up/cz+4X96v7zf3u/nB/ur/c3+4f96/7z03iJfWSecm9FF5KL5WX2kvjpfXSeem9DF5GL5OX2cviZfWyedm9HF5OL5eX28vj5fXyefm9Al5Br5BX2CviFfWKecW9El5Jr5RX2ivjlfXKeeW9Cl5Fr5JX2aviVfWqedW9Gl5Nr5ZX26vj1fXqefW9Bl5Dr5HX2GviNfWaec29Fl6c19Jr5bX22nhtvXZee6+D19Hr5HX2unhdvW5ed6+H19Pr5fX2+nh9vX5ef2+AN9Ab5A32hnhDvWHecG+EN9Ib5Y32xnhjvXHeeG+CN9Gb5E32pnhTvWnedG+GN9Ob5c325nhzvXnefG+Bt9Bb5C32lnhLvWXecm+Ft9Jb5a321nhrvXgvwUv01nnrvQ3eRm+Tt9nb4m31tnnbvR3eTm+Xt9uLeZiHe4QHPNKjPNpjPNbjPN4TPNGTPNlTPNWDnubpnuGZnuXZnuO5nuf5XuCFHvIib4+319vn7fcOeAe9Q95h74h31DvmHfdOeCe9U95p74x31jvnnfcueBe9S95l74p31bvmXfdueDe9W95t745317vn3fceeA+9R95j74n31HvmPfdeeC+9V95r74331nvnvfc+eB+9T95n74v31fvmffd+eD+9X95v74/31/vnJfGT+sn85H4KP6Wfyk/tp/HT+un89H4GP6Ofyc/sZ/Gz+tn87H4OP6efy8/t5/Hz+vn8/H4Bv6BfyC/sF/GL+sX84n4Jv6Rfyi/tl/HL+uX88n4Fv6Jfya/sV/Gr+tX86n4Nv6Zfy6/t1/Hr+vX8+n4Dv6HfyG/sN/Gb+s385n4LP85v6bfyW/tt/LZ+O7+938Hv6HfyO/td/K5+N7+738Pv6ffye/t9/L5+P7+/P8Af6A/yB/tD/KH+MH+4P8If6Y/yR/tj/LH+OH+8P8Gf6E/yJ/tT/Kn+NH+6P8Of6c/yZ/tz/Ln+PH++v8Bf6C/yF/tL/KX+Mn+5v8Jf6a/yV/tr/LV+vJ/gJ/rr/PX+Bn+jv8nf7G/xt/rb/O3+Dn+nv8vf7cd8zMd9wgc+6VM+7TM+63M+7wu+6Eu+7Cu+6kNf83Xf8E3f8m3f8V3f830/8EMf+ZG/x9/r7/P3+wf8g/4h/7B/xD/qH/OP+yf8k/4p/7R/xj/rn/PP+xf8i/4l/7J/xb/qX/Ov+zf8m/4t/7Z/x7/r3/Pv+w/8h/4j/7H/xH/qP/Of+y/8l/4r/7X/xn/rv/Pf+x/8j/4n/7P/xf/qf/O/+z/8n/4v/7f/x//r//OTBEmDZEHyIEWQMkgVpA7SBGmDdEH6IEOQMcgUZA6yBFmDbEH2IEeQM8gV5A7yBHmDfEH+oEBQMCgUFA6KBEWDYkHxoERQMigVlA7KBGWDckH5oEJQMagUVA6qBFWDakH1oEZQM6gV1A7qBHWDekH9oEHQMGgUNA6aBE2DZkHzoEUQF7QMWgWtgzZB26Bd0D7oEHQMOgWdgy5B16Bb0D3oEfQMegW9gz5B36Bf0D8YEAwMBgWDgyHB0GBYMDwYEYwMRgWjgzHB2GBcMD6YEEwMJgWTgynB1GBaMD2YEcwMZgWzgznB3GBeMD9YECwMFgWLgyXB0mBZsDxYEawMVgWrgzXB2iA+SAgSg3XB+mBDsDHYFGwOtgRbg23B9mBHsDPYFewOYgEW4AERgIAMqIAOmIANuIAPhEAMpEAOlEANYKAFemAEZmAFduAEbuAFfhAEYYCCKNgT7A32BfuDA8HB4FBwODgSHA2OBceDE8HJ4FRwOjgTnA3OBeeDC8HF4FJwObgSXA2uBdeDG8HN4FZwO7gT3A3uBfeDB8HD4FHwOHgSPA2eBc+DF8HL4FXwOngTvA3eBe+DD8HH4FPwOfgSfA2+Bd+DH8HP4FfwO/gT/A3+BUnCpGGyMHmYIkwZpgpTh2nCtGG6MH2YIcwYZgozh1nCrGG2MHuYI8wZ5gpzh3nCvGG+MH9YICwYFgoLh0XComGxsHhYIiwZlgpLh2XCsmG5sHxYIawYVgorh1XCqmG1sHpYI6wZ1gprh3XCumG9sH7YIGwYNgobh03CpmGzsHnYIowLW4atwtZhm7Bt2C5sH3YIO4adws5hl7Br2C3sHvYIe4a9wt5hn7Bv2C/sHw4IB4aDwsHhkHBoOCwcHo4IR4ajwtHhmHBsOC4cH04IJ4aTwsnhlHBqOC2cHs4IZ4azwtnhnHBuOC+cHy4IF4aLwsXhknBpuCxcHq4IV4arwtXhmnBtGB8mhInhunB9uCHcGG4KN4dbwq3htnB7uCPcGe4Kd4exEAvxkAhBSIZUSIdMyIZcyIdCKIZSKIdKqIYw1EI9NEIztEI7dEI39EI/DMIwRGEU7gn3hvvC/eGB8GB4KDwcHgmPhsfC4+GJ8GR4KjwdngnPhufC8+GF8GJ4KbwcXgmvhtfC6+GN8GZ4K7wd3gnvhvfC++GD8GH4KHwcPgmfhs/C5+GL8GX4Knwdvgnfhu/C9+GH8GP4Kfwcfgm/ht/C7+GP8Gf4K/wd/gn/hv/CJCgpSoaSoxQoJUqFUqM0KC1Kh9KjDCgjyoQyoywoK8qGsqMcKCfKhXKjPCgvyofyowKoICqECqMiqCgqhoqjEqgkKoVKozKoLCqHyqMKqCKqhCqjKqgqqoaqoxqoJqqFaqM6qC6qh+qjBqghaoQaoyaoKWqGmqMWKA61RK1Qa9QGtUXtUHvUAXVEnVBn1AV1Rd1Qd9QD9US9UG/UB/VF/VB/NAANRIPQYDQEDUXD0HA0Ao1Eo9BoNAaNRePQeDQBTUST0GQ0BU1F09B0NAPNRLPQbDQHzUXz0Hy0AC1Ei9BitAQtRcvQcrQCrUSr0Gq0Bq1F8SgBJaJ1aD3agDaiTWgz2oK2om1oO9qBdqJdaDeKIQzhiEAAkYhCNGIQizjEIwGJSEIyUpCKINKQjgxkIgvZyEEu8pCPAhQihCK0B+1F+9B+dAAdRIfQYXQEHUXH0HF0Ap1Ep9BpdAadRefQeXQBXUSX0GV0BV1F19B1dAPdRLfQbXQH3UX30H30AD1Ej9Bj9AQ9Rc/Qc/QCvUSv0Gv0Br1F79B79AF9RJ/QZ/QFfUXf0Hf0A/1Ev9Bv9Af9Rf9QkihplCxKHqWIUkapotRRmihtlC5KH2WIMkaZosxRlihrlC3KHuWIcka5otxRnihvlC/KHxWICkaFosJRkahoVCwqHpWISkalotJRmahsVC4qH1WIKkaVospRlahqVC2qHtWIaka1otpRnahuVC+qHzWIGkaNosZRk6hp1CxqHrWI4qKWUauoddQmahu1i9pHHaKOUaeoc9Ql6hp1i7pHPaKeUa+od9Qn6hv1i/pHA6KB0aBocDQkGhoNi4ZHI6KR0ahodDQmGhuNi8ZHE6KJ0aRocjQlmhpNi6ZHM6KZ0axodjQnmhvNi+ZHC6KF0aJocbQkWhoti5ZHK6KV0apodbQmWhvFRwlRYrQuWh9tiDZGm6LN0ZZoa7Qt2h7tiHZGu6LdUSzCIjwiIhCRERXR0X+C4AHAiiAAAGjucl22bdtdtm3btnXZtm38We/OztrOts33jsSOxo7FjsdOxE7GTsVOx87EzsbOxc7HLsQuxi7FLseuxK7GrsWux27EbsZuxW7HYjEQw2J4jIiRMSpGx5gYG+NiMMbHUEyIiTEpJseUmBrTYnrMiJkxK2bHnJgb82J+LIiFsSh2J3Y3di92P/Yg9jD2KPY49iT2NPYs9jz2IvYy9ir2OvYm9jb2LvY+9iH2MfYp9jn2JfY19i32PfYj9jP2K/Y79if2N/YvlgQkBclAcpACpASpQGoQB9KAtCAdSA8ygIwgE8gMsoB4kBVkA9lBDpAT5AK5QR6QF+QD+UEBUBAUAoVBEVAUFAPFQQlQEpQCpUEZUBaUA+VBBVARVAKVQRVQFVQD1UENUBPUArVBHVAX1AP1QQPQEDQCjUET0BQ0AwmgOWgBWoJWoDVoA9qCdqA96AA6gk6gM+gCuoJuoDvoAXqCXqA36AP6gn6gPxgABoJBYDAYAoaCYWA4GAFGglFgNBgDxoJxYDyYACaCSWAymAKmgmlgOpgBZoJZYDaYA+aCeWA+WAAWgkVgMVgCloJlYDlYAVaCVWA1WAPWgkSwDqwHG8BGsAlsBlvAVrANbAc7wE6wC+wGe8BesA/sBwfAQXAIHAZHwFFwDBwHJ8BJcAqcBmfAWXAOnAcXwEVwCVwGV8BVcA1cBzfATXAL3AYxAAAGcEAAElCABgxgAQcg4AECAhCBBGSgABVoQAcGMIEFbOAAF3jABwEIQQTugLvgHrgPHoCH4BF4DJ6Ap+AZeA5egJfgFXgN3oC34B14Dz6Aj+AT+Ay+gK/gG/gOfoCf4Bf4Df6Av+AfSIIlxZJhybEUWEosFZYai8PSYGmxdFh6LAOWEcuEZcayYPFYViwblh3LgeXEcmG5sTxYXiwflh8rgBXECmGFsSJYUawYVhwrgZXESmGlsTJYWawcVh6rgFXEKmGVsSpYVawaVh2rgdXEamG1sTpYXaweVh9rgDXEGmGNsSZYU6wZloA1x1pgLbFWWGusDdYWa4e1xzpgHbFOWGesC9YV64Z1x3pgPbFeWG+sD9YX64f1xwZgA7FB2GBsCDYUG4YNx0ZgI7FR2GhsDDYWG4eNxyZgE7FJ2GRsCjYVm4ZNx2ZgM7FZ2GxsDjYXm4fNxxZgC7FF2GJsCbYUW4Ytx1ZgK7FV2GpsDbYWS8TWYeuxDdhGbBO2GduCbcW2YduxHdhObBe2G9uD7cX2YfuxA9hB7BB2GDuCHcWOYcexE9hJ7BR2GjuDncXOYeexC9hF7BJ2GbuCXcWuYdexG9hN7BZ2G4thAMMwHCMwEqMwGmMwFuMwiPEYwgRMxCRMxhRMxTRMxwzMxCzMxhzMxTzMxwIsxCLsDnYXu4fdxx5gD7FH2GPsCfYUe4Y9x15gL7FX2GvsDfYWe4e9xz5gH7FP2GfsC/YV+4Z9x35gP7Ff2G/sD/YX+4clwZPiyfDkeAo8JZ4KT43H4WnwtHg6PD2eAc+IZ8Iz41nweDwrng3PjufAc+K58Nx4Hjwvng/PjxfAC+KF8MJ4EbwoXgwvjpfAS+Kl8NJ4GbwsXg4vj1fAK+KV8Mp4FbwqXg2vjtfAa+K18Np4HbwuXg+vjzfAG+KN8MZ4E7wp3gxPwJvjLfCWeCu8Nd4Gb4u3w9vjHfCOeCe8M94F74p3w7vjPfCeeC+8N94H74v3w/vjA/CB+CB8MD4EH4oPw4fjI/CR+Ch8ND4GH4uPw8fjE/CJ+CR8Mj4Fn4pPw6fjM/CZ+Cx8Nj4Hn4vPw+fjC/CF+CJ8Mb4EX4ovw5fjK/CV+Cp8Nb4GX4sn4uvw9fgGfCO+Cd+Mb8G34tvw7fgOfCe+C9+N78H34vvw/fgB/CB+CD+MH8GP4sfw4/gJ/CR+Cj+Nn8HP4ufw8/gF/CJ+Cb+MX8Gv4tfw6/gN/CZ+C7+Nx3CAYziOEziJUziNMziLczjEeRzhAi7iEi7jCq7iGq7jBm7iFm7jDu7iHu7jAR7iEX4Hv4vfw+/jD/CH+CP8Mf4Ef4o/w5/jL/CX+Cv8Nf4Gf4u/w9/jH/CP+Cf8M/4F/4p/w7/jP/Cf+C/8N/4H/4v/w5MQSYlkRHIiBZGSSEWkJuKINERaIh2RnshAZCQyEZmJLEQ8kZXIRmQnchA5iVxEbiIPkZfIR+QnChAFiUJEYaIIUZQoRhQnShAliVJEaaIMUZYoR5QnKhAViUpEZaIKUZWoRlQnahA1iVpEbaIOUZeoR9QnGhANiUZEY6IJ0ZRoRiQQzYkWREuiFdGaaEO0JdoR7YkOREeiE9GZ6EJ0JboR3YkeRE+iF9Gb6EP0JfoR/YkBxEBiEDGYGEIMJYYRw4kRxEhiFDGaGEOMJcYR44kJxERiEjGZmEJMJaYR04kZxExiFjGbmEPMJeYR84kFxEJiEbGYWEIsJZYRy4kVxEpiFbGaWEOsJRKJdcR6YgOxkdhEbCa2EFuJbcR2Ygexk9hF7Cb2EHuJfcR+4gBxkDhEHCaOEEeJY8Rx4gRxkjhFnCbOEGeJc8R54gJxkbhEXCauEFeJa8R14gZxk7hF3CZiBCAwAicIgiQogiYYgiU4AhI8gQiBEAmJkAmFUAmN0AmDMAmLsAmHcAmP8ImACImIuEPcJe4R94kHxEPiEfGYeEI8JZ4Rz4kXxEviFfGaeEO8Jd4R74kPxEfiE/GZ+EJ8Jb4R34kfxE/iF/Gb+EP8Jf4RScikZDIyOZmCTEmmIlOTcWQaMi2ZjkxPZiAzkpnIzGQWMp7MSmYjs5M5yJxkLjI3mYfMS+Yj85MFyIJkIbIwWYQsShYji5MlyJJkKbI0WYYsS5Yjy5MVyIpkJbIyWYWsSlYjq5M1yJpkLbI2WYesS9Yj65MNyIZkI7Ix2YRsSjYjE8jmZAuyJdmKbE22IduS7cj2ZAeyI9mJ7Ex2IbuS3cjuZA+yJ9mL7E32IfuS/cj+5AByIDmIHEwOIYeSw8jh5AhyJDmKHE2OIceS48jx5ARyIjmJnExOIaeS08jp5AxyJjmLnE3OIeeS88j55AJyIbmIXEwuIZeSy8jl5ApyJbmKXE2uIdeSieQ6cj25gdxIbiI3k1vIreQ2cju5g9xJ7iJ3k3vIveQ+cj95gDxIHiIPk0fIo+Qx8jh5gjxJniJPk2fIs+Q58jx5gbxIXiIvk1fIq+Q18jp5g7xJ3iJvkzESkBiJkwRJkhRJkwzJkhwJSZ5EpECKpETKpEKqpEbqpEGapEXapEO6pEf6ZECGZETeIe+S98j75APyIfmIfEw+IZ+Sz8jn5AvyJfmKfE2+Id+S78j35AfyI/mJ/Ex+Ib+S38jv5A/yJ/mL/E3+If+S/8gkVFIqGZWcSkGlpFJRqak4Kg2VlkpHpacyUBmpTFRmKgsVT2WlslHZqRxUTioXlZvKQ+Wl8lH5qQJUQaoQVZgqQhWlilHFqRJUSaoUVZoqQ5WlylHlqQpURaoSVZmqQlWlqlHVqRpUTaoWVZuqQ9Wl6lH1qQZUQ6oR1ZhqQjWlmlEJVHOqBdWSakW1ptpQbal2VHuqA9WR6kR1prpQXaluVHeqB9WT6kX1pvpQfal+VH9qADWQGkQNpoZQQ6lh1HBqBDWSGkWNpsZQY6lx1HhqAjWRmkRNpqZQU6lp1HRqBjWTmkXNpuZQc6l51HxqAbWQWkQtppZQS6ll1HJqBbWSWkWtptZQa6lEah21ntpAbaQ2UZupLdRWahu1ndpB7aR2UbupPdReah+1nzpAHaQOUYepI9RR6hh1nDpBnaROUaepM9RZ6hx1nrpAXaQuUZepK9RV6hp1nbpB3aRuUbepGAUojMIpgiIpiqIphmIpjoIUTyFKoERKomRKoVRKo3TKoEzKomzKoVzKo3wqoEIqou5Qd6l71H3qAfWQekQ9pp5QT6ln1HPqBfWSekW9pt5Qb6l31HvqA/WR+kR9pr5QX6lv1HfqB/WT+kX9pv5Qf6l/VBI6KZ2MTk6noFPSqejUdBydhk5Lp6PT0xnojHQmOjOdhY6ns9LZ6Ox0DjonnYvOTeeh89L56Px0AbogXYguTBehi9LF6OJ0CbokXYouTZehy9Ll6PJ0BboiXYmuTFehq9LV6Op0DbomXYuuTdeh69L16Pp0A7oh3YhuTDehm9LN6AS6Od2Cbkm3olvTbei2dDu6Pd2B7kh3ojvTXeiudDe6O92D7kn3onvTfei+dD+6Pz2AHkgPogfTQ+ih9DB6OD2CHkmPokfTY+ix9Dh6PD2BnkhPoifTU+ip9DR6Oj2DnknPomfTc+i59Dx6Pr2AXkgvohfTS+il9DJ6Ob2CXkmvolfTa+i1dCK9jl5Pb6A30pvozfQWeiu9jd5O76B30rvo3fQeei+9j95PH6AP0ofow/QR+ih9jD5On6BP0qfo0/QZ+ix9jj5PX6Av0pfoy/QV+ip9jb5O36Bv0rfo23SMBjRG4zRBkzRF0zRDszRHQ5qnES3QIi3RMq3QKq3ROm3QJm3RNu3QLu3RPh3QIR3Rd+i79D36Pv2Afkg/oh/TT+in9DP6Of2Cfkm/ol/Tb+i39Dv6Pf2B/kh/oj/TX+iv9Df6O/2D/kn/on/Tf+i/9D86CZOUScYkZ1IwKZlUTGomjknDpGXSMemZDExGJhOTmcnCxDNZmWxMdiYHk5PJxeRm8jB5mXxMfqYAU5ApxBRmijBFmWJMcaYEU5IpxZRmyjBlmXJMeaYCU5GpxFRmqjBVmWpMdaYGU5OpxdRm6jB1mXpMfaYB05BpxDRmmjBNmWZMAtOcacG0ZFoxrZk2TFumHdOe6cB0ZDoxnZkuTFemG9Od6cH0ZHoxvZk+TF+mH9OfGcAMZAYxg5khzFBmGDOcGcGMZEYxo5kxzFhmHDOemcBMZCYxk5kpzFRmGjOdmcHMZGYxs5k5zFxmHjOfWcAsZBYxi5klzFJmGbOcWcGsZFYxq5k1zFomkVnHrGc2MBuZTcxmZguzldnGbGd2MDuZXcxuZg+zl9nH7GcOMAeZQ8xh5ghzlDnGHGdOMCeZU8xp5gxzljnHnGcuMBeZS8xl5gpzlbnGXGduMDeZW8xtJsYABmNwhmBIhmJohmFYhmMgwzOIERiRkRiZURiV0RidMRiTsRibcRiX8RifCZiQiZg7zF3mHnOfecA8ZB4xj5knzFPmGfOcecG8ZF4xr5k3zFvmHfOe+cB8ZD4xn5kvzFfmG/Od+cH8ZH4xv5k/zF/mH5OETcomY5OzKdiUbCo2NRvHpmHTsunY9GwGNiObic3MZmHj2axsNjY7m4PNyeZic7N52LxsPjY/W4AtyBZiC7NF2KJsMbY4W4ItyZZiS7Nl2LJsObY8W4GtyFZiK7NV2KpsNbY6W4OtydZia7N12LpsPbY+24BtyDZiG7NN2KZsMzaBbc62YFuyrdjWbBu2LduObc92YDuyndjObBe2K9uN7c72YHuyvdjebB+2L9uP7c8OYAeyg9jB7BB2KDuMHc6OYEeyo9jR7Bh2LDuOHc9OYCeyk9jJ7BR2KjuNnc7OYGeys9jZ7Bx2LjuPnc8uYBeyi9jF7BJ2KbuMXc6uYFeyq9jV7Bp2LZvIrmPXsxvYjewmdjO7hd3KbmO3szvYnewudje7h93L7mP3swfYg+wh9jB7hD3KHmOPsyfYk+wp9jR7hj3LnmPPsxfYi+wl9jJ7hb3KXmOvszfYm+wt9jYbYwGLsThLsCRLsTTLsCzLsZDlWcQKrMhKrMwqrMpqrM4arMlarM06rMt6rM8GbMhG7B32LnuPvc8+YB+yj9jH7BP2KfuMfc6+YF+yr9jX7Bv2LfuOfc9+YD+yn9jP7Bf2K/uN/c7+YH+yv9jf7B/2L/uPTcIl5ZJxybkUXEouFZeai+PScGm5dFx6LgOXkcvEZeaycPFcVi4bl53LweXkcnG5uTxcXi4fl58rwBXkCnGFuSJcUa4YV5wrwZXkSnGluTJcWa4cV56rwFXkKnGVuSpcVa4aV52rwdXkanG1uTpcXa4eV59rwDXkGnGNuSZcU64Zl8A151pwLblWXGuuDdeWa8e15zpwHblOXGeuC9eV68Z153pwPbleXG+uD9eX68f15wZwA7lB3GBuCDeUG8YN50ZwI7lR3GhuDDeWG8eN5yZwE7lJ3GRuCjeVm8ZN52ZwM7lZ3GxuDjeXm8fN5xZwC7lF3GJuCbeUW8Yt51ZwK7lV3GpuDbeWS+TWceu5DdxGbhO3mdvCbeW2cdu5HdxObhe3m9vD7eX2cfu5A9xB7hB3mDvCHeWOcce5E9xJ7hR3mjvDneXOcee5C9xF7hJ3mbvCXeWucde5G9xN7hZ3m4txgMM4nCM4kqM4mmM4luM4yPEc4gRO5CRO5hRO5TRO5wzO5CzO5hzO5TzO5wIu5CLuDneXu8fd5x5wD7lH3GPuCfeUe8Y9515wL7lX3GvuDfeWe8e95z5wH7lP3GfuC/eV+8Z9535wP7lf3G/uD/eX+8clgUlhMpgcpoApYSqYGsbBNDAtTAfTwwwwI8wEM8MsMB5mhdlgdpgD5oS5YG6YB+aF+WB+WAAWhIVgYVgEFoXFYHFYApaEpWBpWAaWheVgeVgBVoSVYGVYBVaF1WB1WAPWhLVgbVgH1oX1YH3YADaEjWBj2AQ2hc1gAmwOW8CWsBVsDdvAtrAdbA87wI6wE+wMu8CusBvsDnvAnrAX7A37wL6wH+wPB8CBcBAcDIfAoXAYHA5HwJFwFBwNx8CxcBwcDyfAiXASnAynwKlwGpwOZ8CZcBacDefAuXAenA8XwIVwEVwMl8ClcBlcDlfAlXAVXA3XwLUwEa6D6+EGuBFugpvhFrgVboPb4Q64E+6Cu+EeuBfug/vhAXgQHoKH4RF4FB6Dx+EJeBKegqfhGXgWnoPn4QV4EV6Cl+EVeBVeg9fhDXgT3oK3YQwCiEEcEpCEFKQhA1nIQQh5iKAARShBGSpQhRrUoQFNaEEbOtCFHvRhAEMYwTvwLrwH78MH8CF8BB/DJ/ApfAafwxfwJXwFX8M38C18B9/DD/Aj/AQ/wy/wK/wGv8Mf8Cf8BX/DP/Av/AeT8En5ZHxyPgWfkk/Fp+bj+DR8Wj4dn57PwGfkM/GZ+Sx8PJ+Vz8Zn53PwOflcfG4+D5+Xz8fn5wvwBflCfGG+CF+UL8YX50vwJflSfGm+DF+WL8eX5yvwFflKfGW+Cl+Vr8ZX52vwNflafG2+Dl+Xr8fX5xvwDflGfGO+Cd+Ub8Yn8M35FnxLvhXfmm/Dt+Xb8e35DnxHvhPfme/Cd+W78d35HnxPvhffm+/D9+X78f35AfxAfhA/mB/CD+WH8cP5EfxIfhQ/mh/Dj+XH8eP5CfxEfhI/mZ/CT+Wn8dP5GfxMfhY/m5/Dz+Xn8fP5BfxCfhG/mF/CL+WX8cv5FfxKfhW/ml/Dr+UT+XX8en4Dv5HfxG/mt/Bb+W38dn4Hv5Pfxe/m9/B7+X38fv4Af5A/xB/mj/BH+WP8cf4Ef5I/xZ/mz/Bn+XP8ef4Cf5G/xF/mr/BX+Wv8df4Gf5O/xd/mYzzgMR7nCZ7kKZ7mGZ7lOR7yPI94gRd5iZd5hVd5jdd5gzd5i7d5h3d5j/f5gA/5iL/D3+Xv8ff5B/xD/hH/mH/CP+Wf8c/5F/xL/hX/mn/Dv+Xf8e/5D/xH/hP/mf/Cf+W/8d/5H/xP/hf/m//D/+X/8UlQUpQMJUcpUEqUCqVGcSgNSovSofQoA8qIMqHMKAuKR1lRNpQd5UA5US6UG+VBeVE+lB8VQAVRIVQYFUFFUTFUHJVAJVEpVBqVQWVROVQeVUAVUSVUGVVBVVE1VB3VQDVRLVQb1UF1UT1UHzVADVEj1Bg1QU1RM5SAmqMWqCVqhVqjNqgtaofaow6oI+qEOqMuqCvqhrqjHqgn6oV6oz6oL+qH+qMBaCAahAajIWgoGoaGoxFoJBqFRqMxaCwah8ajCWgimoQmoyloKpqGpqMZaCaahWajOWgumofmowVoIVqEFqMlaClahpajFWglWoVWozVoLUpE69B6tAFtRJvQZrQFbUXb0Ha0A+1Eu9ButAftRfvQfnQAHUSH0GF0BB1Fx9BxdAKdRKfQaXQGnUXn0Hl0AV1El9BldAVdRdfQdXQD3US30G0UQwBhCEcEIhGFaMQgFnEIIh4hJCARSUhGClKRhnRkIBNZyEYOcpGHfBSgEEXoDrqL7qH76AF6iB6hx+gJeoqeoefoBXqJXqHX6A16i96h9+gD+og+oc/oC/qKvqHv6Af6iX6h3+gP+ov+oSRCUiGZkFxIIaQUUgmphTghjZBWSCekFzIIGYVMQmYhixAvZBWyCdmFHEJOIZeQW8gj5BXyCfmFAkJBoZBQWCgiFBWKCcWFEkJJoZRQWigjlBXKCeWFCkJFoZJQWagiVBWqCdWFGkJNoZZQW6gj1BXqCfWFBkJDoZHQWGgiNBWaCQlCc6GF0FJoJbQW2ghthXZCe6GD0FHoJHQWughdhW5Cd6GH0FPoJfQW+gh9hX5Cf2GAMFAYJAwWhghDhWHCcGGEMFIYJYwWxghjhXHCeGGCMFGYJEwWpghThWnCdGGGMFOYJcwW5ghzhXnCfGGBsFBYJCwWlghLhWXCcmGFsFJYJawW1ghrhURhnbBe2CBsFDYJm4UtwlZhm7Bd2CHsFHYJu4U9wl5hn7BfOCAcFA4Jh4UjwlHhmHBcOCGcFE4Jp4UzwlnhnHBeuCBcFC4Jl4UrwlXhmnBduCHcFG4Jt4WYAARMwAVCIAVKoAVGYAVOgAIvIEEQREESZEERVEETdMEQTMESbMERXMETfCEQQiES7gh3hXvCfeGB8FB4JDwWnghPhWfCc+GF8FJ4JbwW3ghvhXfCe+GD8FH4JHwWvghfhW/Cd+GH8FP4JfwW/gh/hX9CEjGpmExMLqYQU4qpxNRinJhGTCumE9OLGcSMYiYxs5hFjBezitnE7GIOMaeYS8wt5hHzivnE/GIBsaBYSCwsFhGLisXE4mIJsaRYSiwtlhHLiuXE8mIFsaJYSawsVhGritXE6mINsaZYS6wt1hHrivXE+mIDsaHYSGwsNhGbis3EBLG52EJsKbYSW4ttxLZiO7G92EHsKHYSO4tdxK5iN7G72EPsKfYSe4t9xL5iP7G/OEAcKA4SB4tDxKHiMHG4OEIcKY4SR4tjxLHiOHG8OEGcKE4SJ4tTxKniNHG6OEOcKc4SZ4tzxLniPHG+uEBcKC4SF4tLxKXiMnG5uEJcKa4SV4trxLViorhOXC9uEDeKm8TN4hZxq7hN3C7uEHeKu8Td4h5xr7hP3C8eEA+Kh8TD4hHxqHhMPC6eEE+Kp8TT4hnxrHhOPC9eEC+Kl8TL4hXxqnhNvC7eEG+Kt8TbYkwEIibiIiGSIiXSIiOyIidCkReRKIiiKImyqIiqqIm6aIimaIm26Iiu6Im+GIihGIl3xLviPfG++EB8KD4SH4tPxKfiM/G5+EJ8Kb4SX4tvxLfiO/G9+EH8KH4SP4tfxK/iN/G7+EP8Kf4Sf4t/xL/iPzGJlFRKJiWXUkgppVRSailOSiOlldJJ6aUMUkYpk5RZyiLFS1mlbFJ2KYeUU8ol5ZbySHmlfFJ+qYBUUCokFZaKSEWlYlJxqYRUUiollZbKSGWlclJ5qYJUUaokVZaqSFWlalJ1qYZUU6ol1ZbqSHWlelJ9qYHUUGokNZaaSE2lZlKC1FxqIbWUWkmtpTZSW6md1F7qIHWUOkmdpS5SV6mb1F3qIfWUekm9pT5SX6mf1F8aIA2UBkmDpSHSUGmYNFwaIY2URkmjpTHSWGmcNF6aIE2UJkmTpSnSVGmaNF2aIc2UZkmzpTnSXGmeNF9aIC2UFkmLpSXSUmmZtFxaIa2UVkmrpTXSWilRWietlzZIG6VN0mZpi7RV2iZtl3ZIO6Vd0m5pj7RX2iftlw5IB6VD0mHpiHRUOiYdl05IJ6VT0mnpjHRWOiedly5IF6VL0mXpinRVuiZdl25IN6Vb0m0pJgEJk3CJkEiJkmiJkViJk6DES0gSJFGSJFlSJFXSJF0yJFOyJFtyJFfyJF8KpFCKpDvSXemedF96ID2UHkmPpSfSU+mZ9Fx6Ib2UXkmvpTfSW+md9F76IH2UPkmfpS/SV+mb9F36If2Ufkm/pT/SX+mflEROKieTk8sp5JRyKjm1HCenkdPK6eT0cgY5o5xJzixnkePlrHI2ObucQ84p55Jzy3nkvHI+Ob9cQC4oF5ILy0XkonIxubhcQi4pl5JLy2XksnI5ubxcQa4oV5Iry1XkqnI1ubpcQ64p15Jry3XkunI9ub7cQG4oN5Iby03kpnIzOUFuLreQW8qt5NZyG7mt3E5uL3eQO8qd5M5yF7mr3E3uLveQe8q95N5yH7mv3E/uLw+QB8qD5MHyEHmoPEweLo+QR8qj5NHyGHmsPE4eL0+QJ8qT5MnyFHmqPE2eLs+QZ8qz5NnyHHmuPE+eLy+QF8qL5MXyEnmpvExeLq+QV8qr5NXyGnmtnCivk9fLG+SN8iZ5s7xF3ipvk7fLO+Sd8i55t7xH3ivvk/fLB+SD8iH5sHxEPiofk4/LJ+ST8in5tHxGPiufk8/LF+SL8iX5snxFvipfk6/LN+Sb8i35thyTgYzJuEzIpEzJtMzIrMzJUOZlJAuyKEuyLCuyKmuyLhuyKVuyLTuyK3uyLwdyKEfyHfmufE++Lz+QH8qP5MfyE/mp/Ex+Lr+QX8qv5NfyG/mt/E5+L3+QP8qf5M/yF/mr/E3+Lv+Qf8q/5N/yH/mv/E9OoiRVkinJlRRKSiWVklqJU9IoaZV0Snolg5JRyaRkVrIo8UpWJZuSXcmh5FRyKbmVPEpeJZ+SXymgFFQKKYWVIkpRpZhSXCmhlFRKKaWVMkpZpZxSXqmgVFQqKZWVKkpVpZpSXamh1FRqKbWVOkpdpZ5SX2mgNFQaKY2VJkpTpZmSoDRXWigtlVZKa6WN0lZpp7RXOigdlU5KZ6WL0lXppnRXeig9lV5Kb6WP0lfpp/RXBigDlUHKYGWIMlQZpgxXRigjlVHKaGWMMlYZp4xXJigTlUnKZGWKMlWZpkxXZigzlVnKbGWOMleZp8xXFigLlUXKYmWJslRZpixXVigrlVXKamWNslZJVNYp65UNykZlk7JZ2aJsVbYp25Udyk5ll7Jb2aPsVfYp+5UDykHlkHJYOaIcVY4px5UTyknllHJaOaOcVc4p55ULykXlknJZuaJcVa4p15Ubyk3llnJbiSlAwRRcIRRSoRRaYRRW4RSo8ApSBEVUJEVWFEVVNEVXDMVULMVWHMVVPMVXAiVUIuWOcle5p9xXHigPlUfKY+WJ8lR5pjxXXigvlVfKa+WN8lZ5p7xXPigflU/KZ+WL8lX5pnxXfig/lV/Kb+WP8lf5pyRRk6rJ1ORqCjWlmkpNrcapadS0ajo1vZpBzahmUjOrWdR4NauaTc2u5lBzqrnU3GoeNa+aT82vFlALqoXUwmoRtahaTC2ullBLqqXU0moZtaxaTi2vVlArqpXUymoVtapaTa2u1lBrqrXU2modta5aT62vNlAbqo3UxmoTtanaTE1Qm6st1JZqK7W12kZtq7ZT26sd1I5qJ7Wz2kXtqnZTu6s91J5qL7W32kftq/ZT+6sD1IHqIHWwOkQdqg5Th6sj1JHqKHW0OkYdq45Tx6sT1InqJHWyOkWdqk5Tp6sz1JnqLHW2Okedq85T56sL1IXqInWxukRdqi5Tl6sr1JXqKnW1ukZdqyaq69T16gZ1o7pJ3axuUbeq29Tt6g51p7pL3a3uUfeq+9T96gH1oHpIPaweUY+qx9Tj6gn1pHpKPa2eUc+q59Tz6gX1onpJvaxeUa+q19Tr6g31pnpLva3GVKBiKq4SKqlSKq0yKqtyKlR5FamCKqqSKquKqqqaqquGaqqWaquO6qqe6quBGqqReke9q95T76sP1IfqI/Wx+kR9qj5Tn6sv1JfqK/W1+kZ9q75T36sf1I/qJ/Wz+kX9qn5Tv6s/1J/qL/W3+kf9q/5Tk2hJtWRaci2FllJLpaXW4rQ0WlotnZZey6Bl1DJpmbUsWryWVcumZddyaDm1XFpuLY+WV8un5dcKaAW1QlphrYhWVCumFddKaCW1UlpprYxWViunldcqaBW1SlplrYpWVaumVddqaDW1WlptrY5WV6un1dcaaA21RlpjrYnWVGumJWjNtRZaS62V1lpro7XV2mnttQ5aR62T1lnronXVumndtR5aT62X1lvro/XV+mn9tQHaQG2QNlgbog3VhmnDtRHaSG2UNlobo43VxmnjtQnaRG2SNlmbok3VpmnTtRnaTG2WNlubo83V5mnztQXaQm2Rtlhboi3VlmnLtRXaSm2Vtlpbo63VErV12nptg7ZR26Rt1rZoW7Vt2nZth7ZT26Xt1vZoe7V92n7tgHZQO6Qd1o5oR7Vj2nHthHZSO6Wd1s5oZ7Vz2nntgnZRu6Rd1q5oV7Vr2nXthnZTu6Xd1mIa0DAN1wiN1CiN1hiN1TgNaryGNEETNUmTNUVTNU3TNUMzNUuzNUdzNU/ztUALtUi7o93V7mn3tQfaQ+2R9lh7oj3VnmnPtRfaS+2V9lp7o73V3mnvtQ/aR+2T9ln7on3VvmnftR/aT+2X9lv7o/3V/mlJ9KR6Mj25nkJPqafSU+txeho9rZ5OT69n0DPqmfTMehY9Xs+qZ9Oz6zn0nHouPbeeR8+r59Pz6wX0gnohvbBeRC+qF9OL6yX0knopvbReRi+rl9PL6xX0inolvbJeRa+qV9Or6zX0mnotvbZeR6+r19Pr6w30hnojvbHeRG+qN9MT9OZ6C72l3kpvrbfR2+rt9PZ6B72j3knvrHfRu+rd9O56D72n3kvvrffR++r99P76AH2gPkgfrA/Rh+rD9OH6CH2kPkofrY/Rx+rj9PH6BH2iPkmfrE/Rp+rT9On6DH2mPkufrc/R5+rz9Pn6An2hvkhfrC/Rl+rL9OX6Cn2lvkpfra/R1+qJ+jp9vb5B36hv0jfrW/St+jZ9u75D36nv0nfre/S9+j59v35AP6gf0g/rR/Sj+jH9uH5CP6mf0k/rZ/Sz+jn9vH5Bv6hf0i/rV/Sr+jX9un5Dv6nf0m/rMR3omI7rhE7qlE7rjM7qnA51Xke6oIu6pMu6oqu6puu6oZu6pdu6o7u6p/t6oId6pN/R7+r39Pv6A/2h/kh/rD/Rn+rP9Of6C/2l/kp/rb/R3+rv9Pf6B/2j/kn/rH/Rv+rf9O/6D/2n/kv/rf/R/+r/9CRGUiOZkdxIYaQ0UhmpjTgjjZHWSGekNzIYGY1MRmYjixFvZDWyGdmNHEZOI5eR28hj5DXyGfmNAkZBo5BR2ChiFDWKGcWNEkZJo5RR2ihjlDXKGeWNCkZFo5JR2ahiVDWqGdWNGkZNo5ZR26hj1DXqGfWNBkZDo5HR2GhiNDWaGQlGc6OF0dJoZbQ22hhtjXZGe6OD0dHoZHQ2uhhdjW5Gd6OH0dPoZfQ2+hh9jX5Gf2OAMdAYZAw2hhhDjWHGcGOEMdIYZYw2xhhjjXHGeGOCMdGYZEw2phhTjWnGdGOGMdOYZcw25hhzjXnGfGOBsdBYZCw2lhhLjWXGcmOFsdJYZaw21hhrjURjnbHe2GBsNDYZm40txlZjm7Hd2GHsNHYZu409xl5jn7HfOGAcNA4Zh40jxlHjmHHcOGGcNE4Zp40zxlnjnHHeuGBcNC4Zl40rxlXjmnHduGHcNG4Zt42YAQzMwA3CIA3KoA3GYA3OgAZvIEMwREMyZEMxVEMzdMMwTMMybMMxXMMzfCMwQiMy7hh3jXvGfeOB8dB4ZDw2nhhPjWfGc+OF8dJ4Zbw23hhvjXfGe+OD8dH4ZHw2vhhfjW/Gd+OH8dP4Zfw2/hh/jX9GEjOpmcxMbqYwU5qpzNRmnJnGTGumM9ObGcyMZiYzs5nFjDezmtnM7GYOM6eZy8xt5jHzmvnM/GYBs6BZyCxsFjGLmsXM4mYJs6RZyixtljHLmuXM8mYFs6JZyaxsVjGrmtXM6mYNs6ZZy6xt1jHrmvXM+mYDs6HZyGxsNjGbms3MBLO52cJsabYyW5ttzLZmO7O92cHsaHYyO5tdzK5mN7O72cPsafYye5t9zL5mP7O/OcAcaA4yB5tDzKHmMHO4OcIcaY4yR5tjzLHmOHO8OcGcaE4yJ5tTzKnmNHO6OcOcac4yZ5tzzLnmPHO+ucBcaC4yF5tLzKXmMnO5ucJcaa4yV5trzLVmornOXG9uMDeam8zN5hZzq7nN3G7uMHeau8zd5h5zr7nP3G8eMA+ah8zD5hHzqHnMPG6eME+ap8zT5hnzrHnOPG9eMC+al8zL5hXzqnnNvG7eMG+at8zbZswEJmbiJmGSJmXSJmOyJmdCkzeRKZiiKZmyqZiqqZm6aZimaZm26Ziu6Zm+GZihGZl3zLvmPfO++cB8aD4yH5tPzKfmM/O5+cJ8ab4yX5tvzLfmO/O9+cH8aH4yP5tfzK/mN/O7+cP8af4yf5t/zL/mPzOJldRKZiW3UlgprVRWaivOSmOltdJZ6a0MVkYrk5XZymLFW1mtbFZ2K4eV08pl5bbyWHmtfFZ+q4BV0CpkFbaKWEWtYlZxq4RV0ipllbbKWGWtclZ5q4JV0apkVbaqWFWtalZ1q4ZV06pl1bbqWHWtelZ9q4HV0GpkNbaaWE2tZlaC1dxqYbW0WlmtrTZWW6ud1d7qYHW0OlmdrS5WV6ub1d3qYfW0elm9rT5WX6uf1d8aYA20BlmDrSHWUGuYNdwaYY20RlmjrTHWWGucNd6aYE20JlmTrSnWVGuaNd2aYc20ZlmzrTnWXGueNd9aYC20FlmLrSXWUmuZtdxaYa20VlmrrTXWWivRWmettzZYG61N1mZri7XV2mZtt3ZYO61d1m5rj7XX2mfttw5YB61D1mHriHXUOmYdt05YJ61T1mnrjHXWOmedty5YF61L1mXrinXVumZdt25YN61b1m0rZgELs3CLsEiLsmiLsViLs6DFW8gSLNGSLNlSLNXSLN0yLNOyLNtyLNfyLN8KrNCKrDvWXeuedd96YD20HlmPrSfWU+uZ9dx6Yb20XlmvrTfWW+ud9d76YH20PlmfrS/WV+ub9d36Yf20flm/rT/WX+uflcROaiezk9sp7JR2Kju1HWensdPa6ez0dgY7o53JzmxnsePtrHY2O7udw85p57Jz23nsvHY+O79dwC5oF7IL20XsonYxu7hdwi5pl7JL22XssnY5u7xdwa5oV7Ir21XsqnY1u7pdw65p17Jr23XsunY9u77dwG5oN7Ib203spnYzO8FubrewW9qt7NZ2G7ut3c5ub3ewO9qd7M52F7ur3c3ubvewe9q97N52H7uv3c/ubw+wB9qD7MH2EHuoPcwebo+wR9qj7NH2GHusPc4eb0+wJ9qT7Mn2FHuqPc2ebs+wZ9qz7Nn2HHuuPc+eby+wF9qL7MX2Enupvcxebq+wV9qr7NX2GnutnWivs9fbG+yN9iZ7s73F3mpvs7fbO+yd9i57t73H3mvvs/fbB+yD9iH7sH3EPmofs4/bJ+yT9in7tH3GPmufs8/bF+yL9iX7sn3Fvmpfs6/bN+yb9i37th2zgY3ZuE3YpE3ZtM3YrM3Z0OZtZAu2aEu2bCu2amu2bhu2aVu2bTu2a3u2bwd2aEf2Hfuufc++bz+wH9qP7Mf2E/up/cx+br+wX9qv7Nf2G/ut/c5+b3+wP9qf7M/2F/ur/c3+bv+wf9q/7N/2H/uv/c9O4iR1kjnJnRROSieVk9qJc9I4aZ10Tnong5PRyeRkdrI48U5WJ5uT3cnh5HRyObmdPE5eJ5+T3yngFHQKOYWdIk5Rp5hT3CnhlHRKOaWdMk5Zp5xT3qngVHQqOZWdKk5Vp5pT3anh1HRqObWdOk5dp55T32ngNHQaOY2dJk5Tp5mT4DR3WjgtnVZOa6eN09Zp57R3OjgdnU5OZ6eL09Xp5nR3ejg9nV5Ob6eP09fp5/R3BjgDnUHOYGeIM9QZ5gx3RjgjnVHOaGeMM9YZ54x3JjgTnUnOZGeKM9WZ5kx3ZjgznVnObGeOM9eZ58x3FjgLnUXOYmeJs9RZ5ix3VjgrnVXOameNs9ZJdNY5650NzkZnk7PZ2eJsdbY5250dzk5nl7Pb2ePsdfY5+50DzkHnkHPYOeIcdY45x50TzknnlHPaOeOcdc45550LzkXnknPZueJcda45150bzk3nlnPbiTnAwRzcIRzSoRzaYRzW4Rzo8A5yBEd0JEd2FEd1NEd3DMd0LMd2HMd1PMd3Aid0IueOc9e559x3HjgPnUfOY+eJ89R55jx3XjgvnVfOa+eN89Z557x3PjgfnU/OZ+eL89X55nx3fjg/nV/Ob+eP89f55yRxk7rJ3ORuCjelm8pN7ca5ady0bjo3vZvBzehmcjO7Wdx4N6ubzc3u5nBzurnc3G4eN6+bz83vFnALuoXcwm4Rt6hbzC3ulnBLuqXc0m4Zt6xbzi3vVnArupXcym4Vt6pbza3u1nBrurXc2m4dt65bz63vNnAbuo3cxm4Tt6nbzE1wm7st3JZuK7e128Zt67Zz27sd3I5uJ7ez28Xt6nZzu7s93J5uL7e328ft6/Zz+7sD3IHuIHewO8Qd6g5zh7sj3JHuKHe0O8Yd645zx7sT3InuJHeyO8Wd6k5zp7sz3JnuLHe2O8ed685z57sL3IXuInexu8Rd6i5zl7sr3JXuKne1u8Zd6ya669z17gZ3o7vJ3exucbe629zt7g53p7vL3e3ucfe6+9z97gH3oHvIPewecY+6x9zj7gn3pHvKPe2ecc+659zz7gX3onvJvexeca+619zr7g33pnvLve3GXOBiLu4SLulSLu0yLutyLnR5F7mCK7qSK7uKq7qaq7uGa7qWa7uO67qe67uBG7qRe8e9695z77sP3IfuI/ex+8R96j5zn7sv3JfuK/e1+8Z9675z37sf3I/uJ/ez+8X96n5zv7s/3J/uL/e3+8f96/5zk3hJvWReci+Fl9JL5aX24rw0XlovnZfey+Bl9DJ5mb0sXryX1cvmZfdyeDm9XF5uL4+X18vn5fcKeAW9Ql5hr4hX1CvmFfdKeCW9Ul5pr4xX1ivnlfcqeBW9Sl5lr4pX1avmVfdqeDW9Wl5tr45X16vn1fcaeA29Rl5jr4nX1GvmJXjNvRZeS6+V19pr47X12nntvQ5eR6+T19nr4nX1unndvR5eT6+X19vr4/X1+nn9vQHeQG+QN9gb4g31hnnDvRHeSG+UN9ob4431xnnjvQneRG+SN9mb4k31pnnTvRneTG+WN9ub48315nnzvQXeQm+Rt9hb4i31lnnLvRXeSm+Vt9pb4631Er113npvg7fR2+Rt9rZ4W71t3nZvh7fT2+Xt9vZ4e7193n7vgHfQO+Qd9o54R71j3nHvhHfSO+Wd9s54Z71z3nnvgnfRu+Rd9q54V71r3nXvhnfTu+Xd9mIe8DAP9wiP9CiP9hiP9TgPeryHPMETPcmTPcVTPc3TPcMzPcuzPcdzPc/zvcALvci749317nn3vQfeQ++R99h74j31nnnPvRfeS++V99p747313nnvvQ/eR++T99n74n31vnnfvR/eT++X99v74/31/nlJ/KR+Mj+5n8JP6afyU/txfho/rZ/OT+9n8DP6mfzMfhY/3s/qZ/Oz+zn8nH4uP7efx8/r5/Pz+wX8gn4hv7BfxC/qF/OL+yX8kn4pv7Rfxi/rl/PL+xX8in4lv7Jfxa/qV/Or+zX8mn4tv7Zfx6/r1/Pr+w38hn4jv7HfxG/qN/MT/OZ+C7+l38pv7bfx2/rt/PZ+B7+j38nv7Hfxu/rd/O5+D7+n38vv7ffx+/r9/P7+AH+gP8gf7A/xh/rD/OH+CH+kP8of7Y/xx/rj/PH+BH+iP8mf7E/xp/rT/On+DH+mP8uf7c/x5/rz/Pn+An+hv8hf7C/xl/rL/OX+Cn+lv8pf7a/x1/qJ/jp/vb/B3+hv8jf7W/yt/jZ/u7/D3+nv8nf7e/y9/j5/v3/AP+gf8g/7R/yj/jH/uH/CP+mf8k/7Z/yz/jn/vH/Bv+hf8i/7V/yr/jX/un/Dv+nf8m/7MR/4mI/7hE/6lE/7jM/6nA993ke+4Iu+5Mu+4qu+5uu+4Zu+5du+47u+5/t+4Id+5N/x7/r3/Pv+A/+h/8h/7D/xn/rP/Of+C/+l/8p/7b/x3/rv/Pf+B/+j/8n/7H/xv/rf/O/+D/+n/8v/7f/x//r//CRB0iBZkDxIEaQMUgWpg7ggTZA2SBekDzIEGYNMQeYgSxAfZA2yBdmDHEHOIFeQO8gT5A3yBfmDAkHBoFBQOCgSFA2KBcWDEkHJoFRQOigTlA3KBeWDCkHFoFJQOagSVA2qBdWDGkHNoFZQO6gT1A3qBfWDBkHDoFHQOGgSNA2aBQlB86BF0DJoFbQO2gRtg3ZB+6BD0DHoFHQOugRdg25B96BH0DPoFfQO+gR9g35B/2BAMDAYFAwOhgRDg2HB8GBEMDIYFYwOxgRjg3HB+GBCMDGYFEwOpgRTg2nB9GBGMDOYFcwO5gRzg3nB/GBBsDBYFCwOlgRLg2XB8mBFsDJYFawO1gRrg8RgXbA+2BBsDDYFm4MtwdZgW7A92BHsDHYFu4M9wd5gX7A/OBAcDA4Fh4MjwdHgWHA8OBGcDE4Fp4MzwdngXHA+uBBcDC4Fl4MrwdXgWnA9uBHcDG4Ft4NYAAIswAMiIAMqoAMmYAMugAEfoEAIxEAK5EAJ1EAL9MAIzMAK7MAJ3MAL/CAIwiAK7gR3g3vB/eBB8DB4FDwOngRPg2fB8+BF8DJ4FbwO3gRvg3fB++BD8DH4FHwOvgRfg2/B9+BH8DP4FfwO/gR/g39BkjBpmCxMHqYIU4apwtRhXJgmTBumC9OHGcKMYaYwc5gljA+zhtnC7GGOMGeYK8wd5gnzhvnC/GGBsGBYKCwcFgmLhsXC4mGJsGRYKiwdlgnLhuXC8mGFsGJYKawcVgmrhtXC6mGNsGZYK6wd1gnrhvXC+mGDsGHYKGwcNgmbhs3ChLB52CJsGbYKW4dtwrZhu7B92CHsGHYKO4ddwq5ht7B72CPsGfYKe4d9wr5hv7B/OCAcGA4KB4dDwqHhsHB4OCIcGY4KR4djwrHhuHB8OCGcGE4KJ4dTwqnhtHB6OCOcGc4KZ4dzwrnhvHB+uCBcGC4KF4dLwqXhsnB5uCJcGa4KV4drwrVhYrguXB9uCDeGm8LN4ZZwa7gt3B7uCHeGu8Ld4Z5wb7gv3B8eCA+Gh8LD4ZHwaHgsPB6eCE+Gp8LT4ZnwbHguPB9eCC+Gl8LL4ZXwangtvB7eCG+Gt8LbYSwEIRbiIRGSIRXSIROyIRfCkA9RKIRiKIVyqIRqqIV6aIRmaIV26IRu6IV+GIRhGIV3wrvhvfB++CB8GD4KH4dPwqfhs/B5+CJ8Gb4KX4dvwrfhu/B9+CH8GH4KP4dfwq/ht/B7+CP8Gf4Kf4d/wr/hvzBJlDRKFiWPUkQpo1RR6iguShOljdJF6aMMUcYoU5Q5yhLFR1mjbFH2KEeUM8oV5Y7yRHmjfFH+qEBUMCoUFY6KREWjYlHxqERUMioVlY7KRGWjclH5qEJUMaoUVY6qRFWjalH1qEZUM6oV1Y7qRHWjelH9qEHUMGoUNY6aRE2jZlFC1DxqEbWMWkWtozZR26hd1D7qEHWMOkWdoy5R16hb1D3qEfWMekW9oz5R36hf1D8aEA2MBkWDoyHR0GhYNDwaEY2MRkWjozHR2GhcND6aEE2MJkWToynR1GhaND2aEc2MZkWzoznR3GheND9aEC2MFkWLoyXR0mhZtDxaEa2MVkWrozXR2igxWhetjzZEG6NN0eZoS7Q12hZtj3ZEO6Nd0e5oT7Q32hftjw5EB6ND0eH/7J0LXBRV3/i3okRDRVkUYYEFFlhguS8CioqKioqGt8REJdOkIiNDRUPDvERpikVGRoZpSqZJRnlDo8KiosKipNy5z+5cFylmlbn/dyQezXqe93nv//d93e/nzPzO/Xfu58zugO2g7W3bIdthW53tHdsR27u2o7Zjtvdsx231tvdtJ2wf2BpsH9o+sp20nbKdtp2xnbU12s7Zzts+tjXZPrF9avvM1my7YPvc9oWtxfal7Svb17ZW2ze2b23f2dpsF23f236wtdt+tP1ku2TrsP1s+8V22WazATbQBtlgG2JDbZgNt9ltDhthI22UjbYxNtbmtHXarti6bL/afrN12ziby3bVds3WY+Ntgk20STbZpthUmw64A7gTuAvwAO4G7gH6AZ5Af2AAcC/gBQwEBgGDAW9gCDAU8AH0gC8wDBgO+AEjAH8gADAAgUAQEAwYgRAgFAgDTEA4EAFEAmYgCogGYgALEAvEAfFAApAIJAHJgBVIAUYCqUAakA6MAkYDGcAYYCwwDsgExgMTgIlAFjAJmAxMAbKBqcA0YDqQA8wAZgL3AbnALGA2MAeYC8wD7gfmA3nAAuABYCGQDywCFgNLgALgQWAp8BCwDFgOPAysAAqBR4BHgceAIuBxYCXwBFAMPAmsAp4CSoDVwBpgLVAKrAPWA08DZcAGYCPwDFAObAKeBTYDW4CtwDbgOaACeB54AdgO7ABeBHYCu4BKYDfwEvAyUAW8AuwBXgWqgdeAvcDrQA3wBrAPeBOoBfYDbwEHgIPA28Ah4DBQB7wDHAHeBY4Cx4D3gONAPfA+cAL4AGgAPgQ+Ak4Cp4DTwBngLNAInAPOAx8DTcAnwKfAZ0AzcAH4HPgCaAG+BL4CvgZagW+Ab4HvgDbgIvA98APQDvwI/ARcAjqAn4FfgMuADQAAEIAAGEAAFMAAHLADDoAASIACaIABWMAJdAJXgC7gV+A3oBvgABdwFbgG9AA8IAAiIAEyoAAqoAPvAO8E7wI9wLvBe8B+oCfYHxwA3gt6gQPBQeBg0BscAg4FfUA96AsOA4eDfuAI0B8MAA1gIBgEBoNGMAQMBcNAExgORoCRoBmMAqPBGNACxoJxYDyYACaCSWAyaAVTwJFgKpgGpoOjwNFgBjgGHAuOAzPB8eAEcCKYBU4CJ4NTwGxwKjgNnA7mgDPAmeB9YC44C5wNzgHngvPA+8H5YB64AHwAXAjmg4vAxeASsAB8EFwKPgQuA5eDD4MrwELwEfBR8DGwCHwcXAk+ARaDT4KrwKfAEnA1uAZcC5aC68D14NNgGbgB3Ag+A5aDm8Bnwc3gFnAruA18DqwAnwdfALeDO8AXwZ3gLrAS3A2+BL4MVoGvgHvAV8Fq8DVwL/g6WAO+Ae4D3wRrwf3gW+AB8CD4NngIPAzWge+AR8B3waPgMfA98DhYD74PngA/ABvAD8GPwJPgKfA0eAY8CzaC58Dz4MdgE/gJ+Cn4GdgMXgA/B78AW8Avwa/Ar8FW8BvwW/A7sA28CH4P/gC2gz+CP4GXwA7wZ/AX8DJoAwEQBCEQBhEQBTEQB+2gAyRAEqRAGmRAFnSCneAVsAv8FfwN7AY50AVeBa+BPSAPCqAISqAMKqAK6qA7oDuhuyAP6G7oHqgf5An1hwZA90Je0EBoEDQY8oaGQEMhH0gP+ULDoOGQHzQC8ocCIAMUCAVBwZARCoFCoTDIBIVDEVAkZIaioGgoBrJAsVAcFA8lQIlQEpQMWaEUaCSUCqVB6dAoaDSUAY2BxkLjoExoPDQBmghlQZOgydAUKBuaCk2DpkM50AxoJnQflAvNgmZDc6C50Dzofmg+lActgB6AFkL50CJoMbQEKoAehJZCD0HLoOXQw9AKqBB6BHoUegwqgh6HVkJPQMXQk9Aq6CmoBFoNrYHWQqXQOmg99DRUBm2ANkLPQOXQJuhZaDO0BdoKbYOegyqg56EXoO3QDuhFaCe0C6qEdkMvQS9DVdAr0B7oVagaeg3aC70O1UBvQPugN6FaaD/0FnQAOgi9DR2CDkN10DvQEehd6Ch0DHoPOg7VQ+9DJ6APoAboQ+gj6CR0CjoNnYHOQo3QOeg89DHUBH0CfQp9BjVDF6DPoS+gFuhL6Cvoa6gV+gb6FvoOaoMuQt9DP0Dt0I/QT9AlqAP6GfoFugzZIAACIQiCIQRCIQzCITvkgAiIhCiIhhiIhZxQJ3QF6oJ+hX6DuiEOckFXoWtQD8RDAiRCEiRDCqRCOvgO+E74LtgDvhu+B+4He8L94QHwvbAXPBAeBA+GveEh8FDYB9bDvvAweDjsB4+A/eEA2AAHwkFwMGyEQ+BQOAw2weFwBBwJm+EoOBqOgS1wLBwHx8MJcCKcBCfDVjgFHgmnwmlwOjwKHg1nwGPgsfA4OBMeD0+AJ8JZ8CR4MjwFzoanwtPg6XAOPAOeCd8H58Kz4NnwHHguPA++H54P58EL4AfghXA+vAheDC+BC+AH4aXwQ/AyeDn8MLwCLoQfgR+FH4OL4MfhlfATcDH8JLwKfgougVfDa+C1cCm8Dl4PPw2XwRvgjfAzcDm8CX4W3gxvgbfC2+Dn4Ar4efgFeDu8A34R3gnvgivh3fBL8MtwFfwKvAd+Fa6GX4P3wq/DNfAb8D74TbgW3g+/BR+AD8Jvw4fgw3Ad/A58BH4XPgofg9+Dj8P18PvwCfgDuAH+EP4IPgmfgk/DZ+CzcCN8Dj4Pfww3wZ/An8Kfwc3wBfhz+Au4Bf4S/gr+Gm6Fv4G/hb+D2+CL8PfwD3A7/CP8E3wJ7oB/hn+BL8M2GIBBGIJhGIFRGINx2A47YAImYQqmYQZmYSfcCV+Bu+Bf4d/gbpiDXfBV+BrcA/OwAIuwBMuwAquwDrkDuRO5C/FA7kbuQfohnkh/ZAByL+KFDEQGIYMRb2QIMhTxQfSILzIMGY74ISMQfyQAMSCBSBASjBiRECQUCUNMSDgSgUQiZiQKiUZiEAsSi8Qh8UgCkogkIcmIFUlBRiKpSBqSjoxCRiMZyBhkLDIOyUTGIxOQiUgWMgmZjExBspGpyDRkOpKDzEBmIvchucgsZDYyB5mLzEPuR+YjecgC5AFkIZKPLEIWI0uQAuRBZCnyELIMWY48jKxACpFHkEeRx5Ai5HFkJfIEUow8iaxCnkJKkNXIGmQtUoqsQ9YjTyNlyAZkI/IMUo5sQp5FNiNbkK3INuQ5pAJ5HnkB2Y7sQF5EdiK7kEpkN/IS8jJShbyC7EFeRaqR15C9yOtIDfIGsg95E6lF9iNvIQeQg8jbyCHkMFKHvIMcQd5FjiLHkPeQ40g98j5yAvkAaUA+RD5CTiKnkNPIGeQs0oicQ84jHyNNyCfIp8hnSDNyAfkc+QJpQb5EvkK+RlqRb5Bvke+QNuQi8j3yA9KO/Ij8hFxCOpCfkV+Qy4gNARAQgRAYQRAUwRAcsSMOhEBIhEJohEFYxIl0IleQLuRX5DekG+EQF3IVuYb0IDwiICIiITKiICqiQ+9A70TvQj3Qu9F70H6oJ9ofHYDei3qhA9FB6GDUGx2CDkV9UD3qiw5Dh6N+6AjUHw1ADWggGoQGo0Y0BA1Fw1ATGo5GoJGoGY1Co9EY1ILGonFoPJqAJqJJaDJqRVPQkWgqmoamo6PQ0WgGOgYdi45DM9Hx6AR0IpqFTkIno1PQbHQqOg2djuagM9CZ6H1oLjoLnY3OQeei89D70floHroAfQBdiOaji9DF6BK0AH0QXYo+hC5Dl6MPoyvQQvQR9FH0MbQIfRxdiT6BFqNPoqvQp9ASdDW6Bl2LlqLr0PXo02gZugHdiD6DlqOb0GfRzegWdCu6DX0OrUCfR19At6M70BfRnegutBLdjb6EvoxWoa+ge9BX0Wr0NXQv+jpag76B7kPfRGvR/ehb6AH0IPo2egg9jNah76BH0HfRo+gx9D30OFqPvo+eQD9AG9AP0Y/Qk+gp9DR6Bj2LNqLn0PPox2gT+gn6KfoZ2oxeQD9Hv0Bb0C/Rr9Cv0Vb0G/Rb9Du0Db2Ifo/+gLajP6I/oZfQDvRn9Bf0MmpDARREIRRGERRFMRRH7agDJVASpVAaZVAWdaKd6BW0C/0V/Q3tRjnUhV5Fr6E9KI8KqIhKqIwqqIrqsDuwO7G7MA/sbuwerB/mifXHBmD3Yl7YQGwQNhjzxoZgQzEfTI/5YsOw4ZgfNgLzxwIwAxaIBWHBmBELwUKxMMyEhWMRWCRmxqKwaCwGs2CxWBwWjyVgiVgSloxZsRRsJJaKpWHp2ChsNJaBjcHGYuOwTGw8NgGbiGVhk7DJ2BQsG5uKTcOmYznYDGwmdh+Wi83CZmNzsLnYPOx+bD6Why3AHsAWYvnYImwxtgQrwB7ElmIPYcuw5djD2AqsEHsEexR7DCvCHsdWYk9gxdiT2CrsKawEW42twdZipdg6bD32NFaGbcA2Ys9g5dgm7FlsM7YF24ptw57DKrDnsRew7dgO7EVsJ7YLq8R2Yy9hL2NV2CvYHuxVrBp7DduLvY7VYG9g+7A3sVpsP/YWdgA7iL2NHcIOY3XYO9gR7F3sKHYMew87jtVj72MnsA+wBuxD7CPsJHYKO42dwc5ijdg57Dz2MdaEfYJ9in2GNWMXsM+xL7AW7EvsK+xrrBX7BvsW+w5rwy5i32M/YO3Yj9hP2CWsA/sZ+wW7jNkwAAMxCIMxBEMxDMMxO+bACIzEKIzGGIzFnFgndgXrwn7FfsO6MQ5zYVexa1gPxmMCJmISJmMKpmI6/A78Tvwu3AO/G78H74d74v3xAfi9uBc+EB+ED8a98SH4UNwH1+O++DB8OO6Hj8D98QDcgAfiQXgwbsRD8FA8DDfh4XgEHomb8Sg8Go/BLXgsHofH4wl4Ip6EJ+NWPAUfiafiaXg6PgofjWfgY/Cx+Dg8Ex+PT8An4ln4JHwyPgXPxqfi0/DpeA4+A5+J34fn4rPw2fgcfC4+D78fn4/n4QvwB/CFeD6+CF+ML8EL8AfxpfhD+DJ8Of4wvgIvxB/BH8Ufw4vwx/GV+BN4Mf4kvgp/Ci/BV+Nr8LV4Kb4OX48/jZfhG/CN+DN4Ob4JfxbfjG/Bt+Lb8OfwCvx5/AV8O74DfxHfie/CK/Hd+Ev4y3gV/gq+B38Vr8Zfw/fir+M1+Bv4PvxNvBbfj7+FH8AP4m/jh/DDeB3+Dn4Efxc/ih/D38OP4/X4+/gJ/AO8Af8Q/wg/iZ/CT+Nn8LN4I34OP49/jDfhn+Cf4p/hzfgF/HP8S/wb/Fv8J/xn3IYDOI47cAIn8U78Cn4V78F5XMXvsN9pv9s+wD7QPtg+1K63D7P72w32QHuQPdhutIfYTXazPcoebY+xW+xx9nh7qn2sfaJ9un2ufZ59vj3PvsC+0J5vX2xfYl9qf9i+wv64faW92L7K/pR9tX2Nfa19nX29vcy+wb7RXm5/1r7ZvsW+1b7NXmHfbt9hf9G+077LXml/yf6yvcq+1/6GfZ/9TXutfb/9oP2Q/bC9zn7Eftz+vv2E/UP7Sfsp+xn7Wft5+8f2Jvun9hb7l/ZL9g77z/bLdpsdsiN21I7Z7XaHnbJ32q/Yu+y/2rvtol2y6xx3Ojwcgx3ejiGOoY4RDn9HgMPgCHGEOUyOSEeMI8mR7LA6Uh1pjlGODMc4R6ZjvGOCY5JjsiPbMd0x03GfY7ZjjmOuY55jviPPscCxyLHYscRR4FjqeMix3PGwY4Wj0PGoY6XjCceTjjWOtY5SxzrH044yxwbHM45yx2bHFsdWxzbHc44KxwuO7Y4djp2OXY5Kx0uOPY5XHa859jpqHPscbzr2O95yHHIcdRxznHCcdpxxnHOcdzQ5PnFccHzh+Mpx0fG945Kjw/GL47IDcIAOyAE7EAfusDscjk7Hb45uxzWH4BAdkkN13EHcSdxD9CP6EwMIL8KbGEL4EMMJP8KfCCACCRMRTsQQ8UQyYSVSiJFEKpFBjCEyifHEBCKLmELMIGYS9xGziNnEQiKfWEQsIR4klhLLiOXECqKQeIQoIh4nVhLFxGpiLVFKrCfKiA3EFmIb8TyxnXiR2EnsIiqJ3cRLxMtEFfEKsYd4lagmXiP2Eq8TNcQbxD7iTaKW2E+8RRwgDhJvE4eIw0Qd8Q5xhHiXOEocI94jjhP1xPvECeIDooH4kPiIOEmcIk4TZ4izRCNxjjhPfEw0EZ8QnxKfEc3EBeJz4guihfiS+Ir4mmglviG+Jb4j2oiLxPfED0Q78SPxE3GJ6CB+Jn4hLhM2AiBAAiJgAiFQAiNwwk44CIIgCYqgCYZgCSfRSVwhuohfid+IboIjXMRV4hrRQ/CEQIiERMiEQqiEjryDvJO8i/Qg7ybvIfuRnmR/cgB5L+lFDiQHkYNJb3IIOZT0IfWkLzmMHE76kSNIfzKANJCBZBAZTBrJEDKUDCNNZDgZQUaSZjKKjCZjSAsZS8aR8WQCmUgmkcmklUwhR5KpZBqZTo4iR5MZ5BhyLDmOzCTHkxPIiWQWOYmcTE4hs8mp5DRyOplDziBnkveRueQscjY5h5xLziPvJ+eTeeQC8gFyIZlPLiIXk0vIAvJBcin5ELmMXE4+TK4gC8lHyEfJx8gi8nFyJfkEWUw+Sa4inyJLyNXkGnItWUquI9eTT5Nl5AZyI/kMWU5uIp8lN5NbyK3kNvI5soJ8nnyB3E7uIF8kd5K7yEpyN/kS+TJZRb5C7iFfJavJ18i95OtkDfkGuY98k6wl95NvkQfIg+Tb5CHyMFlHvkMeId8lj5LHyPfI42Q9+T55gvyAbCA/JD8iT5KnyNPkGfIs2UieI8+TH5NN5Cfkp+RnZDN5gfyc/IJsIb8kvyK/JlvJb8hvye/INvIi+T35A9lO/kj+RF4iO8ifyV/Iy6SNBEiQhEiYREiUxEictJMOkiBJkiJpkiFZ0kl2klfILvJX8jeym+RIF3mVvEb2kDwpkCIpkTKpkCqpo+6g7qTuojyou6l7qH6UJ9WfGkDdS3lRA6lB1GDKmxpCDaV8KD3lSw2jhlN+1AjKnwqgDFQgFUQFU0YqhAqlwigTFU5FUJGUmYqioqkYykLFUnFUPJVAJVJJVDJlpVKokVQqlUalU6Oo0VQGNYYaS42jMqnx1ARqIpVFTaImU1OobGoqNY2aTuVQM6iZ1H1ULjWLmk3NoeZS86j7qflUHrWAeoBaSOVTi6jF1BKqgHqQWko9RC2jllMPUyuoQuoR6lHqMaqIepxaST1BFVNPUquop6gSajW1hlpLlVLrqPXU01QZtYHaSD1DlVObqGepzdQWaiu1jXqOqqCep16gtlM7qBepndQuqpLaTb1EvUxVUa9Qe6hXqWrqNWov9TpVQ71B7aPepGqp/dRb1AHqIPU2dYg6TNVR71BHqHepo9Qx6j3qOFVPvU+doD6gGqgPqY+ok9Qp6jR1hjpLNVLnqPPUx1QT9Qn1KfUZ1UxdoD6nvqBaqC+pr6ivqVbqG+pb6juqjbpIfU/9QLVTP1I/UZeoDupn6hfqMmWjAAqkIAqmEAqlMAqn7JSDIiiSoiiaYiiWclKd1BWqi/qV+o3qpjjKRV2lrlE9FE8JlEhJlEwplErp6DvoO+m7aA/6bvoeuh/tSfenB9D30l70QHoQPZj2pofQQ2kfWk/70sPo4bQfPYL2pwNoAx1IB9HBtJEOoUPpMNpEh9MRdCRtpqPoaDqGttCxdBwdTyfQiXQSnUxb6RR6JJ1Kp9Hp9Ch6NJ1Bj6HH0uPoTHo8PYGeSGfRk+jJ9BQ6m55KT6On0zn0DHomfR+dS8+iZ9Nz6Ln0PPp+ej6dRy+gH6AX0vn0InoxvYQuoB+kl9IP0cvo5fTD9Aq6kH6EfpR+jC6iH6dX0k/QxfST9Cr6KbqEXk2vodfSpfQ6ej39NF1Gb6A30s/Q5fQm+ll6M72F3kpvo5+jK+jn6Rfo7fQO+kV6J72LrqR30y/RL9NV9Cv0HvpVupp+jd5Lv07X0G/Q++g36Vp6P/0WfYA+SL9NH6IP03X0O/QR+l36KH2Mfo8+TtfT79Mn6A/oBvpD+iP6JH2KPk2foc/SjfQ5+jz9Md1Ef0J/Sn9GN9MX6M/pL+gW+kv6K/prupX+hv6W/o5uoy/S39M/0O30j/RP9CW6g/6Z/oW+TNtogAZpiIZphEZpjMZpO+2gCZqkKZqmGZqlnXQnfYXuon+lf6O7aY520Vfpa3QPzdMCLdISLdMKrdI65g7mTuYuxoO5m7mH6cd4Mv2ZAcy9jBczkBnEDGa8mSHMUMaH0TO+zDBmOOPHjGD8mQDGwAQyQUwwY2RCmFAmjDEx4UwEE8mYmSgmmolhLEwsE8fEMwlMIpPEJDNWJoUZyaQyaUw6M4oZzWQwY5ixzDgmkxnPTGAmMlnMJGYyM4XJZqYy05jpTA4zg5nJ3MfkMrOY2cwcZi4zj7mfmc/kMQuYB5iFTD6ziFnMLGEKmAeZpcxDzDJmOfMws4IpZB5hHmUeY4qYx5mVzBNMMfMks4p5iilhVjNrmLVMKbOOWc88zZQxG5iNzDNMObOJeZbZzGxhtjLbmOeYCuZ55gVmO7ODeZHZyexiKpndzEvMy0wV8wqzh3mVqWZeY/YyrzM1zBvMPuZNppbZz7zFHGAOMm8zh5jDTB3zDnOEeZc5yhxj3mOOM/XM+8wJ5gOmgfmQ+Yg5yZxiTjNnmLNMI3OOOc98zDQxnzCfMp8xzcwF5nPmC6aF+ZL5ivmaaWW+Yb5lvmPamIvM98wPTDvzI/MTc4npYH5mfmEuMzYGYEAGYmAGYVAGY3DGzjgYgiEZiqEZhmEZJ9PJXGG6mF+Z35huhmNczFXmGtPD8IzAiIzEyIzCqIyOvYO9k72L9WDvZu9h+7GebH92AHsv68UOZAexg1lvdgg7lPVh9awvO4wdzvqxI1h/NoA1sIFsEBvMGtkQNpQNY01sOBvBRrJmNoqNZmNYCxvLxrHxbAKbyCaxyayVTWFHsqlsGpvOjmJHsxnsGHYsO47NZMezE9iJbBY7iZ3MTmGz2ansNHY6m8POYGey97G57Cx2NjuHncvOY+9n57N57AL2AXYhm88uYhezS9gC9kF2KfsQu4xdzj7MrmAL2UfYR9nH2CL2cXYl+wRbzD7JrmKfYkvY1ewadi1byq5j17NPs2XsBnYj+wxbzm5in2U3s1vYrew29jm2gn2efYHdzu5gX2R3srvYSnY3+xL7MlvFvsLuYavZ19i97OvsG+w+tpY9wB5kD7N17LvsMfY428B+xJ5mz7Bn2e/YdvYya2NBFmJhFmHtbBf7G+tiJdbD2c85wOnlHOgc5Bzs9HYOcfo4fZ3DnMOdfk5/p8EZ6AxyhjpNznBnhDPSGeWMdlqcsc7RzjHO8c4JzknOKc5pzunOGc6Zzvucs5yznXOcc53znXnOJc6lzsecTzpXOVc71zpLneudm5xbnFud25wVzuedLzi3O3c6dzsPOT93fue86Lzk/MV52Qk4EafT6dk5pNO3M6DT2BnaGd2Z0JnYae3M7ry/c2Hnos6CzmWdj3au6Szr3Ni5u7Om863OA50HO9/uPNR5uLOu853OI51HO491vtd5vLO+8/3Ohs6TnXd1e3Tf3X1Pd79uz+7+3QO67+326h7YPah7cLd395Duod0+3fpu3+5h3cO7/brDuyO7s7ond0/rnt5d272/+2h3VzffLXRL3Z5cf24Ady83hsvkxnMTuCxuMpfNTeWmczO4XG4WN5uby83j7ufmcw9wC7l8bhG3mFvCPcgt5R7ilnMPc49wRdzj3EruCa6EW8uVcuu4p7kybgO3kSvnNnGbuS3cVq6C2869yO3kdnGV3G7uVa6ae53bxx3k3uYOcYe5d7gj3DHuOFfPneA+4Bq4k9wZ7izXyJ3jznMfc03cJ9xnXDN3gfuCa+G+5L7iWrlvuG+577iL3PfcD1w79yN3ifuZ+4W7zNk4gAM5iIM5lMM4nLNzDo7gSI7irnC/cd1cDydxCqdyOtcdrrtcd7v6uTxd/V0DXPe6vFwDXYNcg13eriEuH5fe5esa5vJzjXD5uwJcBlegK9hldIW4Ql1hLpMr3BXhinYlu6yuUa7RrjGuma45rvtdC1wPuBa7lrsec61yrXOtd21wbXJtdm11bXftcO10veza43rdVeOqdR1wHXS966p3Nbg+cp12nXM1uZpdF1ytrm9dba4fXT+5Lrlwl8NFumgX42JdTtcVV9XVfVePXa2/ar/muEZeo68x15zXOq/p+Dv4O/m7eA/+bv4evh/vyffnB/D38l78QH4QP5j35ofwQ3kfXs/78sP44bwfP4L35wN4Ax/IB/HBvJEP4UP5MN7Eh/MRfCRv5qP4aD6Gt/CxfBwfzyfwiXwSn8xb+RR+JJ/Kp/Hp/Ch+NJ/Bj+HH8uP4TH48P4GfyGfxk/jJ/BQ+m5/KT+On8zn8DH4mfx+fy8/iZ/Nz+Ln8PP5+fj6fxy/gH+AX8vn8In4xv4Qv4B/kl/IP8cv45fzD/Aq+kH+Ef5R/jC/iH+dX8k/wxfyT/Cr+Kb6EX82v4dfypfw6fj3/NF/Gb+A38s/w5fwm/ll+M7+F38pv45/jK/jn+Rf47fwO/kV+J7+Lr+R38y/xL/NV/Cv8Hv5Vvpp/jd/Lv87X8G/w+/g3+Vp+P/8Wf4A/yL/NH+IP83X8O/wR/l3+KH+Mf48/ztfz7/Mn+A/4Bv5D/iP+JH+KP82f4c/yjfw5/jz/Md/Ef8J/yn/GN/MX+M/5L/gW/kv+K/5rvpX/hv+W/45v4y/y3/M/8O38j/xP/CW+g/+Z/4W/zNt4gAd5iId5hEd5jMd5O+/gCZ7kKZ7mGZ7lnXwnf4Xv4n/lf+O7eY538Vf5a3wPz/MCL/ISL/MKr/I64Q7hTuEuwUO4W7hH6Cd4Cv2FAcK9gpcwUBgkDBa8hSHCUMFH0Au+wjBhuOAnjBD8hQDBIAQKQUKwYBRChFAhTDAJ4UKEECmYhSghWogRLEKsECfECwlCopAkJAtWIUUYKaQKaUK6MEoYLWQIY4SxwjghUxgvTBAmClnCJGGyMEXIFqYK04TpQo4wQ5gp3CfkCrOE2cIcYa4wT7hfmC/kCQuEB4SFQr6wSFgsLBEKhAeFpcJDwjJhufCwsEIoFB4RHhUeE4qEx4WVwhNCsfCksEp4SigRVgtrhLVCqbBOWC88LZQJG4SNwjNCubBJeFbYLGwRtgrbhOeECuF54QVhu7BDeFHYKewSKoXdwkvCy0KV8IqwR3hVqBZeE/YKrws1whvCPuFNoVbYL7wlHBAOCm8Lh4TDQp3wjnBEeFc4KhwT3hOOC/XC+8IJ4QOhQfhQ+Eg4KZwSTgtnhLNCo3BOOC98LDQJnwifCp8JzcIF4XPhC6FF+FL4SvhaaBW+Eb4VvhPahIvC98IPQrvwo/CTcEnoEH4WfhEuCzYBEEABEmABEVABE3DBLjgEQiAFSqAFRmAFp9ApXBG6hF+F34RugRNcwlXhmtAj8IIgiIIkyIIiqIKPqBd9xWHicDFQDBKDRaMYIoaKYaJJDBcjxEjRLEaJ0WKMaBFjxTgxXkwQE8UkMVm0iiniSDFVTBPTxVHiaDFDHCOOFceJmeJ4cYI4UcwSJ4mTxSlitjhVnCZOF3PEGeJM8T4xV5wlzhbniHPFeeL94nwxT1wgPiAuFPPFReJicYlYID4oLhUfEpeJy8WHxRViofiI+Kj4mFgkPi6uFJ8Qi8UnxVXiU2KJuFpcI64VS8V14nrxabFM3CBuFJ8Ry8VN4rPiZnGLuFXcJj4nVojPiy+I28Ud4oviTnGXWCnuFl8SXxarxFfEPeKrYrX4mrhXfF2sEd8Q94lvirXifvEt8YB4UHxbPCQeFuvEd8Qj4rviUfGY+J54XKwX3xdPiB+IDeKH4kfiSfGUeFo8I54VG8Vz4nnxY7FJ/ET8VPxMbBYviJ+LX4gt4pfiV+LXYqv4jfit+J3YJl4Uvxd/ENvFH8WfxEtih/iz+It4WbSJgAiKkAiLiIiKmIiLdtEhEiIpUiItMiIrOsVO8YrYJf4q/iZ2i5zoEq+K18QekRcFURQlURYVURV10h3SndJdkod0t3SP1E/ylPpLA6R7JS9poDRIGix5S0OkoZKPpJd8pWHScMlPGiH5SwGSQQqUgqRgySiFSKFSmGSSwqUIKVIyS1FStBQjWaRYKU6KlxKkRClJSpasUoo0UkqV0qR0aZQ0WsqQxkhjpXFSpjRemiBNlLKkSdJkaYqULU2VpknTpRxphjRTuk/KlWZJs6U50lxpnnS/NF/KkxZID0gLpXxpkbRYWiIVSA9KS6WHpGXSculhaYVUKD0iPSo9JhVJj0srpSekYulJaZX0lFQirZbWSGulUmmdtF56WiqTNkgbpWekcmmT9Ky0WdoibZW2Sc9JFdLz0gvSdmmH9KK0U9olVUq7pZekl6Uq6RVpj/SqVC29Ju2VXpdqpDekfdKbUq20X3pLOiAdlN6WDkmHpTrpHemI9K50VDomvScdl+ql96UT0gdSg/Sh9JF0UjolnZbOSGelRumcdF76WGqSPpE+lT6TmqUL0ufSF1KL9KX0lfS11Cp9I30rfSe1SRel76UfpHbpR+kn6ZLUIf0s/SJdlmwSIIESJMESIqESJuGSXXJIhERKlERLjMRKTqlTuiJ1Sb9Kv0ndEie5pKvSNalH4iVBEiVJkiVFUiWdfId8p3yX7CHfLd8j95M95f7yAPle2UseKA+SB8ve8hB5qOwj62VfeZg8XPaTR8j+coBskAPlIDlYNsohcqgcJpvkcDlCjpTNcpQcLcfIFjlWjpPj5QQ5UU6Sk2WrnCKPlFPlNDldHiWPljPkMfJYeZycKY+XJ8gT5Sx5kjxZniJny1PlafJ0OUeeIc+U75Nz5VnybHmOPFeeJ98vz5fz5AXyA/JCOV9eJC+Wl8gF8oPyUvkheZm8XH5YXiEXyo/Ij8qPyUXy4/JK+Qm5WH5SXiU/JZfIq+U18lq5VF4nr5eflsvkDfJG+Rm5XN4kPytvlrfIW+Vt8nNyhfy8/IK8Xd4hvyjvlHfJlfJu+SX5ZblKfkXeI78qV8uvyXvl1+Ua+Q15n/ymXCvvl9+SD8gH5bflQ/JhuU5+Rz4ivysflY/J78nH5Xr5ffmE/IHcIH8ofySflE/Jp+Uz8lm5UT4nn5c/lpvkT+RP5c/kZvmC/Ln8hdwifyl/JX8tt8rfyN/K38lt8kX5e/kHuV3+Uf5JviR3yD/Lv8iXZZsMyKAMybCMyKiMybhslx0yIZMyJdMyI7OyU+6Ur8hd8q/yb3K3zMku+ap8Te6ReVmQRVmSZVmRVTlBSVSSlGTFqqQoI5VUJU1JV0Ypo5UMZYwyVhmnZCrjlQnKRCVLmaRMVqYo2cpUZZoyXclRZigzlfuUXGWWMluZo8xV5in3K/OVPGWB8oCyUMlXFimLlSVKgfKgslR5SFmmLFceVlYohcojyqPKY0qx8qSySnlKKVFWK2uUtUqpsk5ZrzytlCkblI3KM0q5skl5VtmsbFG2KtuU55QK5XnlBWW7skN5Udmp7FIqld3KS8rLSpXyirJHeVWpVl5T9iqvKzXKG8o+5U2lVtmvvKUcUA4qbyuHlMNKnfKOckR5VzmqHFPeU44r9cr7ygnlA6VB+VD5SDmpnFJOK2eUs0qjck45r3ysNCmfKJ8qnynNygXlc+ULpUX5UvlK+VppVb5RvlW+U9qUi8r3yg9Ku/Kj8pNySelQflZ+US4rNgVQQAVSYAVRUAVTcMWuOBRCIRVKoRVGYRWn0qlcUbqUX5XflG6FU1zKVeWa0qPwiqCIiqTIiqKoik69Q71TvUv1UO9W71H7qZ5qf3WAeq/qpQ5UB6mDVW91iDpU9VH1qq86TB2u+qkjVH81QDWogWqQGqwa1RA1VA1TTWq4GqFGqmY1So1WY1SLGqvGqfFqgpqoJqnJqlVNUUeqqWqamq6OUkerGeoYdaw6Ts1Ux6sT1IlqljpJnaxOUbPVqeo0dbqao85QZ6r3qbnqLHW2Okedq85T71fnq3nqAvUBdaGary5SF6tL1AL1QXWp+pC6TF2uPqyuUAvVR9RH1cfUIvVxdaX6hFqsPqmuUp9SS9TV6hp1rVqqrlPXq0+rZeoGdaP6jFqublKfVTerW9St6jb1ObVCfV59Qd2u7lBfVHequ9RKdbf6kvqyWqW+ou5RX1Wr1dfUverrao36hrpPfVOtVferb6kH1IPq2+oh9bBap76jHlHfVY+qx9T31ONqvfq+ekL9QG1QP1Q/Uk+qp9TT6hn1rNqonlPPqx+rTeon6qfqZ2qzekH9XP1CbVG/VL9Sv1Zb1W/Ub9Xv1Db1ovq9+oParv6o/qReUjvUn9Vf1MuqTQVUUIVUWEVUVMVUXLWrDpVQSZVSaZVRWdWpdqpX1C71V/U3tVvlVJd6Vb2m9qi8KqiiKqnwFK+BrIfO/O9DGm7Wtxk90nYkdY1vSC0eWhCqYUkuHlpnLB6qM7emtfonxLcnGFOKE+Ymc3HLkuYmp/mk+ViSNRqji2daxzWme4+uGludUm5tHNuSwfmSMQnpFYklk6zjeiYWp/RMbEu3JMPJLRm6DGNeY3pWuj61IFRn1kxPvM7cFdtmbXCbU3GSoc3qncj6sD7NFtbHL8c70aL9ORyrp7E50tPonVgZR2bVxnrG51iKI/BhxRGtJncJ/p0frfxlcWXJVekdI3XmHUk6c+EES7AlSmeuMxZO0Jk9TJqOGu6yRGg1ojP3+ms0RlvH3aB6jvfo6pReON9e2EytFvrQUmnJ6CUrvT2lJrEr9gZzcxq0fwV8Ha0WNDKStFrow513sndiL57x7pqJ//e2/78M6/OP/bnker9/HCIhv2Du3/OzJDdH/mu0yUrvk/SpOZZ/Lk7pf3IN3eY2/37I4X38q+L97/j8m2os7V+Ymf5t4On/TChtLtfQ1ojb3OZ/K5xvdUJmVInFGlMWhYcXmkrDOhK9LVXhNaEH4yoseLRfcH5EdozZrE9qDzFEu0PE2cLqLTWRGUmFcRmxc4OrI9jQFnO9e6VeFusXpe2ItOHeNbhtSKa3cWiaD+dbkJgTWBl8NKTI6BGcbzgaUhfeZjwacnSoId4cVBzSFNLjthlDSkJLB+PGtoCjIZ7DChKrDY1G0u3XlHA0JDfIOrwpAQ4uDfIMl0I4X6+BOl3f7kvDEP4fi6Z/r5TpbQg3DdKkvCHaFXbndXPOGuXhtWGZ/uXG8nCdHnbbtLvbpuGWYd9et/LwglBjiHtHHJYZXBZVHn5zfI3awbD/rSn30prWsbgnOyP1j64dgTp3k2jtd7PmN/ybhvZem0M535YRNYNqBpX51wzSmWsG1VsKfOot9RYyRCPTN9M3Nyg3qCy5LNmYZczKNGWavEO9Q2+ktGVgQWKhyV2S4Exfdwl8yvxvzfUf4T4rhPwZnfmUd9PQHL96S6HJEK5p59ZNV+FOu8wfj9a0u5k/xtU0/iOa/n9EK01febxDCxJvUGjScsydbAjvrfebdYWDezGG/A0D6S5xL5puN6Mzl8W5zfXa2JLiZmCBzx/Lbp7cNvGv+tWN2tN0/6v60XT3Dm0Z4a5xw6lg48BeanyqhvTSM6zSpAvSB2ljzT0WA83m8uzybL370xF50L9jkDGkMK4wLntgdkqetdxYFd5i9gz3DM+NbY4sibS6R5JenxddE6rF0utrAv8taD3DanCn9xdt1dsmZclaP+qt/b7Saj1IAw7ubaW/7vF/xGA0xOuTctxpe7p1NoaU+TcEdQXh4U0h3qE5ocvMOZn6Edkh9ZbG6K6gQpN7xghxxzDi4TmWnEwNzUXLMye0zN/D9Fe42/AffP4ZHW/zP5f/7vX3X16fG8Mbw8vSuDgurmcsbsSNBaHtMdaU9pi+/tszthcuTp8ERzWYS0KzorXQbGJWdEloVThuLAn1SmAjNVtWdIO5wexh4uI8TO0x7TENZvdgMbTHaOE9TE0xmitu1OqlMbzJkJ9SlpafouV/M/kpvTReX29KRve5/16j17Xg4rRcubgGs6ap5qsbcco0N/jP9K5Ut6KlUBCKG92a+laackbnjHavY7GG9GKDe/6OLo6p+z2/nFBdrHYvDy+NrYrODdMgI7qCcsMKowzRGbFdQVb3rqUrKMEIR+WGWYI1f843N6zRHTbv9/CavTfXXnuxQZMrTcUGT2thcmFypakXzbU21Zqi3f2m+E2pNPUYb9Xb09onablqKZa7Ne2LbQo1GCsC89w+ptDimIpAOK4xXMuxLtwvqi68xNIT3xWUE5oX0BN/c5pa7dW7y98e05ZuTDAmlEWVRfX5dbj7gnYvi2qP6Yg86t6p5UVz7hrKNWdGaWj3XHOumTNp11zz0Qi37Hs0gjN1ud1yIvOi3bJvXrQ7lq9md9dopOai5eo21uvcaFvfPvkPLX4LmhZarlqKf/T5q7VOS6cj1L33nPH3RqgW4pR7rSgZWT+pPUIf2x5RMhK3eiSXjNTcNFfOt35S/aS0UGuCNUEfq931sfpYzZYWqtEe0eviFaFdOd/eML1uae69jiZrrr2khfbm2hPQMdKc1DHyRs/v1UXrAfkp1t/7v/fofzy/zE3O+1sNtkf8Gc63IfUfp7Alxm8MOY7zNUZ0JOrM3pH5EV4RNZHGEM2vOmLH9f7fY5wb1RheE1kT2R5RFpVpygg7ZWp0r/kHTV4ReeFF4WTEQVOZuxe2R8DuNqmIbLZwpgp3WJ3Z6tYg170/cPdpU094U4Q1Qh/Wm+sWQ23qlhhdhlty06tLVXZVtnavn1s/t8/tZk1r/1aWvOu7vwyzV4RXSJ9bi/nPnDJV/WkU3Yp1nLu3+vZM9JtlHr8sKS2zdVave0liSSKezvnaxtvGV25s+33UGMZWWNwtNMrdNtNaftfHkG9O6pWaLR5Tciy9Mp7elZEVXjNy7gSvcXXpnhPNkzvmNi0qe/RvPW82l9YQWzq9dkmvfdmStvy21Zxv0ZaOTcX7GmL/rGlT0T8qR0doW3xLqj7VL9k0yTCjJLFnYun0/FE7Uv0m5Iy25ZZv6bFmzS5YWz6RG3NzLO+RByd4ufsnHp1mKYxKsBZGVYzMzMlw594WnhNZ6J4LCqPcxHmF6GK9QqzjrtvcZOa0JhdGeYX02fv4Pbwb67jMHK+Q7JjCKK1X9IVtGtWXc1eq1nPZ0VkzKtMyJt8Y9dq13Hrr+P/rGaFpUdO4PtkrJC20IjIvoNWUYTaHsYHuXVron2P8Gf1kvbsdT0Vp7Ej1GmfJycg4FdXn0neXQrSV5mBcr+1UlGVCccop96jos/fRF/5UlC7DMqHXX2/WXPvC9pamI7BhepZVP31ZasN0Ywo8QetvWdmFU9ztPz9jZfZUy5g/arkjo/6WuUBLyTzdktZnPxj1Z/6Z8s/NKcjkfLPzMgvgKXhxltW0uD4zP4vzTVtQsKBhgzbHtMxLeNBrXP2krlTzvINjmrI6Fhck1i6pnlMaVmFJm2bO3ZHbk96anGGuGVnjnjULJjVP4mbBcdkJPRNrk3RJWeleCaVJpmmm0fWTyKnNC/ryzZqROaE2g83Mn1qWc328zO6ZYVnH+UprvFdlPJsQ/2dNt+Td6lKf2RtXwxx2dJQ0s3byjiQurnY6l9w+dcu4vy7xHylNbUpx5xpisHYldSVlmozuNb1nbHm6X069pW5ipqkgMiG7ILIgsnHs730uQbNp5MdoJ9pMU93E6lG6JL25KLzXnR1dEFkeXRBpG1EQ2eQeW+7TrUlLpw9tdi3X1kRfzbXXRwvfm35t2N96d4pGbZhGr3vayITshOziotwHMpZUFugy/pnytWXrMszT/56vKdQcVmYyh5nD4Kgy/4wg98nfbdfF6mLL3HN6RlB5NB6/JUHzN4V2hRUGN0Vo7ppd2+tpcmZwhnvHkRGkhTaH1UQ2GnvCG8yNRlNoZrDR4D6Z+eePu/Xc3osU0TZEe76R6c7XbcJuPd83Gt1rvEmK6KVPyjBnp/wz5f5n0OnK4oqidbriGO00VhhcGKXTNVx/Kl4XffM5zRijT6qMa43TTsQlbvRJ+qTM5MxkLX5xTKs7lmd0r9HpyqMT4jW5NcojuGtEbVi1IS2ztw170em0a12AFjZjRH5Cy4hT/i16nS4ttNfnRjidLjvGGONnqou2RFmi9EnLYotjCkZq7nNz5ub8Rzw49zLYRmh79+ZQztvDVDCy1TsnsNxY0b+iv9XTNriuX10/dlD7KDLCNMhqkELqjA1JthGwt96sNzcMtoVlhXfp03zahrX6VgRah9tGFPrnD2/Ql4RqeEX03nup83L7mmwjdoywjWhIbUit8Kvwa4ltid0x4o+457mbbLa/SR1+vfTZEwI4/x0jiofvcOfZ65pxPUxRQG8qN7CN+PuwkTfk3CDtWnI9rbaAvxf7H6f3r8G9Xx3u7bclIiOoILIq3BZUPdQ2whixZXibcYt7HWu8vmuxhf1r+/Nt/nfhHgNBhcENSfmGisAcS0HilpC6gLz0+sB69znPO7AnoDLKLVtYy6movAC/KKuhNqjdoA+rD8wNqjN6Gkss3oGe4cUhBYGSIcuY7z4TWg2FwVsiYP8On970ddNv83+Nm/tXaVBRdKV7lW4NzgzeYS5IbAjSm71iagL17pWdtRgjiqKzrGkjPaI8kouiy6I8rU0J8JiOkVxcudUc2xBbnFJqrrNycUcj6i2nknMi58bVBi0LKw3Kdp8DG4I8TC3mXHd6hVElgSWR+qB6947cz51LYZRfcE5kuTHL6N4dhRS4T9AeUQWhTSG40RrCmXS6gpEFoabQKqu2PrVf9881m0K9Q90nEF1RuE6XMzLNvaIkXPdvCDJEG6JLg9jIWrPOvXdpDS6KbotuDW4w29yyR1TvsxVDtHYtNBWFa/sJdx5mztTqtjdFHAyuiy4PLzLWR3YFFcUXxXsnutfgpKrwHWbPeC19m74liPMvCLT4ZxvMYZnBbGhedFZ4QWimqcdYHZHj3vXozeXRxYbqiNygnMCDJk9jVrQ1xtMIRxmMCcZlZi29nES9udacH6Glt8zskdyavMxck+g+a7j3GVXp7r3HqGWxNYk1iZp/R2ROoi6sPrQ+NMvq1jiuJLAo2mzOMlZEZgWUBOp0PQEdkdkRCQEZYX6mtgCLiXTvrNlEMsGUeDShKaEksXh4k6EhjDQUhGaF54YVxxwNscZ0mb1Dmy07zD3hZXHNoV5uuymUtdSa8fC8eFtYlXvfqQ/Tuc/KxRF58Y3DTKFwsFdITSAZUuOXENDu3hdp/aEmNOP6rojz50zNofkhbUbvUNgfDm6JtaSdcp9i60cejWiM9h7ZleE51m9MS+rRrNzUitH54zKCusxF0c2BOZFlJqOh1nyrPSFA+z2UdXi7ocy/JPBoCBtqdO8b8PBSc6WpOgIPz4/QKLFo1wpLdURWOBeXFX5j/5IQ7d6KBBmGGYZVD8+PWKa3xngZqgK2GKyG0qCegIJAP1NtkNFwyqTtWqsC2sI9TOXxeECRe97sjV85IXd8udU6rjz+aAIbWZReFpUX7RcFR3WZ82PyI6pjYF+L/zL9Mr3FH48v8ctNzU319rt5/5RmyTA3RbSYl6XmDSuJbI/pCqsL97ZwwR6munQPU5s1IcA79GhKV2qae+9cHGMa6RHckVhlbU40hLOWqugsoy7WI6050hTqGV6YXBBZM7o6oSytfKwluDzeO7Mi9GhES1BFZIaZC25JzTMWxlVF22K9LYXB5qS26z16bhQbySVLIZVRNYlHY9pjqiMS3D3Yb4Iulhyn/Q7PPLnU7M4t0phw67OyG1TF99Js6YN1Y03QngVqT66MCV4pfmmaabZ4pPVY/dzGHSay1L3KmHxMPlUBVQGletKgCzL5lHt5+zX7kcMrJ+SnFKXjYzsSm6+zI7aPWje5SRqW5NykjsRTyaWpmmlxX909Kbk21jwi39MwTEroRRvdNzCOmpuWmWYcpZmCxGVJmilN6pVKk0r15enl6XnWPGt5+K3YYm2xaZaqeM1o8s10xVqHW4eXxVkTEuLd9Rd5K9q88A8YVjSsOiIv/I8Ux3BxDbEJ0ZrpvTbE9tl1sTZ9qd6mt42Ya9Kn3krxOA3trtnKjVUB5cYi6600ZDRkFIw2jC0Y7Tm2yNqS0evilVIw2iuFDTzlrzdnhN2KIbo6ZkuMZ3SJxTPaK6IwTjM5FnOsIb7O7VPoW+FX6MsGFvpqeE4syJRGlWYcTNbQTnoauowb9LVQH5Zgbdb6I14xN2i29JobtOjbAnL1ufqytBv0zs+95Mbmxrb6amXZktBLZXIv7Oic0TmBGUk30M6rGto3B0UBfT2nZFKfBMdp+P1OTWBbtE6vPfe/gS62r68UJ/TSOkVD61PavdFYm9QXoq+t/tgybOAfS9+iN4WWBvVSEdpLccxf05HY8bdR8s/I2ujsaxVN7jsj5yTmJPY9fyOHl4wuGS2F9KLJHZG93CxvMWh9vDill5tjaN+tulf+62RHaLhX5t/ZYd5h1p6Oa3SldqX21YzWhk0RvWjTR3l4lpvy8KZRTaOMEb1Ys6xZzaG9aKOi97uEzKgSvxK/m+2WMZYxfbpocl+/qBqm2awRVrdG1ohbQ/W5l4fnulu4dUr9goMLG6Y3TK9fUL/gz7Of9g3Y/2X+u79//O/m999JB/b9Xroj8m9yoFv2+QsCdQOum954gUUBfSn0SkXDbo1h07M+ugG6AQeDD/r+geDrz2iDr6NJvpUmU+gtYa6j07k182MHsT61GR1+7llnCOtz8Hr7XdfZryOwN9cOP+1+c/tWDbHpi7yqjDZ91RDYGw8wDKn8wy+B9HpdRs+wxvCeYa2+Fu9T3rUjvCPxfjd+ndDsYxjSM6zQt9LbOrRWTw719lk2+Ob4JaGGAMmgPcHTRubBqK7BxuE9Q7yGFg8vHt41uGtws0+zT9awNJ/soSWDqgdWehcP7Rni560f3GRoMkghnH9HaN0wv+CefqVBWcZ2w8Fgzcw1FQUYh7t3WyOq3GG1nAt8yKHWgTk+7CC3LcI4PGvIMn2rv2ToGqDlWxtU6N3qax5R4M7LFJjjZx1aNczP28+7VN/sU98/e6h1qGSo8dGPcKc56Nb+b/LzC8707bje8qVh5thTwTU+TYaEYd7ufU3xcKu7vKfc+UtD03xO+Wbos4ZkD80YkR1SO6LZp9hQPNQwrNLbYHTLQ7VyNg20Du0JqA27Pb5u81/FDr3l+jOi4uHaCO7w6xlW6VsS2RNujfF2nzAro4rc9lq3v8mveLjnMNY9P2T6Ho1oj5gbVRiXa/aI+u/W/za3uc1tbnOb/5P81ee/6Ezam9dtbnOb29yMNPzGXKSRFQ1P6ZWKh2rozG1GDe1eEFoV3utXMPL6/Q8zmUfBrWlrv9L4c45aWv9h/EGD/9n8T3j+l5Hae//n3ny9zf9M+kZo8dC2Gf+Jufwnpn2b29zmNre5zW1uc5vb/F/nv+ZJ423+f+W/u//d5ja3uc1tbnOb/3r+r+8vrCldsRmxJZE2c3Ok9kbNsrCmiNwwy/W/XlQYVWXNz7KGmGMN0TmWHmNh1J+/qmcjCxLNSblmY0JOpF9U31/2M5sN4Zw7NZ3OO7EhSZ/knViQ2J4gJeh0GZMzp+ROPjWhZ0bhhJJJOt0f33/T6f74/tif3xf74/tZ//O/3/pv5/f3IbVr39uRf/WeZF+IG7a/798n3Rz6j3H68vlzCjfrcmuIW/O8Nf3/f/n/Xb//vfxL7wBr7xR1JN5w//Obc+Xhfe7/9BvGN3/+Mt+bbY3xmWMqEjPHlIZ1WBLiyVGanDmmaGxlmj6jLTwhXpPh5MZ0zaSNTBtZPa6XrtTm0eQocpQhnRylxcsco5mE+GWppkxyVPW4sgmZY67/cZZMLYWisVqqffS6V6ZpYTLHGNxpV4+rSDRldlgq0+DkhHhDetmEXtfecJljWscsS2q4/jeetEL1vgNWZNXKIMVUppVHp42UYhpStfgViUXp1Sn6jD69Na20u2b/f+3cCXxcZb3/8fOcWc5MljZJ03SHIU2bNp2moUhbCrTpkmla2qY06QI06UySSSeQjZlJaRGvFUFQREEQca+Aa3FBUFFRuKhX79UrTWpb3AE33Df06r3Q+f+e58xMkhIBX6hF/x++nJn32Z5zznPOeZ5n4uWaMzln5PoeO2vZEn0NuxaULy0/T68pOnvZkvLzfrN02RJdK/o6e1Y8WVd0dufS+xbftEyfiRtd1k3LHg3rsvUx3TrU9fXYWU8v0OuWLbl7gbt90dm/WaqPcf2ZjWtnNu5srGo4MKf+fP1fbY1+L/8+/335KW/fX2Ser2Ze9Pv5dz7/XQvkjVi4a4F3fvniXQv2zdP/X2uerFsWfnpu+eJ5C8sXv8iamff3eGZeWAuWzYs4+7/l+f+t87d/K8c/yqm+zn9s/jG1+o+8mhdbwqm+BkIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEJeKjkV//3f8+aU1wohhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEII+WfMU5NfGqk7h5CXcm5adqrPgOseL/e/xM+P/P+Tr/Eskr9xTsX46B8//rPmEUKIG1oLQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEDIqFxDy98lTk5+afOqOTF5Inl55zcp0/ZMrizZb5TPnHJDcX3vX/Lv0JJ+d8+6qteZdNd/NAbP+4Oz66QdCB+ZY5Y/J/vpb5iTaT01+zHwemBOtfGpytNKaXX+63s8qPzj7QChaKTrV7R0hhJyqvNh/nq980/u9kD5St+W6Bxi//3y2nnu7U16vL+3o+/as2tffj57pTvVnPTu5bdzcfnbj8vuWPrZs19kHFhUtf+Cc15d3LrxpWd0iK/LAOZ3n7Tq787zHlt23tKX2gXNuP/ua9U/W3S3R+7ulHJhTtGDewroaPa2t2LXgptqHyh4quz78UNmWyE21nQs7F85bODDzcM15026q3TW3cfnTc+vmhOa6e7plhM7IxTt/Y/XAGd6qebPvnrux+vCcwzIaKKprqT1Q81jto+EHFtXVPFm3b95NtRurHz1zmczvqrtr/vXV8xbqvKNyV92j4V0L7q57quqBRXfP9c731hbVdS58+ozrzwzNvW/ho2cW1T0997H5u+YuO1PKm78sXFfzUNna0lN+B8c++fPcsVAuz7VnwCKEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCHkXyeW9cqyIweClm3pf7P/oBep8FL99fXVHrvZ6Gt5TRR1rMitfddZlrVi5ch2Y7VtSU6X5fdYcG5Ou8wye6XHfs+SsfvevsJjv3vJs8srlWXTVmt9f/mz147ojStzumectc+tr5njFooezOvk7X6xcvSyRP6Kpq54dnltokOmhi7MX1GTLDvTXEc8v100r9tX57RFlp0w+74mv/a8/LXtHufst4t6VufWnma0R457q1Fjfrt2WfYWs+zCcUqJ5q/DkWWTVz9/rb1vnCufOc52jSdtdzivjy4dvd0NK3N1/4v8XbjnrJxKV+f06fwytTynsvzaP8u+p6/UWr00tyyc1zP5ks/PL/uxLPvJCq3fiWaYfT8rx3jIyFn67GP8fpxSvp7XHflSRta+UK3IP1fDI/WcX+bWVa+8KVbuH/R3aP8m5e/va/Ntzvl5XZd/nkf2LcqvPUN0cPnHRU/n3+nx3p6RfUfavyUnvSnvHLPHPeb98K0c/+6PbKff/dtWF455Q92W9f4Vz3UGf+n8xlPlOO/+X6+n8u3arnw7uX3ps1Wf1wV53ZHXVXldndeNeYWX59pd3RJWGb1Cjvamk9Rvas2cn+j2/LJbVo+tjXi+ZdWtxdSTVCLHKDX6kywrN7ozX1eR/HseEP1oxUi/VThGrxtHN42zLCmtVMa0XB/Pt4mPj6NH8npoRU5n5s+lapx2aGTZcH5fW5ZVmHbtJ7Lssyfp26IHjR7It536rF5uzm+k/r6SX/uOfDs5okOi04zeL5p5Uiv6y3Ha3ed+TtG/jqpf4vd8Ub4PmJofl5z6sxpPe/Pt1W/kbfzkylN5piO9wf8f7/T7xhk9PLf+9WroX+U6EEIIIYQQQi9cL+Tvon/NL6VTdc4vVKf+7BFCCP0zip7kn0n/3HfrhZ79P/dVIoQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCP2t1bxUf319tWeU/vo9xtv3b73dc5/Li6mDU3WMv/56X5rXgRBCCCH04vVSGv8hhBBCCP3r68X8JfDUnz36x9x9hBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCH0T6GVFW1mfl1/OhHrDW3s3pNIW40tkVB2QWhN/0CyNrS4rq4u1JKIhxr741098WSoZf9APBTpH+zrTO4Ph9b3ddTKR1f/8tAVV1xRm94/0L8nGRtI7K/t6O+1Xhl8uxzDY/X/seTxZw7cat14lm39xsrIPyPncd5AKNbTvafv/MqOeF86nqxccV5Xf1861BXriJ9fOfrsKkOp7itl2ZmLK0Md/T39yfMrZ3eZfypDPfG07Ns8EOvo7ttzfmVd7dl1+p/K0GXxZJ9ZdGblitVbm3Y0N5y3SJe/4rxFAyusB8uKzAluyZ9OJlgjn15LWa/x+5V8WQ/6y2XJXFs2K5t3kdU+mE7397XE96WterN9SD59suGD/jJRrZKdrW6rvsSy4r0D6f1mK3fdXCUbFket9mT/Fan46nSf9WB5/wpLH8SySqxaq1hXzUSrMOANOranQPkt6y6P5W9OJ+US/E3tl8Y70jOlYmtjnf3t8dpUPNktdXdlLN3d31d7aaq/L7ihuWlzS/9l8T7fqmQytt/T3Zf27u3v7nRW9/f3xGN9/s2Dve3xZFFXTyyVqI3vlSpP+Rr0V/GWpNy6eCpl5oJrY+mY0cTGlpYtzelYetBdU7S+qSGZ7E+ambLmeMdgsju9f2RR0C26L54ujnT3xLfGu+LJeF9HvGBT/2Aqbjbx6rM847muY7neolB/rI139HfGk/Oed+vshr69sZ7BeOFALJmKuxVWYLxdLw72yW0z1RNM6095nJLF+SrTcz6zPLAnnjY7uPuaqjRn09D3As8mu2FRPNURG4i7N7A4pstp6XfngnIMVwV6L5cT+s0p57aZ2NHftzeezM/Pfd7jmgvx7zaV4Nstr2Pcqz9qXtiOugY8Pf0dRanLugfW9Pf26sfD6U6t7d7TnbY7EgXJeKzTPZWArso1iViySK5jc75a9Y47Et3pbM2Zx6KoO2UW6bcz7pErLNRbrd/T15+MdxZ0pxrj+8wBTOnu8zlyU1pe+NnrTSfouS35Q/vM54Ln3X9kj+BuuX6zNpCD1KNcn1d/FA8O9PTHOru79u+Wx7xoU6y7r6W7N97T3Rcvdp/7zu7UQE9sf3BT/97u+Jqe7oHpY3ZZPmaXVDy9Ot+cFHW5r8umwZ50d+mYd2djdyrtdEibK22cvysZ642fWaG3bo73yNNidmiM9XVK8+yTao/1Th45pitdWipQJXduz554Mqj3vXAwPhh35G40y10vSHR3xt1T0c/++r7O+L6CkV2Ls6fWLDde5mI9Pav3p+Oplv50rGfi5bqg9anN/ekG3d4FUx3J7oH0tq0bC2TaGpfVqXSxFBrp75E3YkssnZgycu5uidmTL451pLv3xreZ46YCeqv16XivqZjUmkS847J4Z5EcvP+KeKe+2SlzXim3pHjnRKnOVaPWBmXTC9pTq/buKYjrW2te4+wdXONW5qib0xGTiu7RV+se3y17a1zuZoeUna0BfSfiffFkwR79GUvH1689bVQZ0sQmR4owVezrjLcP7hm51bq6ne4+s64ov3R9756po29apxTdLH2aVE8qmO8vik1db5VmWx7Xzgm5+7BRdot3BvfG5Nlul5Mukorfnpvxm2tPeS5rz1aXe27xTn+naTH9cdNU+Tdv27S6Yasvsmpjc0Px1vXrGlt2r966as0FDS3ezds2bvS2bN3WUDiyvMHZtvmCzU07NvvWNG3atKpoY0Mkv4O/uWXr+s3rCvLLGmSjjdLkJ9LpgeWLFrmvoryUi1Y1n7VIRhhLFrUPdstD3OcdGEwlZjTsG5AbKpceag31J0PhkPS5oS495AiNWveKk9dVjKxbPv4uKdN0jVo3ZZs0YwPm6QnFZb6/K9TdNzCYLhy1PNCdinT3SfsVSGebYW/fYE+PN52Um9sV60nF/T3xvj3phL9DmsNVaXtXpb1rl72r3d7VZe/qs3cl7V1pFSrQa9dITcsWdXUeGZzYuwZVpdqlAqpIFahiFVRhdYlq9ezctLHQbUwG0909qaLOuH6l2uP6ofb2ycsfiAz2deiWSS13ZGP9TAZyNz8Q6+iQTrw/qV6uXqFSwQ4pKKUHaJ7L4vvVXtWv0qMqpFpfRPWoClFdM0etNVc3ZnXf6J11NYxZu7AopJ8m82rFO9WiylDDvo74gK7FWCgR3xfq1O38qHu2PBQw/cR6GVd0Jft712TrSLWrpBqcsU0X1NvdF9MlZG9ej9yJZKyndOQ8Ym6xqm72KlcheZf7+tOhbunAOrtl5579cjjdMoTqVK2Kqwa1YFFzR7f0bt1d3R0h2dY09KE+0/mE+uLxzlRIHoD+Ptkk5Ham3anNsc2O2z2FJoS6U3o3va678wxVM8s0wgt1qy5jU9NxmvUdPf3yplaNrpbQvPhIFS6q1k9xdU11aL46pzDdv21gIJ5cE0vF1SoVmZAdpe2T/frMJbtYrwvS42MnJq1mel6lXTnf2yGtgZqn5vsvlaYluV/NLsy3J+vXFrqvnHmeJrmlus9Jd3u3VOj+3HjQNBXZnkwaCzlMqsCd2xPv780+laZSs+c2IPdEX0l+tl+3MclsEalY70BPfrSZ2i9tZ2+2PN2bBrJPeXd2zLivt2fKmF50eb4XLR+7vFmOm45XjV241v12R31rZIwvXW08efrYjUzduf2Mu+GM5yhk5uhh8nIzdtXrY+mORDzpvbS/uy9Qm+1T1UDQbLZZ3k91uTeW3JPy9siLqVarNWqtWqca1Xq1QV2gNqpNarNqUlvUhWqralYtapvarnaoneoidbF3k3SP/qR0h/29vq6e/v6k3zTuyWB7rpsIxDo71yS6ezq9+u76zG8MX6xnIBErGPlpEhjsc0eeviu6O6XERFz/gAq6j8a8ytkllfNrY+l0cl6lWV8ZLs0vcDetDJvud62U4mjIo6eu8knVyDBNd3AR83AETX+kezR/l+nd/anBdnlPvbqhlzd7T1zqKmHX1vr1nh1xe/3aAumv0lvjKXldvLpgr/5NF5CRsRlz+NNScfH0xPyj6/btk06ab5Ku2gxiTDfujQ2m+ws79Pig2Yw9zKnrVnFC/vw2dvd2p8vyxZjeNyLNl5N0O1O/O2rx98bTif5Oz7qGlpKR0csms9C7pam5pcDdTv86MvWiB4bSV8dGztCMUxr26aOnunvdztYcvSAlF5fWY7+kHmMZjIwnmwbifcXyW0rGe+kWUwmF7SN9e0F7frzlS+qGc6I8mOlRnb//MjPQKc2Xl/s1VyDtif5hLfdCbp80bCObyABf3k7p1/SF6HFZUYeMwHVDKJcXL+nt79StY36B332i/CkzZCvftmVj06q1u6X337KxoaVh99pVLasmuffELTY7qJuUjPf273V/+OVGT95Uf2+8PH8iMmjL7RSUc9a/vZIpb7K/P13YsLmlYevuyNZVmxpKErHUmFJkFCWPTFPXhHxBZgTv1T9Yvd3S5flT5mdrWZd036mEWZk9KXt9UyD309XbtKVhc4m8VWMKD2zZ2rRua0Nzc6Eubndzy6qWbc2B9U27G7Zubdo6oblhzbat61sucmeDqdwjFtQvR0g/cWbUqp8T3SL43VM09ZO7M9lTMSNLffdzI3hzVX53ODryIqwx86MeMz3UNI+x2u/r1Z2P3x0m+lL6Xhc0689V+g8rgZamLbv1UMxn/s4ywaxplu4ivkl62sDmpt3Na1ZtbJBxe3ZRgdvk6EFDQc8IzS+LuOkS3IZGb1ssv+n1ia8ZTMqYo7hX/8Y3rZM8x4Gk7nPl9Qpubdq4cXfT9oatAVfbWgo2NW1rlofGDCA3rl9zgb+5YWPDmpYJY4e+hbqxk46tPdZx2UTz/oyMrktOHrGXjzf8niAlRPSJu03DxJMa8eIx7X3ps3qHivE7Fb/bAb2sQlV4KworyqZWTJ3qs6bOlqlGplqZVkxd5bMqIhWNUzdMiQReq3zWFO/0qdM9Pmv67IqPqorHZIls8DNV8XNV8QtV8UtV8StV8WtV8RtV8VtV8TtV8XtV8ZSq+IOq+KOavmH6/6jpf1LT/6ym/6+a/n9q+tPKp+ygY6vJFVP8U6cFg2q6PWVyYMa0M06bpSafXloeOqOs0jO7ao53bvW8+TULZoYnLaxdVHfm4rOmHbQdJf96HNvnKL+jHEcFHBV0VIHjKXI8xY5nguOZ6HhKHE+p453keMode7JjT3GcaY4z3XFmOM5Mx5nl2Kc5zumOCjnOGY5d6QSrnOAcR811gtVOcJ4TnO8ULnDUNKcw7KiFTvEip7jOKT7TKV7sFJ/lFL/MUWc7xUsctdQpXuYUn+MUVzvFy53ic53i8xz7fMde6ah6p2S1o9Y4JWsd1eCUrnPK1jvqAkdtdLybHLXZKW9y1BZHXeiorY5qdlSLo7Y5arujdjhqp6MuctTFjrrEUbscb6uj2hy121FRR8Uc1e6oDkd1OiruqC5H7XFUwlHdjrrUUZc5qsdRvY7qc1S/owYcdbmjko5KOSrtqEFH7XW8Vzhqn6P2O+pKR73cUVc56hWO+jdHvdJRB5SjXiXT1TK9WqZrZLpWptfIdJ1M16vgZOVMfp2aYQenyPzNKvgmuRXqNln4FpkOyvQmNUOWfEQ5Mz+mJtyj135cBS35uk8F9eyUac6UTytnymdk+qxMD8j0ORWsVEGflPgVKeE/5fuYfH9XBU9TwfNl7h4VXKmcWY8Lf6iCP1VeZ/IzyinPyHTAdspfJQ/E1fL9avl+u0zvkOmd9gyvU/YuO/hu2+so/dS8xw5u9wbvsL3BO2W6Sy9+rx1s8Abfp/k+O/h+/f1+O3hIVt8t00dk3vtRO3iP+OMy3Sfzkz9iO5M/aQc/JfP3y/Rpme5R3uBn5Puzev8H7OBD4n/XftgOfkHv8yU7+B+y7MsyfVfO3fufcjZfkenLMv2XHfyqLP+a3v6/7eAj8l1+2HZmDsn1fErWH5HpGzIdlemYLDsu06MyfVrmP2MHvyf7fl+mhbL7Y7L4cVn8hHz/wA7+UB/6R+KfyLInZfqpTD+T6YdyCT+X71/Lut/I9+9lekqmP8j0R5n+R6Y/2cE/S7H/p0/radnuGZlOyJSxgwc83uCrZbrGI+uulRv7Go9Tdp18Xy/Ta8Wvk+8bZHq9+Eb5foNMb5TpJplululNnuAtet9bxW/WT49Mb5HpdpneJtO7PI7n3bLvQZneI9MdMt3puUj/nVkpW//FWVlj/hlZ4DF//nb/lwJ79AbZT6VMIUZet7j8Zrbls62ArTxFRdK2WcrvcwtR/jElqexhcpOe949M8oiO+fCfdK65fzyWtIFWwCOnIJM+4OirUtbIeWZL8SsVyB7C74w9pm22VwE7e5EB/WGb/YKjP2y/kj09juXT126ZxQX6o3DUxSl/kf4o1h8TpDb9E+W9tGyP7Otkj638JaM/zGmMru9AqR306f/FwQ76LX9gkl5WrqyCycoqrJCLnmJZU61pug6mK8uZIWcy0w4GrAn+WcoqPU1ZZacra2JIn88ZyppUqawSjx0ssCr8s/VRqmxr2hz9v1rMta0pcz3W1CopZ6odLLJmTazWy+cpa/Z8Zc2t0SUsUNbpYSloobJOq1VW1SJlzatT1pwzdVGL9RZnKavyZcqqPltZoSV2cIK1wFq6LDjRqvWeo0tbbluLztXbnWdbdeevkKvZsXClspbXW9Yqa7VcrLVGWdvXKmtNgy4yoqyGdcpa0qgfxPXKWrFBWedcoKz6jcpq2mRZE63Nep8mZUW2WNaF1lZlrWxW1uoWvfM2/bFdr9+hd9+pdZEc+WKNS/SiXcpa26qsLW16yW69eVRZS2PKurBdrqRDWed2KmtVXFnLupR1/h7LWmElLMuxuvX2l1rWZVaPVq/+6NMflt1f6rUHSj3Soxdbk62ZVk3R5f4in8eT9Ad9Xk/K7/f5PGl/gc/vGfQHfI5nr9/rC3iu8Mvz69nnt322Z79sEvRc6S/0FXhe7vf4Cj1X+R1fkWehVHDAq0rlaStSZV5LlauZXsueoTxeyzNfTfVa3rBa4rV8Z6qlXsu/U53vVc5F8sh7vJ7Ddev0Q+zxeEsO17XOHNowUx2YeWw4crolNWvnlpcNbShTB8pk+XS9XN4kr89/uO7wekv29tpS0kTZ6hVRuy5q77RmJUplsW+kfL/H9vpOM9u3TWmdOrRhqkpMaa1oqrDaJrVOjky2EpNkK0eX6jtcF50khwjoXUoP17VNi06JLLRqjiamDQWUrAjqFV1yNO8Gr3XAe9QUE53WNTe6pCtVLi/HUGPJStlsyBTc9G9qnA2yc/vK5dU0q0vkNYxOCd+gZE3VwaZFquRzmUxIjlYgFeC7Xx2uC117rNXeYFsH7DFH3Js94hvkiNlFV5anpVRTUkQp2W3U5leVr8secWjYnF/sleOU9pdO7/Ujp+cuuPHkBW8YWdDnXkChrq5jcgHRaaHygNnojUqvnytn3FoeKbcag60zIjPkS+8qn1PCN42U8lbLnNtROZ2XD02XBqjKKumSZUu69ruzqmSHmb3SnbVLGs3s5e6sp+QcMzvoznpLasxs0p31lcwws2l31l8iLWKJllNi68+AmpHMZJy2TCaeyfSM/TfpXl6Rfvb0E3pAuQ+fmpUokzouHnn4JugaKHEfvlBr5VCkUiVCsnxi7nHT5ZToja6XahqKqnvLpLFunSW6LjJLNQ5FA/eWnSFLXqWE10VepZTeYChytbKuLZGuKXyLaiyRAoeizr1l5fJdJm13+FZl1r1Z1i3Q67xusaeJroucpou1760pk/5o/lDo0G16l9YzhiJnqEZdnGWVeoJe329s/eAdD13b4ZfJCatjQ12vVoMd3iqrw1cirWNwqN0XuUaesuMlt8v9HA7frg4eK6lSmm/VnGb4Ns0Jhm/X9Bi+Q/NPZrd3av7S8F2aTwiPhN+tiuT2HamyItcqVVUSeY0cqKbDL6dQZR8yF/ke9yLvUHJ2w+E7Zch8sN1/8OC1x0rkwoaPaLxFSugIhO9S7YGR5yf83tyseX7C78vNmucn/P7crHl+wh/IzZrnJ/zB3Kx5fsIfys0++/kJzDhXnp9fncj8+UTGm8lMzGSmZzJzMpm6TEZWPOxr97V7J3/6REbObvigfByUg5d5vV5f/eE6qewq63jJGbpS9BVLtymXFD4k1TMsT9GRruuUPElyhQ97jui7MvlYJhO+W5fzYVPOJGnKAx+SR3BHzbG6uAodsHu98nVtr0/PXK96/XE11KviKqx67bhqfa2wR0Veq5Re6ZEZT9frlH7Iwp7yq3XFHdcbXN3hLYnLOcVVu/fIaaY0vVgmn5yRe5Aeb/QGeYqlOyhZblkyb7sXUKRn9Ky+Cn1Q7dZZel950MP3qoOtlXpvfV0Hr+21F3s9pbdmMgFvwFMybM5Anju/PrOLXq/2Xd3hRG+Us1+t5FmUnjvY7rT7Z9d0BGo6gjNb36Aib5BT/4Q6VFMqx52fW/BJdahMmjWpeX97IHadmhUIBgKLHX/p5+VATsDf7gv49DXuyF3j7GxdPf9F+LP1NfpaVHZ59m7lruoO96rCnzJ7Hwzfr2+Z/41K+jLrJmXJmO5mZXmuV9abZMiorFtkWCgzt8rAzbbKc03Om7NNjj0rMVNe/8kjTU6F7ck3OXOGEnPaZg8nZsvyKbkmZ448IFNtaXIC0sPpLWTltNzK2bJyem7l7CGz54zcQW/LHtQzK+GR5TNHDjpL71LhHnTxUGJxW3WVlahuDTeFdSd9mkeGE7f6TEfmNineVs8Gj3XAc7T1rKazrJL369ZEN/OxuUNSL7Eqs2dJm+0u3qsX359fvC67eL9efHd+cV12cUov/nB+8bTs4n168aH8Yju7+Cq9+N784p/LmYQ/r1rDkbB1cPTntceGpVkt102s7lNkr7m5fXTTuij8oLx+utf6oC7hoXFKyJZz/Ii0y7lyklJO9dhy/l0dMeXEdDkPj3cmNR1eaadzRaSliFCuiEJTxBfk2TVlyFg72LogskDXdEmJnpkfrYnMV3trSqUFFYe/KK+EPNWtZ0fONhvJiF2WKj0WCDVKUdId1xwMf0mZ4r6uV3b45A61+7Lt6S3SCN6fm1Ul18js3blZu2RQZj+cm/WYxvdQbta8ZlLz2VmfaXw/n5v1m8b3odysYxrfh3OzAdP43pWbDeYb3wLT+BYEfDMqMpmCe57JfOWZzPefyfzxmUzxiUzVicy5JzKvOJH50olMMJORLYbkmKf75OH8qcd0dtLE5J9MXbdXxuZKU+xWrbyHQama96ryf1OWu+gTptO6S3daXaZX+w/NSwzfq7nF8H2aDYbv11xu+AHNRYYfHOk4P5TrOMPKnE1JpR4qvczc+cjLVKl7g7+s74rckSPyde3xh73t3iqv7gOGo6r1LeqIdJdvUXbkdqW7iJKvWu75yLZ69oHsTbxr5Cbqu/YfIzdx0O0jczdR37X/GrmJO0bfF6+5aw+P3ER91746chNrRt9Tx9y1r43cxNxdC5q7FpS7tjOTCX78ROZzJzJfOZE5ciLzvROZn57IPHUikzmRKchkZLXeYVhftntb5I7cpQ7dVlOWfZ7FpdtPZMwzHDB19d96xGm2HRqOVek7HvJIL/tLGd6MvtWXm1tt3ojyQt3ZflHuhNkt+86UusV9XRcnmz2iyivHnEl2szJ3s8NmnCvXqy8y+OzNSn+a0Sc5pMrP0Qcbeo6DPXcJw7qTy178EXmZL9bFDeeKk4XfGLWBftsLxzvr7PGOPs/xWgPDkYAaPC7D0SN6LLq3Ro8r57e+VWbfqtRtZXJzho7oWpbCjktDFn7UtBx6lHuGT/ql2dKr1EQXt1bXHO2qrnnomNyS6oAdUHocKT+zatyfWZW6NwkdrquyjkqjJa9ddepoa21TrdU6r2meNHrV5T/LZKRfma0Hzt/Wvy9q5Pktf8TKvpc3yD5mx1wdfODkR+QHci1m07fnttKjFf1+f1OVz8iW45YazJU6S26mb2RV7vn6lqmzh+XJbNJl5ZrMb7tN5rn6bTsq5eR+wEyXV+CbKvf7JfcG2OYNkIqY8WAmYzdmMqlM5kFzjVW29MxTD9fpzdwzbZXLjdSp0l+b9XN0Xc2X3w4yYpYb7ddjemlF8vzACD+oDjXq/ztR2WGS3uER9bGaMnfVd9RHZFW1HjpUy6rI2+TnxbHW+UNuX1Eq2wyHv5fbfDj8fbP5PK+UVCyv0VK5JdHFG5Z6ZDw+PzdYeHt2sOCdlZgq51ljy2DhArn9V1RlEle07ZPxwb62l1epxMvb9lbZib1t+6s8if1tqSpvItV2VZU/cVXbYJWTGGxLVgUSybZ0VTCRbruyqiBxZdvlVYWJy6XIBWP+EhDOHfgd2QP7ZiWWyPKFeit3lFIr5+ufJjsMrVdt71ThlYl3qrZzhhPntJ17JHGubLBIKZ9fD4POkcury82cKzNnSunecin9Xab0ZfLvTv+sWYmlstdipYIF7hHO8tgFhVK50Xer8BNq6GD4B/IYHFRKVr3MtgsLC8I/0kt/bEbpZ7tL7tJL3PH/koC3sPgmpcftx+uyQ/RhPc6sf9mBG8zAvP5sDa8ZeXo79SBzldquDnj1WDw3Si0x425ftFQvigyopn9T+nx+ovfxdJodw0+qaEPXe9TBVbL/wdxyn/TOkTuULtIOnzB0T953p4xIb1DWXUr/dfW9MlSVmffJWNVrydDN57WWTvcXFOqfsPNkbPI9Fb7GDl9rh19jS5MkD0v4Ojt8vR1+rR1+nR2+wQ6/3g7faIffYIffaIdvssM32+E32eFb7PCtdvjNdvg2O/wWO3y7HX6rHX6bvX36Ae8xtzP0lczUPw2Hox9Q8m9EBlpV0+6IfEipLhmNSzcoP6mGJn83kzkiNbnM9hQUXiyd+oG71dHQgQuPyeV+WJXNkVf2brXhbmXp5a0XmqUbLlR6gz1DTR9Rami46aNKV87HVK7J0Nvcphu66J6ue1SVin1c389zbLnV0kgNlU3IrbFkTcnJ2y33qIJCafekmHtV2ZTsWnHrfcosi9ynVOwTetNz9aa7zKYfU/rXfHSP8JMq9illJEPgT5tb+QHbvXvhD9oHzRbmkdL3aszaD5m194+slWOc5/MWFKZ1xXilXrzHzrj6eNuO7VZih2z5Gd2gZy/5s2pv2QY5A700/GE78oD8NvQeNSvys/Ij9erjupMLRne0fk7J79JDalh/bPicsuWpO3Lz1cfd36ffMW3V+R65Ka+Wp2Q4VC4DzaHwx+xyaVCijbJJY7RhSPZsLEnog0q/cEhJk2aX6xY33hSXje9yZ1Y2rZSZQ3a+WbvbPqT/lNF6UdNFsuJ9Iyven13R0dQhK7brQ7VuGG7aoObKA7LClid2weE6uf4q65geag1dLU9Ygf4tKb/MT7v6+MP2Yp9Xt7IBX8A7LLus9EjV3ahM3el6k8r4vLr2qPmqktY88qCypaXXXc0ktxLNcq9Zfq996LayTaZCH1Jm1cFrjw7J5pF/H6nK6brn1RUY/oStO57hI7dU2U0PK9vUpP5TgH6+9ThTv5uyv5xVvS1ntUh3llLG4PGSCn07GnUhXV9QQ+XSJB9JHTty8+DxI6aeJz8mBchuq/TF9Jnrz/5t8dhwdeyLymwkjUiT7q3klM4fKe5Lqkv6sfJqPYDIL/myin1ZDecPGPuCPAGxr6jhuVKWOWv3qJ92j7q6QJ6Au6QK27aZoya2Rbe1Thzq+k8VmahiX1KtsblNMdUarfJHouraY9Ftw1JgtDG6TZ6mtp3SW+xs2xzd5h43sbl1Xfhz9rCZb1rnkbnP2+EHbXPAcGd0Z/jSaFv44ujmbd6mdbbsbcnebfLZJtX/X6pshrkZX1V6RNQaCVU3RewSx3CuUB7XNQVOQeET+s9gB2xp1pRbv09JhYw6+2h919eUvnh99p35OampSKc6YMtvta4vqrILLUtOfHO7V877PYnN2rnLOJgQRhtl1VdUvg6z89Ft8hq0tslwvavt5g6//sNFrC3gD/hKLs2+NnIF/62KLpDTHrfOWnfqfXfm9t2p9z3p4GMrsUT6elnyRdsULPWmF7hPj740fStlKP43r+q1+iGWfrN1dc2xrtU3H5dnaHXAE9CrGvzyov7Ia+6C+Uk0r8MXTegfQtHGpq8rqy0xN5GQ0h/5C+/gIye9gyX6XHJv4SPqYOwR1bbF9ASP6J4gsaXt0tbLNlxmJS6VRYdVZEhZ4a/Y5RNlty3RYdV1RMW+ofQPbXf2qJ6VLY+psJokdRW91G3Xj5l2valfmSazbNSaz7ot/nFlFrRujWy1zILPKynx0tijylSVtMR6NDV8W9k9UlHuG3p8SDfJrRcMRS5QqQ6veUjMW6gr+EhuNvv05F5Y/QStC3/dNqUeMS3P3KZ1vpLt2SfolkFp9haat7zdJ3vlyvLly/KNLqvdp3do91Vlpnw1kzm55Gpd8ielaZfTL9H13+ierVvC3rLT5fQ3jl3oemhu00ZvyVWjz2mPHvCuj7ZE1usftVL8N5X8rFVFDbJRy8gJyqfc7CJzsNyp7i2b6R4ot6DdN7JDtT6S/vvkBP2nwPzV3Gy6qIh+EAulV5ed9C8FabPWeWWYNqvtW6r12yrybWXFvqUrdNiOfkcNdX1XvzSyX2ORp7DwqB6XDHV9T6bvqzurOu+IPKbU4LHsftFvqffMuU1N7Je2oFdvFX1cFhwI3Dl6/ZPOnXcmett6W33R3qqCOyI+VVWgF4w+evQJ3UDL4932hHa092CVfWfsCVUScBf1itsujl4s6/SaxMVt3dHu3AEPJrrbHjcnGXtcX8c3c9cR/pY9HP6GrdeEB6Pd4W/b0V79Onvl6tZP9BYW/t42By4/S59/9Aeq64fqL5z9XzoHfXw5vDmb77rNT/dJp1DVac7BrB17GrLhd/SG4XvMtvI0hr9rm7dH/9klu+hg+DP5vb/n6kcyAnX1YxVeaPATtc3f+qQU86iKPKlUriG7RR/sCbXNloe4tU8aoj7TEPXphkg/s3JweVKrlO6Q5Qn8jrr0kJof/akqHWnKdPHRwq6fqejPVdMvZLPGaFPkl0o/oYX6h7L7OFdZh8pmm3b2x3b4ymhfeF+0J3exF5smtPVXauOvlDVf6n6DrQoLa9r6pDXta+uRz562bvnsbtssn5vbLpbPi9u2y+f2tkR1IiF7XFAgd+u1KnrJkB75j7xsYd1HRVuGnn3arT1ytT3manvcq3VPu3SVvGu/VtFg129U5LdKmaFudj66q+l3yn5h17AxIK/QsuglugZ/r1RVpnyeufxf5O/8wvAv7fCvpP6eMvXvbf2DklUb/6CU3n+T3n/p6P2rn7X/b939zxtn980vYPff/eXdmwL+wmI9Dtghnan8LJunf2zN0/+7wLxeR/8PKvKLLJD9Dma/C0b/ejuif7m1e/XPtvp12a3rG7Ob16/Pbl+/QaNQcIFGUVyek0F9KP3ld78c/YtPqv+P+rdcoOl/lG0WFHT9SS8I5hfoR1BQkF9Q1PVnVb8xP1vc9b+qflN+dkLX/6n6zXpWmtmndd8zWZ5WvUpecrfxfdo0vh8tWylPwCX6B2O2Jhdka1Iv0jtIVf6vrkqzi6lMWVqkf116Vqn5+u/L5ohbZP0zqumEfpP0urnStayzijLKCspPy2/Jj8qA9VP5nelIt2cFZNEflFUkX6+yLdtnyWNVKDM/V1aBfD2uLH/A+o78RFXWD+QX6kTrCWU5AWtLQEYOn5fBZr7HzPajHb5RXWed7nNyc2PXNV1tm2HbqP7UDN/0fK4Z0D9ays7XXZJ5r7Iv1OiXZu+z3v3x3qJXeYbaffkhlR5K2UekHZLH70KvjJlv0H/letaox+0rj5VM1l1la7RxONvDDTW1eoZlxXCVNfWHmczzvsJXe5rWqb+midmq/3QxwbR2+gfmTbFX66Fas/mDhl4qP4XNkhaPLCnNb1dl35HddJtu1Tbn66S8Xs5qR+ksM068xi7VP6I3NV1rm7+OReuN8iuL9MroDllourxovWspdbscrvi35k09Whd9jR29zu663o691tZ+nd11gx17vd3W0Hqjfbjr16rrDXbkRlt1vdFONLRtap24YaKV2NRW37pqwyorUd+22x3j725rNP/nHonG/Ki/rcVFS9sl7qpL2lZL7awePfDN1qZba26d9spn7zg1q+vU/MY1v22je+bGbrL1583yWR17k21+wMql32KXVZu/CZR03WrXbzWvq555s13fnJ+5za5vyb7Ix0wTH22Qdv+YMj+PzRZvseu3mS02yUNwux119613Z9aamXer8Fs90a6mt9rGb/dEIzm/wxNtzfmdnmhMW2p+h/7TRan5W1zr2+wqK7qm6W1mxU5bqWD4cF3c0n83e7tM75DpnTK9S6Z3y7RC/t3pzHL/SZwv+6ycdHr2/z5uzH+aWjv6P001/9X6/wMY5M0H");
\ No newline at end of file
diff --git a/lib/uploadify/uploadify.css b/lib/uploadify/uploadify.css
new file mode 100644
index 0000000..7eaa9e9
--- /dev/null
+++ b/lib/uploadify/uploadify.css
@@ -0,0 +1,58 @@
+/*
+Uploadify v2.1.0
+Release Date: August 24, 2009
+
+Copyright (c) 2009 Ronnie Garcia, Travis Nickels
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+.uploadifyQueueItem {
+	font: 11px Verdana, Geneva, sans-serif;
+	border: 2px solid #E5E5E5;
+	background-color: #F5F5F5;
+	margin-top: 5px;
+	padding: 10px;
+	width: auto;
+}
+.uploadifyError {
+	border: 2px solid #FBCBBC !important;
+	background-color: #FDE5DD !important;
+}
+.uploadifyQueueItem .cancel {
+	float: right;
+}
+.uploadifyProgress {
+	background-color: #FFFFFF;
+	border-top: 1px solid #808080;
+	border-left: 1px solid #808080;
+	border-right: 1px solid #C5C5C5;
+	border-bottom: 1px solid #C5C5C5;
+	margin-top: 10px;
+	width: 100%;
+}
+.uploadifyProgressBar {
+	background-color: #0099FF;
+	width: 1px;
+	height: 3px;
+}
+
+/* RTL support ~~~~~~~~~~~~~~~~~~~~~~~~~ */
+.rtl .uploadifyQueueItem .cancel {
+	float: left;
+}
\ No newline at end of file
diff --git a/lib/uploadify/uploadify.fla b/lib/uploadify/uploadify.fla
new file mode 100644
index 0000000..c07bbaf
Binary files /dev/null and b/lib/uploadify/uploadify.fla differ
diff --git a/lib/uploadify/uploadify.swf.php b/lib/uploadify/uploadify.swf.php
new file mode 100644
index 0000000..5811d29
--- /dev/null
+++ b/lib/uploadify/uploadify.swf.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+// Redirect the initial request to strip off any query parameters or URL fragments
+// We know it's an initial request if the token is missing
+if (empty($_GET["token"])) {
+  // We have not yet redirected
+  $rand = md5(rand());
+  setcookie("uploadify_token", $rand);
+  header("Location: uploadify.swf.php?token=$rand#.");
+  exit;
+}
+
+// If the token exists but there's no cookie, then this is a bogus token
+// or the user does not support cookies.  Ignore this request.
+if (empty($_COOKIE["uploadify_token"])) {
+  exit;
+}
+
+// If the token exists but it doesn't match our cookie, then this is a bogus
+// request.  Ignore this request.
+if ($_GET["token"] != $_COOKIE["uploadify_token"]) {
+  exit;
+}
+
+// This is a legitimate request.  Serve it, but disallow caching.
+header("Content-Type: application/x-shockwave-flash");
+header("Cache-Control: no-cache, no-store, must-revalidate");
+setcookie("uploadify_token", "", time() - 3600);
+print base64_decode("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");
\ No newline at end of file
diff --git a/lib/yui/base-min.css b/lib/yui/base-min.css
new file mode 100644
index 0000000..6eaa260
--- /dev/null
+++ b/lib/yui/base-min.css
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2010, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.8.1
+*/
+body{margin:10px;}h1{font-size:138.5%;}h2{font-size:123.1%;}h3{font-size:108%;}h1,h2,h3{margin:1em 0;}h1,h2,h3,h4,h5,h6,strong,dt{font-weight:bold;}optgroup{font-weight:normal;}abbr,acronym{border-bottom:1px dotted #000;cursor:help;}em{font-style:italic;}del{text-decoration:line-through;}blockquote,ul,ol,dl{margin:1em;}ol,ul,dl{margin-left:2em;}ol li{list-style:decimal outside;}ul li{list-style:disc outside;}dl dd{margin-left:1em;}th,td{border:1px solid #000;padding:.5em;}th{font-weight:bold;text-align:center;}caption{margin-bottom:.5em;text-align:center;}sup{vertical-align:super;}sub{vertical-align:sub;}p,fieldset,table,pre{margin-bottom:1em;}button,input[type="checkbox"],input[type="radio"],input[type="reset"],input[type="submit"]{padding:1px;}
\ No newline at end of file
diff --git a/lib/yui/reset-fonts-grids.css b/lib/yui/reset-fonts-grids.css
new file mode 100644
index 0000000..03c7d9d
--- /dev/null
+++ b/lib/yui/reset-fonts-grids.css
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2010, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.8.1
+*/
+html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}body{text-align:center;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main,.yui-g .yui-u .yui-g{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-g .yui-u{width:48.1%;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}.yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#hd:after,#bd:after,#ft:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#hd,#bd,#ft,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;}
\ No newline at end of file
diff --git a/modules/akismet/controllers/admin_akismet.php b/modules/akismet/controllers/admin_akismet.php
new file mode 100644
index 0000000..c907966
--- /dev/null
+++ b/modules/akismet/controllers/admin_akismet.php
@@ -0,0 +1,67 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Akismet_Controller extends Admin_Controller {
+  public function index() {
+    $form = akismet::get_configure_form();
+
+    if (request::method() == "post") {
+      // @todo move the "post" handler part of this code into a separate function
+      access::verify_csrf();
+
+      if ($form->validate()) {
+        $new_key = $form->configure_akismet->api_key->value;
+        $old_key = module::get_var("akismet", "api_key");
+        if ($old_key && !$new_key) {
+          message::success(t("Your Akismet key has been cleared."));
+        } else if ($old_key && $new_key && $old_key != $new_key) {
+          message::success(t("Your Akismet key has been changed."));
+        } else if (!$old_key && $new_key) {
+          message::success(t("Your Akismet key has been saved."));
+        }
+
+        log::success("akismet", t("Akismet key changed to %new_key",
+                                  array("new_key" => $new_key)));
+        module::set_var("akismet", "api_key", $new_key);
+        akismet::check_config();
+        url::redirect("admin/akismet");
+      } else {
+        $valid_key = false;
+      }
+    } else {
+      $valid_key = module::get_var("akismet", "api_key") ? 1 : 0;
+    }
+
+    akismet::check_config();
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Akismet spam filtering");
+    $view->content = new View("admin_akismet.html");
+    $view->content->valid_key = $valid_key;
+    $view->content->form = $form;
+    print $view;
+  }
+
+  public function stats() {
+    $view = new Admin_View("admin.html");
+    $view->content = new View("admin_akismet_stats.html");
+    $view->content->api_key = module::get_var("akismet", "api_key");
+    $view->content->blog_url = url::base(false, "http");
+    print $view;
+  }
+}
\ No newline at end of file
diff --git a/modules/akismet/helpers/akismet.php b/modules/akismet/helpers/akismet.php
new file mode 100644
index 0000000..a7927d6
--- /dev/null
+++ b/modules/akismet/helpers/akismet.php
@@ -0,0 +1,193 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class akismet_Core {
+  public static $test_mode = TEST_MODE;
+
+  static function get_configure_form() {
+    $form = new Forge("admin/akismet", "", "post", array("id" => "g-configure-akismet-form"));
+    $group = $form->group("configure_akismet")->label(t("Configure Akismet"));
+    $group->input("api_key")->label(t("API Key"))->value(module::get_var("akismet", "api_key"))
+      ->callback("akismet::validate_key")
+      ->error_messages("invalid", t("The API key you provided is invalid."));
+    $group->submit("")->value(t("Save"));
+    return $form;
+  }
+
+  /**
+   * Check a comment against Akismet and return "spam", "ham" or "unknown".
+   * @param  Comment_Model  $comment  A comment to check
+   * @return $string "spam", "ham" or "unknown"
+   */
+  static function check_comment($comment) {
+    if (akismet::$test_mode) {
+      return;
+    }
+
+    $request = self::_build_request("comment-check", $comment);
+    $response = self::_http_post($request);
+    $answer = $response->body[0];
+    if ($answer == "true") {
+      return "spam";
+    } else if ($answer == "false") {
+      return "ham";
+    } else {
+      return "unknown";
+    }
+  }
+
+  /**
+   * Tell Akismet that this comment is spam
+   * @param  Comment_Model  $comment  A comment to check
+   */
+  static function submit_spam($comment) {
+    if (akismet::$test_mode) {
+      return;
+    }
+
+    $request = self::_build_request("submit-spam", $comment);
+    self::_http_post($request);
+  }
+
+  /**
+   * Tell Akismet that this comment is ham
+   * @param  Comment_Model  $comment  A comment to check
+   */
+  static function submit_ham($comment) {
+    if (akismet::$test_mode) {
+      return;
+    }
+
+    $request = self::_build_request("submit-ham", $comment);
+    self::_http_post($request);
+  }
+
+  /**
+   * Check an API Key against Akismet to make sure that it's valid
+   * @param  string   $api_key the API key
+   * @return boolean
+   */
+  static function validate_key($api_key_input) {
+    if ($api_key_input->value) {
+      $request = self::_build_verify_request($api_key_input->value);
+      $response = self::_http_post($request, "rest.akismet.com");
+      if ("valid" != $response->body[0]) {
+        $api_key_input->add_error("invalid", 1);
+      }
+    }
+  }
+
+
+  static function check_config() {
+    $api_key = module::get_var("akismet", "api_key");
+    if (empty($api_key)) {
+      site_status::warning(
+        t("Akismet is not quite ready!  Please provide an <a href=\"%url\">API Key</a>",
+          array("url" => html::mark_clean(url::site("admin/akismet")))),
+        "akismet_config");
+    } else {
+      site_status::clear("akismet_config");
+    }
+  }
+
+
+  static function _build_verify_request($api_key) {
+    $base_url = url::base(false, "http");
+    $query_string = "key={$api_key}&blog=$base_url";
+
+    $version = module::get_version("akismet");
+    $http_request  = "POST /1.1/verify-key HTTP/1.0\r\n";
+    $http_request .= "Host: rest.akismet.com\r\n";
+    $http_request .= "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n";
+    $http_request .= "Content-Length: " . strlen($query_string) . "\r\n";
+    $http_request .= "User-Agent: Gallery/3 | Akismet/$version\r\n";
+    $http_request .= "\r\n";
+    $http_request .= $query_string;
+
+    return $http_request;
+  }
+
+  static function _build_request($function, $comment) {
+    $comment_data = array();
+    $comment_data["HTTP_ACCEPT"] = $comment->server_http_accept;
+    $comment_data["HTTP_ACCEPT_ENCODING"] = $comment->server_http_accept_encoding;
+    $comment_data["HTTP_ACCEPT_LANGUAGE"] = $comment->server_http_accept_language;
+    $comment_data["HTTP_CONNECTION"] = $comment->server_http_connection;
+    $comment_data["HTTP_HOST"] = $comment->server_http_host;
+    $comment_data["HTTP_USER_AGENT"] = $comment->server_http_user_agent;
+    $comment_data["QUERY_STRING"] = $comment->server_query_string;
+    $comment_data["REMOTE_ADDR"] = $comment->server_remote_addr;
+    $comment_data["REMOTE_HOST"] = $comment->server_remote_host;
+    $comment_data["REMOTE_PORT"] = $comment->server_remote_port;
+    $comment_data["SERVER_HTTP_ACCEPT_CHARSET"] = $comment->server_http_accept_charset;
+    $comment_data["blog"] = url::base(false, "http");
+    $comment_data["comment_author"] = $comment->author_name();
+    $comment_data["comment_author_email"] = $comment->author_email();
+    $comment_data["comment_author_url"] = $comment->author_url();
+    $comment_data["comment_content"] = $comment->text;
+    $comment_data["comment_type"] = "comment";
+    $comment_data["permalink"] = url::site("comments/{$comment->id}");
+    $comment_data["referrer"] = $comment->server_http_referer;
+    $comment_data["user_agent"] = $comment->server_http_user_agent;
+    $comment_data["user_ip"] = $comment->server_remote_addr;
+
+    $query_string = array();
+    foreach ($comment_data as $key => $data) {
+      $query_string[] = "$key=" . urlencode($data);
+    }
+    $query_string = join("&", $query_string);
+
+    $version = module::get_version("akismet");
+    $http_request  = "POST /1.1/$function HTTP/1.0\r\n";
+    $http_request .= "Host: " . module::get_var("akismet", "api_key") . ".rest.akismet.com\r\n";
+    $http_request .= "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n";
+    $http_request .= "Content-Length: " . strlen($query_string) . "\r\n";
+    $http_request .= "User-Agent: Gallery/3 | Akismet/$version\r\n";
+    $http_request .= "\r\n";
+    $http_request .= $query_string;
+
+    return $http_request;
+  }
+
+  private static function _http_post($http_request, $host=null) {
+    if (!$host) {
+      $host = module::get_var("akismet", "api_key") . ".rest.akismet.com";
+    }
+    $response = "";
+
+    Kohana_Log::add("debug", "Send request\n" . print_r($http_request, 1));
+    if (false !== ($fs = @fsockopen($host, 80, $errno, $errstr, 5))) {
+      fwrite($fs, $http_request);
+      while ( !feof($fs) ) {
+        $response .= fgets($fs, 1160); // One TCP-IP packet
+      }
+      fclose($fs);
+      list($headers, $body) = explode("\r\n\r\n", $response);
+      $headers = explode("\r\n", $headers);
+      $body = explode("\r\n", $body);
+      $response = new ArrayObject(
+        array("headers" => $headers, "body" => $body), ArrayObject::ARRAY_AS_PROPS);
+    } else {
+      throw new Exception("@todo CONNECTION TO SPAM SERVICE FAILED");
+    }
+    Kohana_Log::add("debug", "Received response\n" . print_r($response, 1));
+
+    return $response;
+  }
+}
diff --git a/modules/akismet/helpers/akismet_event.php b/modules/akismet/helpers/akismet_event.php
new file mode 100644
index 0000000..038e487
--- /dev/null
+++ b/modules/akismet/helpers/akismet_event.php
@@ -0,0 +1,70 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class akismet_event_Core {
+  static function comment_created($comment) {
+    if (!module::get_var("akismet", "api_key")) {
+      return;
+    }
+
+    switch(akismet::check_comment($comment)) {
+    case "spam":
+      $comment->state = "spam";
+      module::incr_var("comment", "spam_caught");
+      break;
+
+    case "ham":
+      $comment->state = "published";
+      break;
+
+    case "unknown":
+      $comment->state = "unpublished";
+      break;
+    }
+    $comment->save();
+  }
+
+  static function comment_updated($original, $new) {
+    if (!module::get_var("akismet", "api_key")) {
+      return;
+    }
+
+    if ($original->state != "spam" && $new->state == "spam") {
+      akismet::submit_spam($new);
+    } else if ($original->state == "spam" && $new->state != "spam") {
+      akismet::submit_ham($new);
+    }
+  }
+
+  static function admin_menu($menu, $theme) {
+    $menu->get("settings_menu")
+      ->append(Menu::factory("link")
+               ->id("akismet")
+               ->label(t("Akismet"))
+               ->url(url::site("admin/akismet")));
+
+    if (module::get_var("akismet", "api_key")) {
+      $menu->get("statistics_menu")
+        ->append(Menu::factory("link")
+                 ->id("akismet")
+                 ->label(t("Akismet"))
+                 ->url(url::site("admin/akismet/stats")));
+    }
+  }
+}
diff --git a/modules/akismet/helpers/akismet_installer.php b/modules/akismet/helpers/akismet_installer.php
new file mode 100644
index 0000000..bd16a15
--- /dev/null
+++ b/modules/akismet/helpers/akismet_installer.php
@@ -0,0 +1,28 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class akismet_installer {
+  static function activate() {
+    akismet::check_config();
+  }
+
+  static function deactivate() {
+    site_status::clear("akismet_config");
+  }
+}
diff --git a/modules/akismet/module.info b/modules/akismet/module.info
new file mode 100644
index 0000000..263b7b8
--- /dev/null
+++ b/modules/akismet/module.info
@@ -0,0 +1,7 @@
+name = "Akismet"
+description = "Filter comments through the Akismet web service to detect and eliminate spam (http://akismet.com).  You'll need a WordPress.com API key to use it."
+version = 1
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:akismet"
+discuss_url = "http://galleryproject.org/forum_module_akismet"
diff --git a/modules/akismet/views/admin_akismet.html.php b/modules/akismet/views/admin_akismet.html.php
new file mode 100644
index 0000000..399053d
--- /dev/null
+++ b/modules/akismet/views/admin_akismet.html.php
@@ -0,0 +1,18 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-admin-akismet" class="g-block">
+  <h1> <?= t("Akismet spam filtering") ?> </h1>
+  <p>
+  <?= t("Akismet is a free, automated spam filtering service.  In order to use it, you need to sign up for a <a href=\"%api_key_url\">Wordpress.com API Key</a>, which is also free.  Your comments will be automatically relayed to <a href=\"%akismet_url\">Akismet.com</a> where they'll be scanned for spam.  Spam messages will be flagged accordingly and hidden from your vistors until you approve or delete them.",
+        array("api_key_url" => "http://wordpress.com/api-keys",
+              "akismet_url" => "http://akismet.com")) ?>
+  </p>
+  <div class="g-block-content">
+    <? if ($valid_key): ?>
+    <div class="g-module-status g-success">
+      <?= t("Your API key is valid.  Your comments will be filtered!") ?>
+    </div>
+    <? endif ?>
+
+    <?= $form ?>
+  </div>
+</div>
diff --git a/modules/akismet/views/admin_akismet_stats.html.php b/modules/akismet/views/admin_akismet_stats.html.php
new file mode 100644
index 0000000..32908ba
--- /dev/null
+++ b/modules/akismet/views/admin_akismet_stats.html.php
@@ -0,0 +1,11 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javscript">
+  $(document).ready(function() {
+    $("#g-akismet-external-stats").css("height", "600");
+  });
+</script>
+<div id="g-akismet-stats">
+  <iframe id="g-akismet-external-stats" width="100%" height="500" frameborder="0"
+          src="http://<?= $api_key ?>.web.akismet.com/1.0/user-stats.php?blog=<?= urlencode($blog_url) ?>">
+  </iframe>
+</div>
diff --git a/modules/calendarview/controllers/calendarview.php b/modules/calendarview/controllers/calendarview.php
new file mode 100644
index 0000000..b1bae80
--- /dev/null
+++ b/modules/calendarview/controllers/calendarview.php
@@ -0,0 +1,296 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class CalendarView_Controller extends Controller {
+  public function calendar($display_year="", $display_user="-1") {
+    // Draw a calendar for the year specified by $display_year.
+
+    // Display the current year by default if a year wasn't provided.
+    if ($display_year == "") {
+      $display_year = date('Y');
+    }
+
+    // Draw the page.
+    $root = item::root();
+    $template = new Theme_View("page.html", "other", "CalendarView");
+    $template->set_global(
+      array("calendar_user" => $display_user,
+            "breadcrumbs" => array(
+              Breadcrumb::instance($root->title, $root->url())->set_first(),
+              Breadcrumb::instance($display_year, url::site("calendarview/calendar/" . $display_year))->set_last())));
+    $template->page_title = t("Gallery :: Calendar");
+    $template->content = new View("calendarview_year.html");
+    $template->content->calendar_year = $display_year;
+    $template->content->calendar_user = $display_user;
+    $template->content->calendar_user_year_form = $this->_get_calenderprefs_form($display_year, $display_user);
+    $template->content->title = t("Calendar") . ": " . $display_year;
+    print $template;
+  }
+
+  public function day($display_year, $display_user, $display_month, $display_day) {
+    // Display all images for the specified day.
+
+    // Set up default search conditions for retrieving all photos from the specified day.
+    $where = array(array("type", "!=", "album"));
+    if ($display_user != "-1") {
+      $where[] = array("owner_id", "=", $display_user);
+    }
+    $where[] = array("captured", ">=", mktime(0, 0, 0, $display_month, $display_day, $display_year));
+    $where[] = array("captured", "<", mktime(0, 0, 0, $display_month, ($display_day + 1), $display_year));
+
+    // Figure out the total number of photos to display.
+    $day_count = calendarview::get_items_count($where);
+
+    // Figure out paging stuff.
+    $page_size = module::get_var("gallery", "page_size", 9);
+    $page = (int) Input::instance()->get("page", "1");
+    $offset = ($page-1) * $page_size;
+    $max_pages = max(ceil($day_count / $page_size), 1);
+
+    // Make sure that the page references a valid offset
+    if (($page < 1) || ($page > $max_pages)) {
+      throw new Kohana_404_Exception();
+    }
+
+    // Figure out which photos go on this page.
+    $children = calendarview::get_items($page_size, $offset, $where);
+
+    // Create and display the page.
+    $root = item::root();
+    $template = new Theme_View("page.html", "collection", "CalendarDayView");
+    $template->set_global(
+      array("page" => $page,
+            "max_pages" => $max_pages,
+            "page_size" => $page_size,
+            "children" => $children,
+            "breadcrumbs" => array(
+              Breadcrumb::instance($root->title, $root->url())->set_first(),
+              Breadcrumb::instance($display_year, url::site("calendarview/calendar/" . $display_year . "/" . $display_user)),
+              Breadcrumb::instance(t(date("F", mktime(0, 0, 0, $display_month, $display_day, $display_year))), url::site("calendarview/month/" . $display_year . "/" . $display_user . "/" . $display_month)),
+              Breadcrumb::instance($display_day, url::site("calendarview/month/" . $display_year . "/" . $display_user . "/" . $display_month . "/" . $display_day))->set_last()),
+            "children_count" => $day_count));
+    $template->page_title = t("Gallery :: Calendar");
+    $template->content = new View("dynamic.html");
+    $template->content->title = t("Photos From ") . date("d", mktime(0, 0, 0, $display_month, $display_day, $display_year)) . " " . t(date("F", mktime(0, 0, 0, $display_month, $display_day, $display_year))) . " " . date("Y", mktime(0, 0, 0, $display_month, $display_day, $display_year));
+    print $template;
+
+    // Set breadcrumbs on the photo pages to point back to the calendar day view.
+    item::set_display_context_callback("CalendarView_Controller::get_display_day_context", $display_user, $display_year, $display_month, $display_day);
+  }
+
+  static function get_display_day_context($item, $display_user, $display_year, $display_month, $display_day) {
+    // Set up default search conditions for retrieving all photos from the specified day.
+    $where = array(array("type", "!=", "album"));
+    if ($display_user != "-1") {
+      $where[] = array("owner_id", "=", $display_user);
+    }
+    $where[] = array("captured", ">=", mktime(0, 0, 0, $display_month, $display_day, $display_year));
+    $where[] = array("captured", "<", mktime(0, 0, 0, $display_month, ($display_day + 1), $display_year));			  
+
+    // Generate breadcrumbs for the photo page.
+    $root = item::root();
+    $breadcrumbs = array(
+      Breadcrumb::instance($root->title, $root->url())->set_first(),
+      Breadcrumb::instance($display_year, url::site("calendarview/calendar/" . $display_year . "/" . $display_user)),
+      Breadcrumb::instance(t(date("F", mktime(0, 0, 0, $display_month, $display_day, $display_year))), url::site("calendarview/month/" . $display_year . "/" . $display_user . "/" . $display_month)),
+      Breadcrumb::instance($display_day, url::site("calendarview/month/" . $display_year . "/" . $display_user . "/" . $display_month . "/" . $display_day)),
+      Breadcrumb::instance($item->title, $item->url())->set_last()
+    );
+
+    return CalendarView_Controller::get_display_context($item, $where, $breadcrumbs);
+  }
+
+  public function month($display_year, $display_user, $display_month) {
+    // Display all images for the specified month.
+
+    // Set up default search conditions for retrieving all photos from the specified month.
+    $where = array(array("type", "!=", "album"));
+    if ($display_user != "-1") {
+      $where[] = array("owner_id", "=", $display_user);
+    }
+    $where[] = array("captured", ">=", mktime(0, 0, 0, $display_month, 1, $display_year));
+    $where[] = array("captured", "<", mktime(0, 0, 0, $display_month+1, 1, $display_year));
+
+    // Figure out the total number of photos to display.
+    $day_count = calendarview::get_items_count($where);
+
+    // Figure out paging stuff.
+    $page_size = module::get_var("gallery", "page_size", 9);
+    $page = (int) Input::instance()->get("page", "1");
+    $offset = ($page-1) * $page_size;
+    $max_pages = max(ceil($day_count / $page_size), 1);
+
+    // Make sure that the page references a valid offset
+    if (($page < 1) || ($page > $max_pages)) {
+      throw new Kohana_404_Exception();
+    }
+
+    // Figure out which photos go on this page.
+    $children = calendarview::get_items($page_size, $offset, $where);
+
+    // Create and display the page.
+    $root = item::root();
+    $template = new Theme_View("page.html", "collection", "CalendarMonthView");
+    $template->set_global(
+      array("page" => $page,
+            "max_pages" => $max_pages,
+            "page_size" => $page_size,
+            "breadcrumbs" => array(
+              Breadcrumb::instance($root->title, $root->url())->set_first(),
+              Breadcrumb::instance($display_year, url::site("calendarview/calendar/" . $display_year . "/" . $display_user)),
+              Breadcrumb::instance(t(date("F", mktime(0, 0, 0, $display_month, 1, $display_year))), url::site("calendarview/month/" . $display_year . "/" . $display_user . "/" . $display_month))->set_last()),
+            "children" => $children,
+            "children_count" => $day_count));
+    $template->page_title = t("Gallery :: Calendar");
+    $template->content = new View("dynamic.html");
+    $template->content->title = t("Photos From ") . t(date("F", mktime(0, 0, 0, $display_month, 1, $display_year))) . " " . date("Y", mktime(0, 0, 0, $display_month, 1, $display_year));
+    print $template;
+
+    // Set up breadcrumbs for the photo pages to point back to the calendar month view.
+    item::set_display_context_callback("CalendarView_Controller::get_display_month_context", $display_user, $display_year, $display_month);
+  }
+
+  static function get_display_month_context($item, $display_user, $display_year, $display_month) {
+    // Set up default search conditions for retrieving all photos from the specified month.
+    $where = array(array("type", "!=", "album"));
+    if ($display_user != "-1") {
+      $where[] = array("owner_id", "=", $display_user);
+    }
+    $where[] = array("captured", ">=", mktime(0, 0, 0, $display_month, 1, $display_year));
+    $where[] = array("captured", "<", mktime(0, 0, 0, $display_month+1, 1, $display_year));
+
+    // Generate breadcrumbs for the photo page.
+    $root = item::root();
+    $breadcrumbs = array(
+      Breadcrumb::instance($root->title, $root->url())->set_first(),
+      Breadcrumb::instance($display_year, url::site("calendarview/calendar/" . $display_year . "/" . $display_user)),
+      Breadcrumb::instance(t(date("F", mktime(0, 0, 0, $display_month, 1, $display_year))), url::site("calendarview/month/" . $display_year . "/" . $display_user . "/" . $display_month)),
+      Breadcrumb::instance($item->title, $item->url())->set_last()
+    );
+
+    return CalendarView_Controller::get_display_context($item, $where, $breadcrumbs);
+  }
+
+  private function get_display_context($item, $where=array(), $breadcrumbs=array()) {
+    // Set up previous / next / breadcrumbs / etc to point to CalendarView instead of the album.
+
+    // Figure out the photo's position.
+    $position = calendarview::get_position($item, $where);
+
+    // Figure out the previous and next items.
+    if ($position > 1) {
+      list ($previous_item, $ignore, $next_item) = calendarview::get_items(3, $position - 2, $where);
+    } else {
+      list ($next_item) = calendarview::get_items(1, $position, $where);
+    }
+
+    // Figure out the total number of photos.
+    $sibling_count = calendarview::get_items_count($where);
+
+    return array("position" => $position,
+                 "previous_item" => $previous_item,
+                 "next_item" => $next_item,
+                 "sibling_count" => $sibling_count,
+                 "breadcrumbs" => $breadcrumbs);
+  }
+
+  private function _get_calenderprefs_form($display_year, $display_user) {
+    // Generate a form to allow the visitor to select a year and a gallery photo owner.
+    $calendar_group = new Forge("calendarview/setprefs", "", "post",
+                      array("id" => "g-view-calendar-form"));
+
+    // Generate a list of all Gallery users who have uploaded photos.
+    $valid_users[-1] = "(All Users)";
+    $gallery_users = ORM::factory("user")->find_all();
+    foreach ($gallery_users as $one_user) {
+      $count = ORM::factory("item")
+               ->viewable()
+               ->where("owner_id", "=", $one_user->id)
+               ->where("type", "!=", "album")
+               ->where("captured", "!=", "")
+               ->find_all()
+               ->count();
+      if ($count > 0) {
+        $valid_users[$one_user->id] = $one_user->full_name;
+      }
+    }
+
+    // Generate a list of years, starting with the year the earliest photo was
+    //   taken, and ending with the year of the most recent photo.
+    $valid_years = Array();
+    if ($display_user == -1) {
+      $all_photos = ORM::factory("item")
+        ->viewable()
+        ->where("type", "!=", "album")
+        ->where("captured", "!=", "")
+        ->order_by("captured", "DESC")
+        ->find_all();
+      $counter = date('Y', $all_photos[count($all_photos)-1]->captured);
+      while ($counter <= date('Y', $all_photos[0]->captured)) {
+        $valid_years[$counter] = $counter;
+        $counter++;
+      }
+    } else {
+      $all_photos = ORM::factory("item")
+        ->viewable()
+        ->where("type", "!=", "album")
+        ->where("captured", "!=", "")
+        ->where("owner_id", "=", $display_user)
+        ->order_by("captured", "DESC")
+        ->find_all();
+      $counter = date('Y', $all_photos[count($all_photos)-1]->captured);
+      while ($counter <= date('Y', $all_photos[0]->captured)) {
+        $valid_years[$counter] = $counter;
+        $counter++;
+      }
+    }
+
+    // Create the form.
+    $calendar_group->dropdown('cal_user')
+                   ->label(t("Display Photos From User: "))
+                   ->id('cal_user')
+                   ->options($valid_users)
+                   ->selected($display_user);
+    $calendar_group->dropdown('cal_year')
+                   ->label(t("For Year: "))
+                   ->id('cal_year')
+                   ->options($valid_years)
+                   ->selected($display_year);
+
+    // Add a save button to the form.
+    $calendar_group->submit("SaveSettings")->value(t("Go"))->id('cal_go');
+
+    // Return the newly generated form.
+    return $calendar_group;
+  }
+
+  public function setprefs() {
+    // Change the calendar year and / or user.
+
+    // Prevent Cross Site Request Forgery
+    access::verify_csrf();
+
+    // Get user specified settings.
+    $str_user_id = Input::instance()->post("cal_user");
+    $str_year_id = Input::instance()->post("cal_year");
+
+    // redirect to the currect page.
+    url::redirect(url::site("calendarview/calendar/" . $str_year_id . "/" . $str_user_id, request::protocol()));
+  }
+}
diff --git a/modules/calendarview/css/calendarview_calendar.css b/modules/calendarview/css/calendarview_calendar.css
new file mode 100644
index 0000000..82dfaa9
--- /dev/null
+++ b/modules/calendarview/css/calendarview_calendar.css
@@ -0,0 +1,59 @@
+/* Grid view ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+#g-calendar-grid {
+  position: relative;
+  align: center;
+  float: left;
+  width: 200px;
+  height: 220px;
+  margin: 10px 10px 10px 10px;
+}
+
+#g-calendar-profile-grid {
+  position: relative;
+  align: center;
+  float: left;
+  width: 200px;
+  height: 145px;
+  margin: 10px 10px 10px 10px;
+}
+
+/* Search form ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+#cal_user {
+  top: 0px;
+  left: 60px;
+  display: inline;
+}
+#cal_year {
+  top: 0px;
+  left: 240px;
+  display: inline;
+}
+#cal_go {
+  top: 0px;
+  left: 328px;
+  display: inline;
+}
+
+/* Content ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+table.calendar {
+  text-align: center;
+}
+
+table.calendar caption {
+  font-size: 1.5em;
+  padding: 0.2em;
+}
+
+table.calendar th, table.calendar td {
+  padding: 0.2em;
+  border: 0px;
+}
+
+table.calendar td:hover {
+  background: #ddf;
+}
+
+/* For RTL Languages ~~~~~~~~~~~~~~~~~~~~~~~ */
+.rtl #g-calendar-grid {
+  float: right;
+}
diff --git a/modules/calendarview/css/calendarview_menu.css b/modules/calendarview/css/calendarview_menu.css
new file mode 100644
index 0000000..600cc15
--- /dev/null
+++ b/modules/calendarview/css/calendarview_menu.css
@@ -0,0 +1,3 @@
+#g-view-menu #g-calendarview-link {
+  background-image: url('../images/ico-view-calendarview.png');
+}
diff --git a/modules/calendarview/helpers/calendarview.php b/modules/calendarview/helpers/calendarview.php
new file mode 100644
index 0000000..4807bc0
--- /dev/null
+++ b/modules/calendarview/helpers/calendarview.php
@@ -0,0 +1,48 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class calendarview_Core {
+  static function get_items_count($where=array()) {
+    // Returns the number of viewable items identified by $where.
+    return ORM::factory("item")
+      ->viewable()
+      ->merge_where($where)
+      ->order_by("captured", "ASC")
+      ->count_all();
+  }
+
+  static function get_items($limit=null, $offset=null, $where=array()) {
+    // Returns the items identified by $where, up to $limit, and starting at $offset.
+    return ORM::factory("item")
+      ->viewable()
+      ->merge_where($where)
+      ->order_by("captured", "ASC")
+      ->find_all($limit, $offset);    
+  }
+
+  static function get_position($item, $where=array()) {
+    // Get's $item's position within $where.
+    return ORM::factory("item")
+      ->viewable()
+      ->merge_where($where)
+      ->where("items.id", "<=", $item->id)
+      ->order_by("captured", "ASC")
+      ->count_all();
+  }
+}
diff --git a/modules/calendarview/helpers/calendarview_block.php b/modules/calendarview/helpers/calendarview_block.php
new file mode 100644
index 0000000..05e470d
--- /dev/null
+++ b/modules/calendarview/helpers/calendarview_block.php
@@ -0,0 +1,72 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class calendarview_block_Core {
+  static function get_site_list() {
+    return array("calendarview_photo" => t("More Photos From This Date"));
+  }
+
+  static function get($block_id, $theme) {
+    $block = "";
+
+    // Make sure the current page belongs to an item.
+    if (!$theme->item()) {
+      return;
+    }
+    $item = $theme->item;
+
+    $display_date = "";
+    if (isset($item->captured)) {
+      $display_date = $item->captured;
+    }elseif (isset($item->created)) {
+      $display_date = $item->created;
+    }
+
+    // Make sure there are photo's to display.
+    $day_count = ORM::factory("item")
+                 ->viewable()
+                 ->where("type", "!=", "album")
+                 ->where("captured", ">=", mktime(0, 0, 0, date("n", $display_date), date("j", $display_date), date("Y", $display_date)))
+                 ->where("captured", "<", mktime(0, 0, 0, date("n", $display_date), date("j", $display_date)+1, date("Y", $display_date)))
+                 ->find_all()
+                 ->count();
+    $month_count = ORM::factory("item")
+                   ->viewable()
+                   ->where("type", "!=", "album")
+                   ->where("captured", ">=", mktime(0, 0, 0, date("n", $display_date), 1, date("Y", $display_date)))
+                   ->where("captured", "<", mktime(0, 0, 0, date("n", $display_date)+1, 1, date("Y", $display_date)))
+                   ->find_all()
+                   ->count();
+
+    switch ($block_id) {
+    case "calendarview_photo":
+      if ( ($display_date != "") && (($day_count > 0) || ($month_count > 0)) ) {
+        $block = new Block();
+        $block->css_id = "g-calendarview-sidebar";
+        $block->title = t("Calendar");
+        $block->content = new View("calendarview_sidebar.html");
+        $block->content->date = $display_date;
+        $block->content->day_count = $day_count;
+        $block->content->month_count = $month_count;
+      }
+      break;
+    }
+    return $block;
+  }
+}
diff --git a/modules/calendarview/helpers/calendarview_event.php b/modules/calendarview/helpers/calendarview_event.php
new file mode 100644
index 0000000..e98415c
--- /dev/null
+++ b/modules/calendarview/helpers/calendarview_event.php
@@ -0,0 +1,99 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class calendarview_event_Core {
+  static function photo_menu($menu, $theme) {
+    $menu->append(Menu::factory("link")
+         ->id("calendarview")
+         ->label(t("View Calendar"))
+         ->url(url::site("calendarview/calendar/"))
+         ->css_id("g-calendarview-link"));
+  }
+
+  static function movie_menu($menu, $theme) {
+    $menu->append(Menu::factory("link")
+         ->id("calendarview")
+         ->label(t("View Calendar"))
+         ->url(url::site("calendarview/calendar/"))
+         ->css_id("g-calendarview-link"));
+  }
+  
+  static function album_menu($menu, $theme) {
+    $menu->append(Menu::factory("link")
+         ->id("calendarview")
+         ->label(t("View Calendar"))
+         ->url(url::site("calendarview/calendar/"))
+         ->css_id("g-calendarview-link"));
+  }
+
+  static function tag_menu($menu, $theme) {
+    $menu->append(Menu::factory("link")
+         ->id("calendarview")
+         ->label(t("View Calendar"))
+         ->url(url::site("calendarview/calendar/"))
+         ->css_id("g-calendarview-link"));
+  }
+
+  static function pre_deactivate($data) {
+    // If the admin is about to deactivate EXIF, warn them that this module requires it.
+    if ($data->module == "exif") {
+      $data->messages["warn"][] = t("The CalendarView module requires the EXIF module.");
+    }
+  }
+
+  static function module_change($changes) {
+    // If EXIF is deactivated, display a warning that it is required for this module to function properly.
+    if (!module::is_active("exif") || in_array("exif", $changes->deactivate)) {
+      site_status::warning(
+        t("The CalendarView module requires the EXIF module.  " .
+          "<a href=\"%url\">Activate the EXIF module now</a>",
+          array("url" => html::mark_clean(url::site("admin/modules")))),
+        "calendarview_needs_exif");
+    } else {
+      site_status::clear("calendarview_needs_exif");
+    }
+  }
+
+  static function show_user_profile($data) {
+    // Display a few months on the user profile screen.
+    $v = new View("user_profile_calendarview.html");
+    $v->user_id = $data->user->id;
+
+    // Figure out what month the users newest photo was taken it.
+    //   Make that the last month to display.
+    //   If a user hasn't uploaded anything, make the current month
+    //   the last to be displayed.
+    $latest_photo = ORM::factory("item")
+        ->viewable()
+        ->where("type", "!=", "album")
+        ->where("captured", "!=", "")
+        ->where("owner_id", "=", $data->user->id)
+        ->order_by("captured", "DESC")
+        ->find_all(1);
+    if (count($latest_photo) > 0) {
+      $v->user_year = date('Y', $latest_photo[0]->captured);
+      $v->user_month = date('n', $latest_photo[0]->captured);
+    } else {
+      $v->user_year = date('Y');
+      $v->user_month = date('n');
+    }
+
+    $data->content[] = (object) array("title" => t("User calendar"), "view" => $v);
+  }
+}
diff --git a/modules/calendarview/helpers/calendarview_installer.php b/modules/calendarview/helpers/calendarview_installer.php
new file mode 100644
index 0000000..986a13f
--- /dev/null
+++ b/modules/calendarview/helpers/calendarview_installer.php
@@ -0,0 +1,40 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class calendarview_installer {
+  static function install() {
+    module::set_version("calendarview", 1);
+  }
+
+  static function deactivate() {
+    site_status::clear("calendarview_needs_exif");
+  }
+
+  static function can_activate() {
+    $messages = array();
+    if (!module::is_active("exif")) {
+      $messages["warn"][] = t("The CalendarView module requires the EXIF module.");
+    }
+    return $messages;
+  }
+
+  static function uninstall() {
+    module::delete("calendarview");
+  }
+}
diff --git a/modules/calendarview/helpers/calendarview_theme.php b/modules/calendarview/helpers/calendarview_theme.php
new file mode 100644
index 0000000..d299bf3
--- /dev/null
+++ b/modules/calendarview/helpers/calendarview_theme.php
@@ -0,0 +1,25 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class calendarview_theme_Core {
+  static function head($theme) {
+    return $theme->css("calendarview_calendar.css") . 
+           $theme->css("calendarview_menu.css");
+  }
+}
diff --git a/modules/calendarview/images/ico-view-calendarview.png b/modules/calendarview/images/ico-view-calendarview.png
new file mode 100644
index 0000000..5e564b8
Binary files /dev/null and b/modules/calendarview/images/ico-view-calendarview.png differ
diff --git a/modules/calendarview/libraries/PHPCalendar.php b/modules/calendarview/libraries/PHPCalendar.php
new file mode 100644
index 0000000..2d1df2b
--- /dev/null
+++ b/modules/calendarview/libraries/PHPCalendar.php
@@ -0,0 +1,87 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+
+class PHPCalendar_Core {
+  // Month and year to use for calendaring
+  protected $month;
+  protected $year;
+  protected $month_url;
+
+  // First Day of the Week (0 = Sunday or 1 = Monday).
+  protected $week_start = 0;
+
+  // Events for the current month.
+  protected $event_data = Array();
+
+  public function __construct($month = NULL, $year = NULL, $url = NULL)
+  {
+    empty($month) and $month = date('n'); // Current month
+    empty($year)  and $year  = date('Y'); // Current year
+
+    // Set the month and year
+    $this->month = (int) $month;
+    $this->year  = (int) $year;
+    $this->month_url = $url;
+  }
+
+  public function event($day_of_the_week, $event_url = NULL, $css_id = NULL, $custom_text = NULL) 
+  {
+    $this->event_data += Array($day_of_the_week => Array($event_url, $css_id, $custom_text));
+  }
+
+  public function render()
+  {
+    return $this->generate_calendar($this->year, $this->month, $this->event_data, 2, $this->month_url, $this->week_start, NULL);
+  }
+
+  # PHP Calendar (version 2.3), written by Keith Devens
+  # http://keithdevens.com/software/php_calendar
+  #  see example at http://keithdevens.com/weblog
+  # License: http://keithdevens.com/software/license
+  function generate_calendar($year, $month, $days = array(), $day_name_length = 3, $month_href = NULL, $first_day = 0, $pn = array())
+  {
+    $first_of_month = gmmktime(0,0,0,$month,1,$year);
+    #remember that mktime will automatically correct if invalid dates are entered
+    # for instance, mktime(0,0,0,12,32,1997) will be the date for Jan 1, 1998
+    # this provides a built in "rounding" feature to generate_calendar()
+
+    if ($first_day == 0) $day_names = array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"); 
+    if ($first_day == 1) $day_names = array("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"); 
+
+    list($month, $year, $month_name, $weekday) = explode(',',gmstrftime('%m,%Y,%B,%w',$first_of_month));
+    $weekday = ($weekday + 7 - $first_day) % 7; #adjust for $first_day
+    $title   = t(date("F", mktime(0, 0, 0, $month, 1, $year))) . '&nbsp;' . $year;
+
+    #Begin calendar. Uses a real <caption>. See http://diveintomark.org/archives/2002/07/03
+    @list($p, $pl) = each($pn); @list($n, $nl) = each($pn); #previous and next links, if applicable
+    if($p) $p = '<span class="calendar-prev">'.($pl ? '<a href="'.htmlspecialchars($pl).'">'.$p.'</a>' : $p).'</span>&nbsp;';
+    if($n) $n = '&nbsp;<span class="calendar-next">'.($nl ? '<a href="'.htmlspecialchars($nl).'">'.$n.'</a>' : $n).'</span>';
+    $calendar = '<table class="calendar" id="g-calendar-month">'."\n".
+      '<td class="title" colspan="7" align="center">'.$p.($month_href ? '<a href="'. ($month_href) .'">'.$title.'</a>' : $title).$n."</td></tr>\n<tr>";
+
+    if($day_name_length){ #if the day names should be shown ($day_name_length > 0)
+      #if day_name_length is >3, the full name of the day will be printed
+      foreach($day_names as $d)
+        $calendar .= '<th abbr="' . $d .'">'.t($day_name_length < 4 ? substr($d,0,$day_name_length) : $d) . '</th>';
+      $calendar .= "</tr>\n<tr>";
+    }
+
+    if($weekday > 0) $calendar .= '<td colspan="'.$weekday.'">&nbsp;</td>'; #initial 'empty' days
+    for($day=1,$days_in_month=gmdate('t',$first_of_month); $day<=$days_in_month; $day++,$weekday++){
+      if($weekday == 7){
+        $weekday   = 0; #start a new week
+        $calendar .= "</tr>\n<tr>";
+      }
+      if(isset($days[$day]) and is_array($days[$day])){
+        @list($link, $classes, $content) = $days[$day];
+        if(is_null($content))  $content  = $day;
+          $calendar .= '<td'.($classes ? ' class="'.htmlspecialchars($classes).'">' : '>').
+            ($link ? '<a href="'.htmlspecialchars($link).'">'.$content.'</a>' : $content).'</td>';
+      }
+      else $calendar .= "<td class=\"day\">$day</td>";
+    }
+    if($weekday != 7) $calendar .= '<td colspan="'.(7-$weekday).'">&nbsp;</td>'; #remaining "empty" days
+
+    return $calendar."</tr>\n</table>\n";
+  }
+}
+?>
\ No newline at end of file
diff --git a/modules/calendarview/module.info b/modules/calendarview/module.info
new file mode 100644
index 0000000..f51f162
--- /dev/null
+++ b/modules/calendarview/module.info
@@ -0,0 +1,7 @@
+name = "CalendarView"
+description = "View your photos by the date they were taken."
+version = 1
+author_name = "rWatcher"
+author_url = "http://codex.gallery2.org/User:RWatcher"
+info_url = "http://codex.gallery2.org/Gallery3:Modules:calendarview"
+discuss_url = "http://gallery.menalto.com/node/92405"
diff --git a/modules/calendarview/views/calendarview_sidebar.html.php b/modules/calendarview/views/calendarview_sidebar.html.php
new file mode 100644
index 0000000..b4f1f6f
--- /dev/null
+++ b/modules/calendarview/views/calendarview_sidebar.html.php
@@ -0,0 +1,9 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul>
+  <? if ($day_count > 0): ?>
+  <li><a href="<?=url::site("calendarview/day/" . date("Y", $date) . "/-1/" . date("n", $date) . "/" . date("j", $date)); ?>"><?=t("More from"); ?> <?=date("F", $date); ?> <?=date("j", $date); ?><?=date("S", $date); ?></a></li>
+  <? endif ?>
+  <? if ($month_count > 0): ?>
+  <li><a href="<?=url::site("calendarview/month/" . date("Y", $date) . "/-1/" . date("n", $date)); ?>"><?=t("More from"); ?> <?=date("F", $date); ?></a></li>
+  <? endif ?>
+</ul>
\ No newline at end of file
diff --git a/modules/calendarview/views/calendarview_year.html.php b/modules/calendarview/views/calendarview_year.html.php
new file mode 100644
index 0000000..b40d7d5
--- /dev/null
+++ b/modules/calendarview/views/calendarview_year.html.php
@@ -0,0 +1,95 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-album-header">
+  <div id="g-album-header-buttons">
+    <?= $theme->dynamic_top() ?>
+  </div>
+  <h1><?= html::clean($title) ?></h1>
+</div>
+
+<br/><?= $calendar_user_year_form ?><br /><br />
+
+<?
+  // Search the db for all photos that were taken during the selected year.
+  if ($calendar_user == "-1") {
+    $items_for_year = ORM::factory("item")
+      ->viewable()
+      ->where("type", "!=", "album")
+      ->where("captured", ">=", mktime(0, 0, 0, 1, 1, $calendar_year))
+      ->where("captured", "<", mktime(0, 0, 0, 1, 1, ($calendar_year + 1)))
+      ->order_by("captured")
+      ->find_all();
+  } else {
+    $items_for_year = ORM::factory("item")
+      ->viewable()
+      ->where("owner_id", "=", $calendar_user)
+      ->where("type", "!=", "album")
+      ->where("captured", ">=", mktime(0, 0, 0, 1, 1, $calendar_year))
+      ->where("captured", "<", mktime(0, 0, 0, 1, 1, ($calendar_year + 1)))
+      ->order_by("captured")
+      ->find_all();
+  }
+
+  // Set up some initial variables.
+  $counter_months = 1;
+  $counter_days = 0;
+  $counter = 0;
+  
+  // Set up the January Calendar.
+  //  Check and see if any photos were taken in January, 
+  //  If so, make the month title into a clickable link.
+  print "<div id=\"g-calendar-grid\">";
+  if ((count($items_for_year) > 0) && (date("n", $items_for_year[$counter]->captured) == 1)) {
+    $month_url = url::site("calendarview/month/" . $calendar_year . "/" . $calendar_user . "/" . $counter_months . "/");
+  } else {
+    $month_url = "";
+  }
+  $calendar = new PHPCalendar($counter_months, $calendar_year, $month_url);
+
+  // Loop through each photo taken during this year, and see what month and day they were taken on.
+  //   Make the corresponding dates on the calendars into clickable links.
+  while ($counter < (count($items_for_year))) {
+  
+    // Check and see if we've switched to a new month.
+    //  If so, render the current calendar and set up a new one.
+    while (date("n", $items_for_year[$counter]->captured) > $counter_months) {
+      echo $calendar->render();
+      print "</div>";
+      $counter_months++;
+      $counter_days = 0;
+      print "<div id=\"g-calendar-grid\">";
+      if (date("n", $items_for_year[$counter]->captured) == $counter_months) {
+        $month_url = url::site("calendarview/month/" . $calendar_year . "/" . $calendar_user . "/" . $counter_months . "/");
+      } else {
+        $month_url = "";
+      }
+      $calendar = new PHPCalendar($counter_months, $calendar_year, $month_url);
+    }
+
+    // If the day of the current photo is different then the day of the previous photo, 
+    //   then add a link to the calendar for this date and set the current day to this day.
+    if (date("j", $items_for_year[$counter]->captured) > $counter_days) {
+      $counter_days = date("j", $items_for_year[$counter]->captured);
+      $calendar->event($counter_days, url::site("calendarview/day/" . $calendar_year . "/" . $calendar_user . "/" . $counter_months . "/" . $counter_days));
+    }  
+
+    // Move onto the next photo.
+    $counter++;
+  }
+
+  // Print out the last calendar to be generated.
+  echo $calendar->render();
+  print "</div>";
+  $counter_months++;
+
+  // If the calendar that was previously rendered was not December, 
+  //   then print out a few empty months for the rest of the year.
+  while ($counter_months < 13) {
+    print "<div id=\"g-calendar-grid\">";
+    $month_url = "";
+    $calendar = new PHPCalendar($counter_months, $calendar_year, $month_url);
+    echo $calendar->render();
+    print "</div>";
+    $counter_months++;
+  }
+?>
+<?= $theme->dynamic_bottom() ?>
diff --git a/modules/calendarview/views/user_profile_calendarview.html.php b/modules/calendarview/views/user_profile_calendarview.html.php
new file mode 100644
index 0000000..4d9d68a
--- /dev/null
+++ b/modules/calendarview/views/user_profile_calendarview.html.php
@@ -0,0 +1,86 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?
+  // Generate a list of items within the specified 3 month time-frame.
+  $items = ORM::factory("item")
+    ->viewable()
+    ->where("owner_id", "=", $user_id)
+    ->where("type", "!=", "album")
+    ->where("captured", ">=", mktime(0, 0, 0, $user_month-2, 1, $user_year))
+    ->where("captured", "<", mktime(0, 0, 0, $user_month+1, 1, ($user_year)))
+    ->order_by("captured")
+    ->find_all();
+
+  // Set up some initial variables.
+  $calendar_year = $user_year;
+  $counter_months = $user_month - 2;
+  if ($counter_months < 1) {
+    $counter_months += 12;
+    $calendar_year--;
+  }
+  $counter_days = 0;
+  $counter = 0;
+
+  // Print the first month.
+  print "<div id=\"g-calendar-profile-grid\">";
+  if ((count($items) > 0) && (date("n", $items[$counter]->captured) == $counter_months)) {
+    $month_url = url::site("calendarview/month/" . $calendar_year . "/" . $user_id . "/" . $counter_months . "/");
+  } else {
+    $month_url = "";
+  }
+  $calendar = new PHPCalendar($counter_months, $calendar_year, $month_url);
+
+  // Loop through each photo taken during the 3 month time frame, and see what month and day they were taken on.
+  //   Make the corresponding dates on the calendars into clickable links.
+  while ($counter < (count($items))) {
+
+    // Check and see if we've switched to a new month.
+    //  If so, render the current calendar and set up a new one.
+    //  Continue printing empty months until we reach the next photo or the last month.
+    while (date("n", $items[$counter]->captured) != $counter_months) {
+      echo $calendar->render();
+      print "</div>";
+      $counter_months++;
+      if ($counter_months == 13) {
+        $counter_months = 1;
+        $calendar_year++;
+      }
+      $counter_days = 0;
+      print "<div id=\"g-calendar-profile-grid\">";
+      if (date("n", $items[$counter]->captured) == $counter_months) {
+        $month_url = url::site("calendarview/month/" . $calendar_year . "/" . $user_id . "/" . $counter_months . "/");
+      } else {
+        $month_url = "";
+      }
+      $calendar = new PHPCalendar($counter_months, $calendar_year, $month_url);
+    }
+
+    // If the day of the current photo is different then the day of the previous photo, 
+    //   then add a link to the calendar for this date and set the current day to this day.
+    if (date("j", $items[$counter]->captured) > $counter_days) {
+      $counter_days = date("j", $items[$counter]->captured);
+      $calendar->event($counter_days, url::site("calendarview/day/" . $calendar_year . "/" . $user_id . "/" . $counter_months . "/" . $counter_days));
+    }  
+
+    // Move onto the next photo.
+    $counter++;
+  }
+
+  // Print out the last calendar to be generated.
+  echo $calendar->render();
+  print "</div>";
+  $counter_months++;
+
+  // If the calendar that was previously rendered was not the final month, 
+  //   then print out a few empty months to fill the remaining space.
+  while ($counter_months < $user_month + 1) {
+    print "<div id=\"g-calendar-profile-grid\">";
+    $month_url = "";
+    $calendar = new PHPCalendar($counter_months, $calendar_year, $month_url);
+    echo $calendar->render();
+    print "</div>";
+    $counter_months++;
+  }
+
+?>
+<br clear="all" /><br /><br />
+<div align="right"><a href="<?=url::site("calendarview/calendar/{$user_year}/{$user_id}"); ?>"><?=t("View full calendar"); ?> &gt;&gt;</a></div>
diff --git a/modules/comment/controllers/admin_comments.php b/modules/comment/controllers/admin_comments.php
new file mode 100644
index 0000000..3018340
--- /dev/null
+++ b/modules/comment/controllers/admin_comments.php
@@ -0,0 +1,60 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Comments_Controller extends Admin_Controller {
+  public function index() {
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Comment settings");
+    $view->content = new View("admin_comments.html");
+    $view->content->form = $this->_get_admin_form();
+    print $view;
+  }
+
+  public function save() {
+    access::verify_csrf();
+    $form = $this->_get_admin_form();
+    $form->validate();
+    module::set_var("comment", "access_permissions",
+                    $form->comment_settings->access_permissions->value);
+    module::set_var("comment", "rss_visible",
+                    $form->comment_settings->rss_visible->value);
+    message::success(t("Comment settings updated"));
+    url::redirect("admin/comments");
+  }
+
+  private function _get_admin_form() {
+    $form = new Forge("admin/comments/save", "", "post",
+                      array("id" => "g-comments-admin-form"));
+    $comment_settings = $form->group("comment_settings")->label(t("Permissions"));
+    $comment_settings->dropdown("access_permissions")
+      ->label(t("Who can leave comments?"))
+      ->options(array("everybody" => t("Everybody"),
+                      "registered_users" => t("Only registered users")))
+      ->selected(module::get_var("comment", "access_permissions"));
+    $comment_settings->dropdown("rss_visible")
+      ->label(t("Which RSS feeds can users see?"))
+      ->options(array("all" => t("All comment feeds"),
+                      "newest" => t("New comments feed only"),
+                      "per_item" => t("Comments on photos, movies and albums only")))
+      ->selected(module::get_var("comment", "rss_visible"));
+    $comment_settings->submit("save")->value(t("Save"));
+    return $form;
+  }
+}
+
diff --git a/modules/comment/controllers/admin_manage_comments.php b/modules/comment/controllers/admin_manage_comments.php
new file mode 100644
index 0000000..ef31c95
--- /dev/null
+++ b/modules/comment/controllers/admin_manage_comments.php
@@ -0,0 +1,144 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Manage_Comments_Controller extends Admin_Controller {
+  private static $items_per_page = 20;
+
+  public function index() {
+    // Get rid of old deleted/spam comments once in a while
+    db::build()
+      ->delete("comments")
+      ->where("state", "IN", array("deleted", "spam"))
+      ->where("updated", "<", db::expr("UNIX_TIMESTAMP() - 86400 * 7"))
+      ->execute();
+
+    $view = new Admin_View("admin.html");
+    $view->content = new View("admin_manage_comments.html");
+    $view->content->menu = $this->_menu($this->_counts());
+    print $view;
+  }
+
+  public function menu_labels() {
+    $menu = $this->_menu($this->_counts());
+    json::reply(array((string) $menu->get("unpublished")->label,
+                      (string) $menu->get("published")->label,
+                      (string) $menu->get("spam")->label,
+                      (string) $menu->get("deleted")->label));
+  }
+
+  public function queue($state) {
+    $page = max(Input::instance()->get("page"), 1);
+
+    $view = new Gallery_View("admin_manage_comments_queue.html");
+    $view->counts = $this->_counts();
+    $view->menu = $this->_menu($view->counts);
+    $view->state = $state;
+    $view->comments = ORM::factory("comment")
+      ->order_by("created", "DESC")
+      ->order_by("id", "DESC")
+      ->where("state", "=", $state)
+      ->limit(self::$items_per_page)
+      ->offset(($page - 1) * self::$items_per_page)
+      ->find_all();
+
+    // This view is not themed so we can't use $theme->url() in the view and have to
+    // reproduce Gallery_View::url() logic here.
+    $atn = theme::$admin_theme_name;
+    $view->fallback_avatar_url = url::abs_file("themes/$atn/images/avatar.jpg");
+
+    $view->page = $page;
+    $view->page_type = "collection";
+    $view->page_subtype = "admin_comments";
+    $view->page_size = self::$items_per_page;
+    $view->children_count = $this->_counts()->$state;
+    $view->max_pages = ceil($view->children_count / $view->page_size);
+
+    // Also we want to use $theme->paginator() so we need a dummy theme
+    $view->theme = $view;
+
+    print $view;
+  }
+
+  private function _menu($counts) {
+    return Menu::factory("root")
+      ->append(Menu::factory("link")
+               ->id("unpublished")
+               ->label(t2("Awaiting Moderation (%count)",
+                          "Awaiting Moderation (%count)",
+                          $counts->unpublished))
+               ->url(url::site("admin/manage_comments/queue/unpublished")))
+      ->append(Menu::factory("link")
+               ->id("published")
+               ->label(t2("Approved (%count)",
+                          "Approved (%count)",
+                          $counts->published))
+               ->url(url::site("admin/manage_comments/queue/published")))
+      ->append(Menu::factory("link")
+               ->id("spam")
+               ->label(t2("Spam (%count)",
+                          "Spam (%count)",
+                          $counts->spam))
+               ->url(url::site("admin/manage_comments/queue/spam")))
+      ->append(Menu::factory("link")
+               ->id("deleted")
+               ->label(t2("Recently Deleted (%count)",
+                          "Recently Deleted (%count)",
+                          $counts->deleted))
+               ->url(url::site("admin/manage_comments/queue/deleted")));
+  }
+
+  private function _counts() {
+    $counts = new stdClass();
+    $counts->unpublished = 0;
+    $counts->published = 0;
+    $counts->spam = 0;
+    $counts->deleted = 0;
+    foreach (db::build()
+             ->select("state")
+             ->select(array("c" => 'COUNT("*")'))
+             ->from("comments")
+             ->group_by("state")
+             ->execute() as $row) {
+      $counts->{$row->state} = $row->c;
+    }
+    return $counts;
+  }
+
+  public function set_state($id, $state) {
+    access::verify_csrf();
+
+    $comment = ORM::factory("comment", $id);
+    $orig = clone $comment;
+    if ($comment->loaded()) {
+      $comment->state = $state;
+      $comment->save();
+    }
+  }
+
+  public function delete_all_spam() {
+    access::verify_csrf();
+
+    db::build()
+      ->delete("comments")
+      ->where("state", "=", "spam")
+      ->execute();
+    url::redirect("admin/manage_comments/queue/spam");
+  }
+}
+
diff --git a/modules/comment/controllers/comments.php b/modules/comment/controllers/comments.php
new file mode 100644
index 0000000..64aa0b4
--- /dev/null
+++ b/modules/comment/controllers/comments.php
@@ -0,0 +1,81 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Comments_Controller extends Controller {
+  /**
+   * Add a new comment to the collection.
+   */
+  public function create($id) {
+    $item = ORM::factory("item", $id);
+    access::required("view", $item);
+    if (!comment::can_comment()) {
+      access::forbidden();
+    }
+
+    $form = comment::get_add_form($item);
+    try {
+      $valid = $form->validate();
+      $comment = ORM::factory("comment");
+      $comment->item_id = $id;
+      $comment->author_id = identity::active_user()->id;
+      $comment->text = $form->add_comment->text->value;
+      $comment->guest_name = $form->add_comment->inputs["name"]->value;
+      $comment->guest_email = $form->add_comment->email->value;
+      $comment->guest_url = $form->add_comment->url->value;
+      $comment->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        switch ($key) {
+        case "guest_name":  $key = "name";  break;
+        case "guest_email": $key = "email"; break;
+        case "guest_url":   $key = "url";   break;
+        }
+        $form->add_comment->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      $comment->save();
+      $view = new Theme_View("comment.html", "other", "comment-fragment");
+      $view->comment = $comment;
+
+      json::reply(array("result" => "success",
+                        "view" => (string)$view,
+                        "form" => (string)comment::get_add_form($item)));
+    } else {
+      $form = comment::prefill_add_form($form);
+      json::reply(array("result" => "error", "form" => (string)$form));
+    }
+  }
+
+  /**
+   * Present a form for adding a new comment to this item or editing an existing comment.
+   */
+  public function form_add($item_id) {
+    $item = ORM::factory("item", $item_id);
+    access::required("view", $item);
+    if (!comment::can_comment()) {
+      access::forbidden();
+    }
+
+    print comment::prefill_add_form(comment::get_add_form($item));
+  }
+}
diff --git a/modules/comment/css/comment.css b/modules/comment/css/comment.css
new file mode 100644
index 0000000..db096f2
--- /dev/null
+++ b/modules/comment/css/comment.css
@@ -0,0 +1,45 @@
+#g-content #g-comment-form {
+  margin-top: 2em;
+}
+
+#g-content #g-comments {
+  margin-top: 2em;
+  position: relative;
+}
+
+#g-content #g-comments ul li {
+  margin: 1em 0;
+}
+
+#g-content #g-comments .g-author {
+  border-bottom: 1px solid #ccc;
+  color: #999;
+  height: 32px;
+  line-height: 32px;
+}
+
+#g-content #g-comments ul li div {
+  padding: 0 8px 8px 43px;
+}
+
+#g-content #g-comments .g-avatar {
+  height: 32px;
+  margin-right: .4em;
+  width: 32px;
+}
+
+#g-add-comment {
+  position: absolute;
+  right: 0;
+  top: 2px;
+}
+
+#g-admin-comments-menu {
+  margin: 1em 0;
+}
+
+#g-admin-comments-menu a {
+  margin: 0;
+  padding: .2em .6em;
+}
+
diff --git a/modules/comment/helpers/comment.php b/modules/comment/helpers/comment.php
new file mode 100644
index 0000000..0d922eb
--- /dev/null
+++ b/modules/comment/helpers/comment.php
@@ -0,0 +1,71 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling comments.
+ *
+ * Note: by design, this class does not do any permission checking.
+ */
+class comment_Core {
+  static function get_add_form($item) {
+    $form = new Forge("comments/create/{$item->id}", "", "post", array("id" => "g-comment-form"));
+    $group = $form->group("add_comment")->label(t("Add comment"));
+    $group->input("name")
+      ->label(t("Name"))
+      ->id("g-author")
+      ->error_messages("required", t("You must enter a name for yourself"));
+    $group->input("email")
+      ->label(t("Email (hidden)"))
+      ->id("g-email")
+      ->error_messages("required", t("You must enter a valid email address"))
+      ->error_messages("invalid", t("You must enter a valid email address"));
+    $group->input("url")
+      ->label(t("Website (hidden)"))
+      ->id("g-url")
+      ->error_messages("url", t("You must enter a valid url"));
+    $group->textarea("text")
+      ->label(t("Comment"))
+      ->id("g-text")
+      ->error_messages("required", t("You must enter a comment"));
+    $group->hidden("item_id")->value($item->id);
+    module::event("comment_add_form", $form);
+    module::event("captcha_protect_form", $form);
+    $group->submit("")->value(t("Add"))->class("ui-state-default ui-corner-all");
+
+    return $form;
+  }
+
+  static function prefill_add_form($form) {
+    $active = identity::active_user();
+    if (!$active->guest) {
+      $group = $form->add_comment;
+      $group->inputs["name"]->value($active->full_name)->disabled("disabled");
+      $group->email->value($active->email)->disabled("disabled");
+      $group->url->value($active->url)->disabled("disabled");
+    }
+    return $form;
+  }
+
+  static function can_comment() {
+    return !identity::active_user()->guest ||
+      module::get_var("comment", "access_permissions") == "everybody";
+  }
+}
+
diff --git a/modules/comment/helpers/comment_block.php b/modules/comment/helpers/comment_block.php
new file mode 100644
index 0000000..b602595
--- /dev/null
+++ b/modules/comment/helpers/comment_block.php
@@ -0,0 +1,39 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class comment_block_Core {
+  static function get_admin_list() {
+    return array("recent_comments" => t("Recent comments"));
+  }
+
+  static function get($block_id) {
+    $block = new Block();
+    switch ($block_id) {
+    case "recent_comments":
+      $block->css_id = "g-recent-comments";
+      $block->title = t("Recent comments");
+      $block->content = new View("admin_block_recent_comments.html");
+      $block->content->comments =
+        ORM::factory("comment")->order_by("created", "DESC")->limit(5)->find_all();
+      break;
+    }
+
+    return $block;
+  }
+}
\ No newline at end of file
diff --git a/modules/comment/helpers/comment_event.php b/modules/comment/helpers/comment_event.php
new file mode 100644
index 0000000..f73e545
--- /dev/null
+++ b/modules/comment/helpers/comment_event.php
@@ -0,0 +1,97 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class comment_event_Core {
+  static function item_deleted($item) {
+    db::build()
+      ->delete("comments")
+      ->where("item_id", "=", $item->id)
+      ->execute();
+  }
+
+  static function user_deleted($user) {
+    $guest = identity::guest();
+    if (!empty($guest)) {          // could be empty if there is not identity provider
+      db::build()
+        ->update("comments")
+        ->set("author_id", $guest->id)
+        ->set("guest_email", null)
+        ->set("guest_name", "guest")
+        ->set("guest_url", null)
+        ->where("author_id", "=", $user->id)
+        ->execute();
+    }
+  }
+
+  static function identity_provider_changed($old_provider, $new_provider) {
+    $guest = identity::guest();
+    db::build()
+      ->update("comments")
+      ->set("author_id", $guest->id)
+      ->set("guest_email", null)
+      ->set("guest_name", "guest")
+      ->set("guest_url", null)
+      ->execute();
+  }
+
+  static function admin_menu($menu, $theme) {
+    $menu->get("settings_menu")
+      ->append(Menu::factory("link")
+               ->id("comment")
+               ->label(t("Comments"))
+               ->url(url::site("admin/comments")));
+
+    $menu->get("content_menu")
+      ->append(Menu::factory("link")
+               ->id("comments")
+               ->label(t("Comments"))
+               ->url(url::site("admin/manage_comments")));
+  }
+
+  static function photo_menu($menu, $theme) {
+    $menu
+      ->append(Menu::factory("link")
+               ->id("comments")
+               ->label(t("View comments on this item"))
+               ->url("#comments")
+               ->css_id("g-comments-link"));
+  }
+
+  static function item_index_data($item, $data) {
+    foreach (db::build()
+             ->select("text")
+             ->from("comments")
+             ->where("item_id", "=", $item->id)
+             ->execute() as $row) {
+      $data[] = $row->text;
+    }
+  }
+
+  static function show_user_profile($data) {
+    $view = new View("user_profile_comments.html");
+    $view->comments = ORM::factory("comment")
+      ->order_by("created", "DESC")
+      ->where("state", "=", "published")
+      ->where("author_id", "=", $data->user->id)
+      ->find_all();
+    if ($view->comments->count()) {
+      $data->content[] = (object)array("title" => t("Comments"), "view" => $view);
+    }
+  }
+}
diff --git a/modules/comment/helpers/comment_installer.php b/modules/comment/helpers/comment_installer.php
new file mode 100644
index 0000000..136f96e
--- /dev/null
+++ b/modules/comment/helpers/comment_installer.php
@@ -0,0 +1,118 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class comment_installer {
+  static function install() {
+    $db = Database::instance();
+    $db->query("CREATE TABLE IF NOT EXISTS {comments} (
+                 `author_id` int(9) default NULL,
+                 `created` int(9) NOT NULL,
+                 `guest_email` varchar(128) default NULL,
+                 `guest_name` varchar(128) default NULL,
+                 `guest_url` varchar(255) default NULL,
+                 `id` int(9) NOT NULL auto_increment,
+                 `item_id` int(9) NOT NULL,
+                 `server_http_accept_charset` varchar(64) default NULL,
+                 `server_http_accept_encoding` varchar(64) default NULL,
+                 `server_http_accept_language` varchar(64) default NULL,
+                 `server_http_accept` varchar(128) default NULL,
+                 `server_http_connection` varchar(64) default NULL,
+                 `server_http_host` varchar(64) default NULL,
+                 `server_http_referer` varchar(255) default NULL,
+                 `server_http_user_agent` varchar(128) default NULL,
+                 `server_query_string` varchar(64) default NULL,
+                 `server_remote_addr` varchar(40) default NULL,
+                 `server_remote_host` varchar(255) default NULL,
+                 `server_remote_port` varchar(16) default NULL,
+                 `state` varchar(15) default 'unpublished',
+                 `text` text,
+                 `updated` int(9) NOT NULL,
+               PRIMARY KEY (`id`))
+               DEFAULT CHARSET=utf8;");
+
+    module::set_var("comment", "spam_caught", 0);
+    module::set_var("comment", "access_permissions", "everybody");
+    module::set_var("comment", "rss_visible", "all");
+  }
+
+  static function upgrade($version) {
+    $db = Database::instance();
+    if ($version == 1) {
+      $db->query("ALTER TABLE {comments} CHANGE `state` `state` varchar(15) default 'unpublished'");
+      module::set_version("comment", $version = 2);
+    }
+
+    if ($version == 2) {
+      module::set_var("comment", "access_permissions", "everybody");
+      module::set_version("comment", $version = 3);
+    }
+
+    if ($version == 3) {
+      // 40 bytes for server_remote_addr is enough to swallow the longest
+      // representation of an IPv6 addy.
+      //
+      // 255 bytes for server_remote_host is enough to swallow the longest
+      // legit DNS entry, with a few bytes to spare.
+      $db->query(
+        "ALTER TABLE {comments} CHANGE `server_remote_addr` `server_remote_addr` varchar(40)");
+      $db->query(
+        "ALTER TABLE {comments} CHANGE `server_remote_host` `server_remote_host` varchar(255)");
+      module::set_version("comment", $version = 4);
+    }
+
+    if ($version == 4) {
+      module::set_var("comment", "rss_visible", "all");
+      module::set_version("comment", $version = 5);
+    }
+
+    // In version 5 we accidentally set the installer variable to rss_available when it should
+    // have been rss_visible.  Migrate it over now, if necessary.
+    if ($version == 5) {
+      if (!module::get_var("comment", "rss_visible")) {
+        module::set_var("comment", "rss_visible", module::get_var("comment", "rss_available"));
+      }
+      module::clear_var("comment", "rss_available");
+      module::set_version("comment", $version = 6);
+    }
+
+    // In version 6 we accidentally left the install value of "rss_visible" to "both" when it
+    // should have been "all"
+    if ($version == 6) {
+      if (module::get_var("comment", "rss_visible") == "both") {
+        module::set_var("comment", "rss_visible", "all");
+      }
+      module::set_version("comment", $version = 7);
+    }
+  }
+
+  static function uninstall() {
+    $db = Database::instance();
+
+    // Notify listeners that we're deleting some data.  This is probably going to be very
+    // inefficient for large uninstalls, and we could make it better by doing things like passing
+    // a SQL fragment through so that the listeners could use subselects.  But by using a single,
+    // simple event API we lighten the load on module developers.
+    foreach (ORM::factory("item")
+             ->join("comments", "items.id", "comments.item_id")
+             ->find_all() as $item) {
+      module::event("item_related_update", $item);
+    }
+    $db->query("DROP TABLE IF EXISTS {comments};");
+  }
+}
diff --git a/modules/comment/helpers/comment_rest.php b/modules/comment/helpers/comment_rest.php
new file mode 100644
index 0000000..1971edc
--- /dev/null
+++ b/modules/comment/helpers/comment_rest.php
@@ -0,0 +1,74 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class comment_rest_Core {
+  static function get($request) {
+    $comment = rest::resolve($request->url);
+    access::required("view", $comment->item());
+
+    return array(
+      "url" => $request->url,
+      "entity" => $comment->as_restful_array(),
+      "relationships" => rest::relationships("comment", $comment));
+  }
+
+  static function put($request) {
+    // Only admins can edit comments, for now
+    if (!identity::active_user()->admin) {
+      access::forbidden();
+    }
+
+    $comment = rest::resolve($request->url);
+    $comment = ORM::factory("comment");
+    $comment->text = $request->params->text;
+    $comment->save();
+  }
+
+  static function delete($request) {
+    if (!identity::active_user()->admin) {
+      access::forbidden();
+    }
+
+    $comment = rest::resolve($request->url);
+    access::required("edit", $comment->item());
+
+    $comment->delete();
+  }
+
+  static function relationships($resource_type, $resource) {
+    switch ($resource_type) {
+    case "item":
+      return array(
+        "comments" => array(
+          "url" => rest::url("item_comments", $resource)));
+    }
+  }
+
+  static function resolve($id) {
+    $comment = ORM::factory("comment", $id);
+    if (!access::can("view", $comment->item())) {
+      throw new Kohana_404_Exception();
+    }
+    return $comment;
+  }
+
+  static function url($comment) {
+    return url::abs_site("rest/comment/{$comment->id}");
+  }
+}
diff --git a/modules/comment/helpers/comment_rss.php b/modules/comment/helpers/comment_rss.php
new file mode 100644
index 0000000..924710f
--- /dev/null
+++ b/modules/comment/helpers/comment_rss.php
@@ -0,0 +1,92 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class comment_rss_Core {
+  static function feed_visible($feed_id) {
+    $visible = module::get_var("comment", "rss_visible");
+    if (!in_array($feed_id, array("newest", "per_item"))) {
+      return false;
+    }
+
+    return ($visible == "all" || $visible == $feed_id);
+  }
+
+  static function available_feeds($item, $tag) {
+    $feeds = array();
+
+    if (comment_rss::feed_visible("newest")) {
+      $feeds["comment/newest"] = t("All new comments");
+    }
+
+    if ($item && comment_rss::feed_visible("per_item")) {
+      $feeds["comment/per_item/$item->id"] =
+        t("Comments on %title", array("title" => html::purify($item->title)));
+    }
+    return $feeds;
+  }
+
+  static function feed($feed_id, $offset, $limit, $id) {
+    if (!comment_rss::feed_visible($feed_id)) {
+      return;
+    }
+
+    $comments = ORM::factory("comment")
+      ->viewable()
+      ->where("comments.state", "=", "published")
+      ->order_by("comments.created", "DESC");
+
+    if ($feed_id == "item") {
+      $item = ORM::factory("item", $id);
+      $comments
+        ->where("items.left_ptr", ">=", $item->left_ptr)
+        ->where("items.right_ptr", "<=", $item->right_ptr);
+    }
+
+    $feed = new stdClass();
+    $feed->view = "comment.mrss";
+    $feed->comments = array();
+    foreach ($comments->find_all($limit, $offset) as $comment) {
+      $item = $comment->item();
+      $feed->comments[] = new ArrayObject(
+        array("pub_date" => date("D, d M Y H:i:s O", $comment->created),
+              "text" => nl2br(html::purify($comment->text)),
+              "thumb_url" => $item->thumb_url(),
+              "thumb_height" => $item->thumb_height,
+              "thumb_width" => $item->thumb_width,
+              "item_uri" => url::abs_site("{$item->type}s/$item->id"),
+              "title" => (
+                ($item->id == item::root()->id) ?
+                html::purify($item->title) :
+                t("%site_title - %item_title",
+                  array("site_title" => item::root()->title,
+                        "item_title" => $item->title))),
+              "author" => html::clean($comment->author_name())),
+        ArrayObject::ARRAY_AS_PROPS);
+    }
+
+    $feed->max_pages = ceil($comments->count_all() / $limit);
+    $feed->title = html::purify(t("%site_title - Recent Comments",
+                                 array("site_title" => item::root()->title)));
+    $feed->uri = url::abs_site("albums/" . (empty($id) ? "1" : $id));
+    $feed->description = t("Recent comments");
+
+    return $feed;
+  }
+}
diff --git a/modules/comment/helpers/comment_theme.php b/modules/comment/helpers/comment_theme.php
new file mode 100644
index 0000000..1c2d7c5
--- /dev/null
+++ b/modules/comment/helpers/comment_theme.php
@@ -0,0 +1,46 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class comment_theme_Core {
+  static function head($theme) {
+    return $theme->css("comment.css")
+      . $theme->script("comment.js");
+  }
+
+  static function admin_head($theme) {
+    return $theme->css("comment.css");
+  }
+
+  static function photo_bottom($theme) {
+    $block = new Block;
+    $block->css_id = "g-comments";
+    $block->title = t("Comments");
+    $block->anchor = "comments";
+
+    $view = new View("comments.html");
+    $view->comments = ORM::factory("comment")
+      ->where("item_id", "=", $theme->item()->id)
+      ->where("state", "=", "published")
+      ->order_by("created", "ASC")
+      ->find_all();
+
+    $block->content = $view;
+    return $block;
+  }
+}
\ No newline at end of file
diff --git a/modules/comment/helpers/comments_rest.php b/modules/comment/helpers/comments_rest.php
new file mode 100644
index 0000000..6fc86ad
--- /dev/null
+++ b/modules/comment/helpers/comments_rest.php
@@ -0,0 +1,62 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class comments_rest_Core {
+  /**
+   * Possible request parameters:
+   *   start=#
+   *     start at the Nth comment (zero based)
+   *
+   *   num=#
+   *     return up to N comments (max 100)
+   */
+  static function get($request) {
+    $comments = array();
+
+    $p = $request->params;
+    $num = isset($p->num) ? min((int)$p->num, 100) : 10;
+    $start = isset($p->start) ? (int)$p->start : 0;
+
+    foreach (ORM::factory("comment")->viewable()->find_all($num, $start) as $comment) {
+      $comments[] = rest::url("comment", $comment);
+    }
+    return array("url" => rest::url("comments"),
+                 "members" => $comments);
+  }
+
+
+  static function post($request) {
+    $entity = $request->params->entity;
+
+    $item = rest::resolve($entity->item);
+    access::required("edit", $item);
+
+    $comment = ORM::factory("comment");
+    $comment->author_id = identity::active_user()->id;
+    $comment->item_id = $item->id;
+    $comment->text = $entity->text;
+    $comment->save();
+
+    return array("url" => rest::url("comment", $comment));
+  }
+
+  static function url() {
+    return url::abs_site("rest/comments");
+  }
+}
diff --git a/modules/comment/helpers/item_comments_rest.php b/modules/comment/helpers/item_comments_rest.php
new file mode 100644
index 0000000..f6f8930
--- /dev/null
+++ b/modules/comment/helpers/item_comments_rest.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class item_comments_rest_Core {
+  static function get($request) {
+    $item = rest::resolve($request->url);
+    access::required("view", $item);
+
+    $comments = array();
+    foreach (ORM::factory("comment")
+             ->viewable()
+             ->where("item_id", "=", $item->id)
+             ->order_by("created", "DESC")
+             ->find_all() as $comment) {
+      $comments[] = rest::url("comment", $comment);
+    }
+
+    return array(
+      "url" => $request->url,
+      "members" => $comments);
+  }
+
+  static function resolve($id) {
+    $item = ORM::factory("item", $id);
+    if (!access::can("view", $item)) {
+      throw new Kohana_404_Exception();
+    }
+    return $item;
+  }
+
+  static function url($item) {
+    return url::abs_site("rest/item_comments/{$item->id}");
+  }
+}
diff --git a/modules/comment/js/comment.js b/modules/comment/js/comment.js
new file mode 100644
index 0000000..2487c5f
--- /dev/null
+++ b/modules/comment/js/comment.js
@@ -0,0 +1,45 @@
+$("document").ready(function() {
+  $("#g-add-comment").click(function(event) {
+    event.preventDefault();
+    if (!$("#g-comment-form").length) {
+      $.get($(this).attr("href"),
+	    {},
+	    function(data) {
+	      $("#g-comment-detail").append(data);
+	      ajaxify_comment_form();
+        $.scrollTo("#g-comment-form-anchor", 800);
+	    });
+    }
+  });
+  $(".g-no-comments a").click(function(event) {
+    event.preventDefault();
+    if (!$("#g-comment-form").length) {
+      $.get($(this).attr("href"),
+	    {},
+	    function(data) {
+	      $("#g-comment-detail").append(data);
+	      ajaxify_comment_form();
+	    });
+      $(".g-no-comments").remove();
+    }
+  });
+});
+
+function ajaxify_comment_form() {
+  $("#g-comments form").ajaxForm({
+    dataType: "json",
+    success: function(data) {
+      if (data.result == "success") {
+        $("#g-comments #g-comment-detail ul").append(data.view);
+        $("#g-comments #g-comment-detail ul li:last").effect("highlight", {color: "#cfc"}, 8000);
+        $("#g-comment-form").hide(2000).remove();
+        $("#g-no-comments").hide(2000);
+      } else {
+        if (data.form) {
+          $("#g-comments form").replaceWith(data.form);
+          ajaxify_comment_form();
+        }
+      }
+    }
+  });
+}
diff --git a/modules/comment/models/comment.php b/modules/comment/models/comment.php
new file mode 100644
index 0000000..62ab8bc
--- /dev/null
+++ b/modules/comment/models/comment.php
@@ -0,0 +1,194 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Comment_Model_Core extends ORM {
+  function item() {
+    return ORM::factory("item", $this->item_id);
+  }
+
+  function author() {
+    return identity::lookup_user($this->author_id);
+  }
+
+  function author_name() {
+    $author = $this->author();
+    if ($author->guest) {
+      return $this->guest_name;
+    } else {
+      return $author->display_name();
+    }
+  }
+
+  function author_email() {
+    $author = $this->author();
+    if ($author->guest) {
+      return $this->guest_email;
+    } else {
+      return $author->email;
+    }
+  }
+
+  function author_url() {
+    $author = $this->author();
+    if ($author->guest) {
+      return $this->guest_url;
+    } else {
+      return $author->url;
+    }
+  }
+
+  /**
+   * Add some custom per-instance rules.
+   */
+  public function validate(Validation $array=null) {
+    // validate() is recursive, only modify the rules on the outermost call.
+    if (!$array) {
+      $this->rules = array(
+        "guest_name"  => array("callbacks" => array(array($this, "valid_author"))),
+        "guest_email" => array("callbacks" => array(array($this, "valid_email"))),
+        "guest_url"   => array("rules"     => array("url")),
+        "item_id"     => array("callbacks" => array(array($this, "valid_item"))),
+        "state"       => array("rules"     => array("Comment_Model::valid_state")),
+        "text"        => array("rules"     => array("required")),
+      );
+    }
+
+    parent::validate($array);
+  }
+
+  /**
+   * @see ORM::save()
+   */
+  public function save() {
+    $this->updated = time();
+    if (!$this->loaded()) {
+      // New comment
+      $this->created = $this->updated;
+      if (empty($this->state)) {
+        $this->state = "published";
+      }
+
+      // These values are useful for spam fighting, so save them with the comment.  It's painful to
+      // check each one to see if it already exists before setting it, so just use server_http_host
+      // as a semaphore for now (we use that in g2_import.php)
+      if (empty($this->server_http_host)) {
+        $input = Input::instance();
+        $this->server_http_accept = substr($input->server("HTTP_ACCEPT"), 0, 128);
+        $this->server_http_accept_charset = substr($input->server("HTTP_ACCEPT_CHARSET"), 0, 64);
+        $this->server_http_accept_encoding = substr($input->server("HTTP_ACCEPT_ENCODING"), 0, 64);
+        $this->server_http_accept_language = substr($input->server("HTTP_ACCEPT_LANGUAGE"), 0, 64);
+        $this->server_http_connection = substr($input->server("HTTP_CONNECTION"), 0, 64);
+        $this->server_http_host = substr($input->server("HTTP_HOST"), 0, 64);
+        $this->server_http_referer = substr($input->server("HTTP_REFERER"), 0, 255);
+        $this->server_http_user_agent = substr($input->server("HTTP_USER_AGENT"), 0, 128);
+        $this->server_query_string = substr($input->server("QUERY_STRING"), 0, 64);
+        $this->server_remote_addr = substr($input->server("REMOTE_ADDR"), 0, 40);
+        $this->server_remote_host = substr($input->server("REMOTE_HOST"), 0, 255);
+        $this->server_remote_port = substr($input->server("REMOTE_PORT"), 0, 16);
+      }
+
+      $visible_change = $this->state == "published";
+      parent::save();
+      module::event("comment_created", $this);
+    } else {
+      // Updated comment
+      $original = ORM::factory("comment", $this->id);
+      $visible_change = $original->state == "published" || $this->state == "published";
+      parent::save();
+      module::event("comment_updated", $original, $this);
+    }
+
+    // We only notify on the related items if we're making a visible change.
+    if ($visible_change) {
+      $item = $this->item();
+      module::event("item_related_update", $item);
+    }
+
+    return $this;
+  }
+
+  /**
+   * Add a set of restrictions to any following queries to restrict access only to items
+   * viewable by the active user.
+   * @chainable
+   */
+  public function viewable() {
+    $this->join("items", "items.id", "comments.item_id");
+    return item::viewable($this);
+  }
+
+  /**
+   * Make sure we have an appropriate author id set, or a guest name.
+   */
+  public function valid_author(Validation $v, $field) {
+    if (empty($this->author_id)) {
+      $v->add_error("author_id", "required");
+    } else if ($this->author_id == identity::guest()->id && empty($this->guest_name)) {
+      $v->add_error("guest_name", "required");
+    }
+  }
+
+  /**
+   * Make sure that the email address is legal.
+   */
+  public function valid_email(Validation $v, $field) {
+    if ($this->author_id == identity::guest()->id) {
+      if (empty($v->guest_email)) {
+        $v->add_error("guest_email", "required");
+      } else if (!valid::email($v->guest_email)) {
+        $v->add_error("guest_email", "invalid");
+      }
+    }
+  }
+
+  /**
+   * Make sure we have a valid associated item id.
+   */
+  public function valid_item(Validation $v, $field) {
+    if (db::build()
+        ->from("items")
+        ->where("id", "=", $this->item_id)
+        ->count_records() != 1) {
+      $v->add_error("item_id", "invalid");
+    }
+  }
+
+  /**
+   * Make sure that the state is legal.
+   */
+  static function valid_state($value) {
+    return in_array($value, array("published", "unpublished", "spam", "deleted"));
+  }
+
+  /**
+   * Same as ORM::as_array() but convert id fields into their RESTful form.
+   */
+  public function as_restful_array() {
+    $data = array();
+    foreach ($this->as_array() as $key => $value) {
+      if (strncmp($key, "server_", 7)) {
+        $data[$key] = $value;
+      }
+    }
+    $data["item"] = rest::url("item", $this->item());
+    unset($data["item_id"]);
+
+    return $data;
+  }
+}
diff --git a/modules/comment/module.info b/modules/comment/module.info
new file mode 100644
index 0000000..b69379f
--- /dev/null
+++ b/modules/comment/module.info
@@ -0,0 +1,7 @@
+name = "Comments"
+description = "Allows users and guests to leave comments on photos and albums."
+version = 7
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:comment"
+discuss_url = "http://galleryproject.org/forum_module_comment"
diff --git a/modules/comment/views/admin_block_recent_comments.html.php b/modules/comment/views/admin_block_recent_comments.html.php
new file mode 100644
index 0000000..4017e4f
--- /dev/null
+++ b/modules/comment/views/admin_block_recent_comments.html.php
@@ -0,0 +1,23 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul>
+  <? foreach ($comments as $comment): ?>
+  <li class="<?= text::alternate("g-even", "g-odd") ?>">
+    <img src="<?= $comment->author()->avatar_url(32, $theme->url("images/avatar.jpg", true)) ?>"
+         class="g-avatar"
+         alt="<?= html::clean_attribute($comment->author_name()) ?>"
+         width="32"
+         height="32" />
+    <?= gallery::date_time($comment->created) ?>
+    <? if ($comment->author()->guest): ?>
+    <?= t('%author_name said <em>%comment_text</em>',
+          array("author_name" => html::clean($comment->author_name()),
+                "comment_text" => text::limit_words(nl2br(html::purify($comment->text)), 50))); ?>
+    <? else: ?>
+    <?= t('<a href="%url">%author_name</a> said <em>%comment_text</em>',
+          array("author_name" => html::clean($comment->author_name()),
+                "url" => user_profile::url($comment->author_id),
+                "comment_text" => text::limit_words(nl2br(html::purify($comment->text)), 50))); ?>
+    <? endif ?>
+  </li>
+  <? endforeach ?>
+</ul>
diff --git a/modules/comment/views/admin_comments.html.php b/modules/comment/views/admin_comments.html.php
new file mode 100644
index 0000000..dc6985b
--- /dev/null
+++ b/modules/comment/views/admin_comments.html.php
@@ -0,0 +1,7 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="g-block">
+  <h1> <?= t("Comment settings") ?> </h1>
+  <div class="g-block-content">
+    <?= $form ?>
+  </div>
+</div>
diff --git a/modules/comment/views/admin_manage_comments.html.php b/modules/comment/views/admin_manage_comments.html.php
new file mode 100644
index 0000000..e3c8546
--- /dev/null
+++ b/modules/comment/views/admin_manage_comments.html.php
@@ -0,0 +1,46 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  var set_state_url =
+    <?= html::js_string(url::site("admin/manage_comments/set_state/__ID__/__STATE__?csrf=$csrf")) ?>;
+  var set_state = function(state, id) {
+    $("#g-comment-" + id).fadeOut("fast", function() {
+      $.get(set_state_url.replace("__STATE__", state).replace("__ID__", id),
+          {},
+          update_menu);
+      });
+  }
+
+  var update_menu = function() {
+    $.get(<?= html::js_string(url::site("admin/manage_comments/menu_labels")) ?>, {},
+          function(data) {
+            for (var i = 0; i < data.length; i++) {
+              $("#g-admin-comments ul li:eq(" + i + ") a").html(data[i]);
+            }
+          },
+          "json");
+  }
+
+  // Paginator clicks load their href in the active tab panel
+  var fix_links = function() {
+    $(".g-paginator a, a#g-delete-all-spam").click(function(event) {
+      event.stopPropagation();
+      $.scrollTo(0, 800, { easing: "swing" });
+      $(this).parents(".ui-tabs-panel").load(
+        $(this).attr("href"),
+        function() {
+          fix_links();
+        });
+      return false;
+    });
+  }
+
+  $(document).ready(function() {
+    $("#g-admin-comments").tabs({
+      show: fix_links,
+    });
+  });
+</script>
+
+<div id="g-admin-comments" class="g-block">
+  <?= $menu->render() ?>
+</div>
diff --git a/modules/comment/views/admin_manage_comments_queue.html.php b/modules/comment/views/admin_manage_comments_queue.html.php
new file mode 100644
index 0000000..d847d72
--- /dev/null
+++ b/modules/comment/views/admin_manage_comments_queue.html.php
@@ -0,0 +1,157 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="g-block-content">
+  <? if ($state == "spam"): ?>
+  <div>
+    <? $spam_caught = module::get_var("comment", "spam_caught") ?>
+    <? if ($spam_caught > 0): ?>
+    <p>
+      <?= t2("Gallery has caught %count spam for you since you installed spam filtering.",
+             "Gallery has caught %count spam for you since you installed spam filtering.",
+             $spam_caught) ?>
+    </p>
+    <? endif ?>
+    <p>
+      <? if ($counts->spam): ?>
+      <?= t2("There is currently one comment in your spam queue.  You can delete it with a single click, but there is no undo operation so you may want to check the message first to make sure that it really is spam.",
+             "There are currently %count comments in your spam queue.  You can delete them all with a single click, but there is no undo operation so you may want to check the messages first to make sure that they really are spam.  All spam messages will be deleted after 7 days automatically.",
+             $counts->spam) ?>
+    </p>
+    <p>
+      <a id="g-delete-all-spam"
+         href="<?= url::site("admin/manage_comments/delete_all_spam?csrf=$csrf") ?>">
+        <?= t("Delete all spam") ?>
+      </a>
+      <? else: ?>
+      <?= t("Your spam queue is empty!") ?>
+      <? endif ?>
+    </p>
+  </div>
+  <? endif ?>
+
+  <? if ($state == "deleted"): ?>
+  <div>
+    <p>
+      <?= t("These are messages that have been recently deleted.  They will be permanently erased automatically after 7 days.") ?>
+    </p>
+  </div>
+  <? endif ?>
+
+  <div class="g-paginator">
+    <?= $theme->paginator() ?>
+  </div>
+  <table id="g-admin-comments-list">
+    <tr>
+      <th>
+        <?= t("Author") ?>
+      </th>
+      <th>
+        <?= t("Comment") ?>
+      </th>
+      <th>
+        <?= t("Actions") ?>
+      </th>
+    </tr>
+    <? foreach ($comments as $comment): ?>
+    <tr id="g-comment-<?= $comment->id ?>" class="<?= text::alternate("g-odd", "g-even") ?>">
+      <td>
+        <a href="#">
+          <img src="<?= $comment->author()->avatar_url(40, $fallback_avatar_url) ?>"
+               class="g-avatar"
+               alt="<?= html::clean_attribute($comment->author_name()) ?>"
+               width="40"
+               height="40" />
+        </a>
+        <p>
+          <a href="mailto:<?= html::clean_attribute($comment->author_email()) ?>"
+             title="<?= html::clean_attribute($comment->author_email()) ?>">
+            <?= html::clean($comment->author_name()) ?>
+          </a>
+        </p>
+      </td>
+      <td>
+        <div class="g-right">
+          <? $item = $comment->item() ?>
+          <div class="g-item g-photo">
+            <a href="<?= $item->url() ?>">
+              <? if ($item->has_thumb()): ?>
+              <img src="<?= $item->thumb_url() ?>"
+                 alt="<?= html::purify($item->title)->for_html_attr() ?>"
+                 <?= photo::img_dimensions($item->thumb_width, $item->thumb_height, 75) ?>
+              />
+              <? else: ?>
+              <?= t("No thumbnail") ?>
+              <? endif ?>
+            </a>
+          </div>
+        </div>
+        <p><?= gallery::date($comment->created) ?></p>
+           <?= nl2br(html::purify($comment->text)) ?>
+      </td>
+      <td>
+        <ul class="g-buttonset-vertical">
+        <? if ($comment->state != "unpublished" && $comment->state != "deleted"): ?>
+          <li>
+            <a href="javascript:set_state('unpublished',<?=$comment->id?>)"
+                class="g-button ui-state-default ui-icon-left">
+              <span class="ui-icon ui-icon-check"></span>
+              <?= t("Unapprove") ?>
+            </a>
+          </li>
+        <? endif ?>
+        <? if ($comment->state != "published"): ?>
+          <li>
+            <a href="javascript:set_state('published',<?=$comment->id?>)"
+                class="g-button ui-state-default ui-icon-left">
+              <span class="ui-icon ui-icon-check"></span>
+              <? if ($state == "deleted"): ?>
+              <?= t("Undelete") ?>
+              <? else: ?>
+              <?= t("Approve") ?>
+              <? endif ?>
+            </a>
+          </li>
+        <? endif ?>
+        <? if ($comment->state != "spam"): ?>
+          <li>
+            <a href="javascript:set_state('spam',<?=$comment->id?>)"
+                class="g-button ui-state-default ui-icon-left">
+              <span class="ui-icon ui-icon-cancel"></span>
+              <?= t("Spam") ?>
+            </a>
+          </li>
+        <? endif ?>
+          <!--
+          <li>
+            <a href="javascript:reply(<?=$comment->id?>)"
+                class="g-button ui-state-default ui-icon-left">
+              <span class="ui-icon ui-icon-arrowreturnthick-1-w"></span>
+              <?= t("Reply") ?>
+            </a>
+          </li>
+          <li>
+            <a href="javascript:Edit(<?=$comment->id?>)"
+                class="g-button ui-state-default ui-icon-left">
+              <span class="ui-icon ui-icon-pencil"></span>
+              <?= t("Edit") ?>
+            </a>
+          </li>
+          -->
+        <? if ($comment->state != "deleted"): ?>
+          <li>
+            <a href="javascript:set_state('deleted',<?=$comment->id?>)"
+                class="g-button ui-state-default ui-icon-left">
+              <span class="ui-icon ui-icon-trash"></span>
+              <?= t("Delete") ?>
+            </a>
+          </li>
+        <? endif ?>
+        </ul>
+      </td>
+    </tr>
+    <? endforeach ?>
+  </table>
+
+  <div class="g-paginator">
+    <?= $theme->paginator() ?>
+  </div>
+</div>
diff --git a/modules/comment/views/comment.html.php b/modules/comment/views/comment.html.php
new file mode 100644
index 0000000..263e5f9
--- /dev/null
+++ b/modules/comment/views/comment.html.php
@@ -0,0 +1,25 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<li id="g-comment-<?= $comment->id; ?>">
+  <p class="g-author">
+    <a href="#">
+      <img src="<?= $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>"
+           class="g-avatar"
+           alt="<?= html::clean_attribute($comment->author_name()) ?>"
+           width="40"
+           height="40" />
+    </a>
+    <? if ($comment->author()->guest): ?>
+    <?= t("on %date_time, %name said",
+          array("date_time" => gallery::date_time($comment->created),
+                "name" => html::clean($comment->author_name()))) ?>
+    <? else: ?>
+    <?= t("on %date_time,  <a href=\"%url\">%name</a> said",
+          array("date_time" => gallery::date_time($comment->created),
+                "url" => user_profile::url($comment->author_id),
+                "name" => html::clean($comment->author_name()))) ?>
+    <? endif ?>
+  </p>
+  <div>
+  <?= nl2br(html::purify($comment->text)) ?>
+  </div>
+</li>
diff --git a/modules/comment/views/comment.mrss.php b/modules/comment/views/comment.mrss.php
new file mode 100644
index 0000000..809e789
--- /dev/null
+++ b/modules/comment/views/comment.mrss.php
@@ -0,0 +1,43 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? echo "<?xml version=\"1.0\" ?>" ?>
+<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"
+   xmlns:atom="http://www.w3.org/2005/Atom"
+   xmlns:content="http://purl.org/rss/1.0/modules/content/"
+   xmlns:fh="http://purl.org/syndication/history/1.0">
+  <channel>
+    <generator>Gallery 3</generator>
+    <title><?= html::clean($feed->title) ?></title>
+    <link><?= $feed->uri ?></link>
+    <description><?= html::clean($feed->description) ?></description>
+    <language>en-us</language>
+    <atom:link rel="self" href="<?= $feed->uri ?>" type="application/rss+xml" />
+    <fh:complete/>
+    <? if (!empty($feed->previous_page_uri)): ?>
+    <atom:link rel="previous" href="<?= $feed->previous_page_uri ?>" type="application/rss+xml" />
+    <? endif ?>
+    <? if (!empty($feed->next_page_uri)): ?>
+    <atom:link rel="next" href="<?= $feed->next_page_uri ?>" type="application/rss+xml" />
+    <? endif ?>
+    <pubDate><?= $pub_date ?></pubDate>
+    <lastBuildDate><?= $pub_date ?></lastBuildDate>
+    <? foreach ($feed->comments as $comment): ?>
+    <item>
+      <title><?= html::purify($comment->title) ?></title>
+      <link><?= html::clean($comment->item_uri) ?></link>
+      <author><?= html::clean($comment->author) ?></author>
+      <guid isPermaLink="true"><?= $comment->item_uri ?></guid>
+      <pubDate><?= $comment->pub_date ?></pubDate>
+      <content:encoded>
+        <![CDATA[
+          <p><?= nl2br(html::purify($comment->text)) ?></p>
+          <p>
+            <img alt="" src="<?= $comment->thumb_url ?>"
+                 height="<?= $comment->thumb_height ?>" width="<?= $comment->thumb_width ?>" />
+            <br />
+          </p>
+        ]]>
+      </content:encoded>
+    </item>
+    <? endforeach ?>
+  </channel>
+</rss>
diff --git a/modules/comment/views/comments.html.php b/modules/comment/views/comments.html.php
new file mode 100644
index 0000000..b524f5d
--- /dev/null
+++ b/modules/comment/views/comments.html.php
@@ -0,0 +1,56 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? if (comment::can_comment()): ?>
+<a href="<?= url::site("form/add/comments/{$item->id}") ?>#comment-form" id="g-add-comment"
+   class="g-button ui-corner-all ui-icon-left ui-state-default">
+  <span class="ui-icon ui-icon-comment"></span>
+  <?= t("Add a comment") ?>
+</a>
+<? endif ?>
+
+<div id="g-comment-detail">
+  <? if (!$comments->count()): ?>
+  <p class="g-no-comments">
+    <? if (comment::can_comment()): ?>
+    <?= t("No comments yet. Be the first to <a %attrs>comment</a>!",
+          array("attrs" => html::mark_clean("href=\"" . url::site("form/add/comments/{$item->id}") . "\" class=\"showCommentForm\""))) ?>
+    <? else: ?>
+    <?= t("No comments yet.") ?>
+    <? endif ?>
+   </p>
+  <ul>
+    <li class="g-no-comments">&nbsp;</li>
+  </ul>
+  <? endif ?>
+
+  <? if ($comments->count()): ?>
+  <ul>
+    <? foreach ($comments as $comment): ?>
+    <li id="g-comment-<?= $comment->id ?>">
+      <p class="g-author">
+        <a href="#">
+          <img src="<?= $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>"
+               class="g-avatar"
+               alt="<?= html::clean_attribute($comment->author_name()) ?>"
+               width="40"
+               height="40" />
+        </a>
+        <? if ($comment->author()->guest): ?>
+        <?= t('on %date %name said',
+            array("date" => gallery::date_time($comment->created),
+                  "name" => html::clean($comment->author_name()))); ?>
+        <? else: ?>
+        <?= t('on %date <a href="%url">%name</a> said',
+              array("date" => gallery::date_time($comment->created),
+                    "url" => user_profile::url($comment->author_id),
+                    "name" => html::clean($comment->author_name()))); ?>
+        <? endif ?>
+      </p>
+      <div>
+        <?= nl2br(html::purify($comment->text)) ?>
+      </div>
+    </li>
+    <? endforeach ?>
+  </ul>
+  <? endif ?>
+  <a name="comment-form" id="g-comment-form-anchor"></a>
+</div>
diff --git a/modules/comment/views/user_profile_comments.html.php b/modules/comment/views/user_profile_comments.html.php
new file mode 100644
index 0000000..377b2d9
--- /dev/null
+++ b/modules/comment/views/user_profile_comments.html.php
@@ -0,0 +1,20 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-comment-detail">
+<ul>
+  <? foreach ($comments as $comment): ?>
+  <li id="g-comment-<?= $comment->id ?>">
+    <p class="g-author">
+      <?= t("on %date for %title ",
+            array("date" => gallery::date_time($comment->created),
+                  "title" => $comment->item()->title)); ?>
+      <a href="<?= $comment->item()->url() ?>">
+        <?= $comment->item()->thumb_img(array(), 50) ?>
+      </a>
+    </p>
+    <div>
+      <?= nl2br(html::purify($comment->text)) ?>
+    </div>
+  </li>
+  <? endforeach ?>
+</ul>
+</div>
diff --git a/modules/downloadalbum/controllers/downloadalbum.php b/modules/downloadalbum/controllers/downloadalbum.php
new file mode 100644
index 0000000..f352763
--- /dev/null
+++ b/modules/downloadalbum/controllers/downloadalbum.php
@@ -0,0 +1,300 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2012 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class downloadalbum_Controller extends Controller {
+
+  /**
+   * Generate a ZIP on-the-fly.
+   */
+  public function zip($container_type, $id) {
+    switch($container_type) {
+      case "album":
+        $container = ORM::factory("item", $id);
+        if (!$container->is_album()) {
+          throw new Kohana_Exception('container is not an album: '.$container->relative_path());
+        }
+
+        $zipname = (empty($container->name))
+            ? 'Gallery.zip' // @todo purified_version_of($container->title).'.zip'
+            : $container->name.'.zip';
+        break;
+
+     case "tag":
+        // @todo: if the module is not installed, it crash
+        $container = ORM::factory("tag", $id);
+        if (is_null($container->name)) {
+          throw new Kohana_Exception('container is not a tag: '.$id);
+        }
+
+        $zipname = $container->name.'.zip';
+        break;
+
+     default:
+       throw new Kohana_Exception('unhandled container type: '.$container_type);
+   }
+
+   $files = $this->getFilesList($container);
+
+    // Calculate ZIP size (look behind for details)
+    $zipsize = 22;
+    foreach($files as $f_name => $f_path) {
+      $zipsize += 76 + 2*strlen($f_name) + filesize($f_path);
+    }
+
+    // Send headers
+    $this->prepareOutput();
+    $this->sendHeaders($zipname, $zipsize);
+
+    // Generate and send ZIP file
+    // http://www.pkware.com/documents/casestudies/APPNOTE.TXT (v6.3.2)
+    $lfh_offset = 0;
+    $cds = '';
+    $cds_offset = 0;
+    foreach($files as $f_name => $f_path) {
+      $f_namelen = strlen($f_name);
+      $f_size = filesize($f_path);
+      $f_mtime = $this->unix2dostime(filemtime($f_path));
+      $f_crc32 = $this->fixBug45028(hexdec(hash_file('crc32b', $f_path, false)));
+
+      // Local file header
+      echo pack('VvvvVVVVvva' . $f_namelen,
+          0x04034b50,         // local file header signature (4 bytes)
+          0x0a,               // version needed to extract (2 bytes) => 1.0
+          0x0800,             // general purpose bit flag (2 bytes) => UTF-8
+          0x00,               // compression method (2 bytes) => store
+          $f_mtime,           // last mod file time and date (4 bytes)
+          $f_crc32,           // crc-32 (4 bytes)
+          $f_size,            // compressed size (4 bytes)
+          $f_size,            // uncompressed size (4 bytes)
+          $f_namelen,         // file name length (2 bytes)
+          0,                  // extra field length (2 bytes)
+
+          $f_name             // file name (variable size)
+                              // extra field (variable size) => n/a
+      );
+
+      // File data
+      readfile($f_path);
+
+      // Data descriptor (n/a)
+
+      // Central directory structure: File header
+      $cds .= pack('VvvvvVVVVvvvvvVVa' . $f_namelen,
+          0x02014b50,         // central file header signature (4 bytes)
+          0x031e,             // version made by (2 bytes) => v3 / Unix
+          0x0a,               // version needed to extract (2 bytes) => 1.0
+          0x0800,             // general purpose bit flag (2 bytes) => UTF-8
+          0x00,               // compression method (2 bytes) => store
+          $f_mtime,           // last mod file time and date (4 bytes)
+          $f_crc32,           // crc-32 (4 bytes)
+          $f_size,            // compressed size (4 bytes)
+          $f_size,            // uncompressed size (4 bytes)
+          $f_namelen,         // file name length (2 bytes)
+          0,                  // extra field length (2 bytes)
+          0,                  // file comment length (2 bytes)
+          0,                  // disk number start (2 bytes)
+          0,                  // internal file attributes (2 bytes)
+          0x81b40000,         // external file attributes (4 bytes) => chmod 664
+          $lfh_offset,        // relative offset of local header (4 bytes)
+
+          $f_name             // file name (variable size)
+                              // extra field (variable size) => n/a
+                              // file comment (variable size) => n/a
+      );
+
+      // Update local file header/central directory structure offset
+      $cds_offset = $lfh_offset += 30 + $f_namelen + $f_size;
+    }
+
+    // Archive decryption header (n/a)
+    // Archive extra data record (n/a)
+
+    // Central directory structure: Digital signature (n/a)
+    echo $cds; // send Central directory structure
+
+    // Zip64 end of central directory record (n/a)
+    // Zip64 end of central directory locator (n/a)
+
+    // End of central directory record
+    $numfile = count($files);
+    $cds_len = strlen($cds);
+    echo pack('VvvvvVVv',
+        0x06054b50,             // end of central dir signature (4 bytes)
+        0,                      // number of this disk (2 bytes)
+        0,                      // number of the disk with the start of
+                                // the central directory (2 bytes)
+        $numfile,               // total number of entries in the
+                                // central directory on this disk (2 bytes)
+        $numfile,               // total number of entries in the
+                                // central directory (2 bytes)
+        $cds_len,               // size of the central directory (4 bytes)
+        $cds_offset,            // offset of start of central directory
+                                // with respect to the
+                                // starting disk number (4 bytes)
+        0                       // .ZIP file comment length (2 bytes)
+                                // .ZIP file comment (variable size)
+    );
+  }
+
+
+  /**
+   * Return the files that must be included in the archive.
+   */
+  private function getFilesList($container) {
+    $files = array();
+
+    if( $container instanceof Item_Model && $container->is_album() ) {
+      $container_realpath = realpath($container->file_path().'/../');
+
+      $items = $container->viewable()
+          ->descendants(null, null, array(array("type", "<>", "album")));
+      foreach($items as $i) {
+        if (!access::can('view_full', $i)) {
+          continue;
+        }
+
+        $i_realpath = realpath($i->file_path());
+        if (!is_readable($i_realpath)) {
+          continue;
+        }
+
+        $i_relative_path = str_replace($container_realpath.DIRECTORY_SEPARATOR, '', $i_realpath);
+        $i_relative_path = str_replace(DIRECTORY_SEPARATOR, '/', $i_relative_path);
+        $files[$i_relative_path] = $i_realpath;
+      }
+
+    } else if( $container instanceof Tag_Model ) {
+      $items = $container->items();
+      foreach($items as $i) {
+        if (!access::can('view_full', $i)) {
+          continue;
+        }
+
+        if( $i->is_album() ) {
+          foreach($this->getFilesList($i) as $f_name => $f_path) {
+            $files[$container->name.'/'.$f_name] = $f_path;
+          }
+
+        } else {
+          $i_realpath = realpath($i->file_path());
+          if (!is_readable($i_realpath)) {
+            continue;
+          }
+
+          $i_relative_path = $container->name.'/'.$i->name;
+          $files[$i_relative_path] = $i_realpath;
+        }
+      }
+    }
+
+    if (count($files) === 0) {
+      throw new Kohana_Exception('no zippable files in ['.$container->name.']');
+    }
+
+    return $files;
+  }
+
+
+  /**
+   * See system/helpers/download.php
+   */
+  private function prepareOutput() {
+    // Close output buffers
+    Kohana::close_buffers(FALSE);
+    // Clear any output
+    Event::add('system.display', create_function('', 'Kohana::$output = "";'));
+  }
+
+  /**
+   * See system/helpers/download.php
+   */
+  private function sendHeaders($filename, $filesize = null) {
+    if (!is_null($filesize)) {
+      header('Content-Length: '.$filesize);
+    }
+
+    // Retrieve MIME type by extension
+    $mime = Kohana::config('mimes.'.strtolower(substr(strrchr($filename, '.'), 1)));
+    $mime = empty($mime) ? 'application/octet-stream' : $mime[0];
+    header("Content-Type: $mime");
+    header('Content-Transfer-Encoding: binary');
+
+    // Send headers necessary to invoke a "Save As" dialog
+    header('Content-Disposition: attachment; filename="'.$filename.'"');
+
+    // Prevent caching
+    header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
+
+    $pragma = 'no-cache';
+    $cachecontrol = 'no-cache, max-age=0';
+
+    // request::user_agent('browser') seems bugged
+    if (request::user_agent('browser') === 'Internet Explorer'
+        || stripos(request::user_agent(), 'msie') !== false
+        || stripos(request::user_agent(), 'internet explorer') !== false)
+    {
+      if (request::protocol() === 'https') {
+        // See http://support.microsoft.com/kb/323308/en-us
+        $pragma = 'cache';
+        $cachecontrol = 'private';
+
+      } else if (request::user_agent('version') <= '6.0') {
+        $pragma = '';
+        $cachecontrol = 'must-revalidate, post-check=0, pre-check=0';
+      }
+    }
+
+    header('Pragma: '.$pragma);
+    header('Cache-Control: '.$cachecontrol);
+  }
+
+  /**
+   * @return integer             DOS date and time
+   * @param  integer _timestamp  Unix timestamp
+   * @desc                       returns DOS date and time of the timestamp
+   */
+  private function unix2dostime($timestamp)
+  {
+    $timebit = getdate($timestamp);
+
+    if ($timebit['year'] < 1980) {
+      return (1 << 21 | 1 << 16);
+    }
+
+    $timebit['year'] -= 1980;
+
+    return ($timebit['year']    << 25 | $timebit['mon']     << 21 |
+            $timebit['mday']    << 16 | $timebit['hours']   << 11 |
+            $timebit['minutes'] << 5  | $timebit['seconds'] >> 1);
+  }
+
+  /**
+   * See http://bugs.php.net/bug.php?id=45028
+   */
+  private function fixBug45028($hash) {
+    $output = $hash;
+
+    if( version_compare(PHP_VERSION, '5.2.7', '<') ) {
+      $str = str_pad(dechex($hash), 8, '0', STR_PAD_LEFT);
+      $output = hexdec($str{6}.$str{7}.$str{4}.$str{5}.$str{2}.$str{3}.$str{0}.$str{1});
+    }
+
+    return $output;
+  }
+}
diff --git a/modules/downloadalbum/css/downloadalbum_menu.css b/modules/downloadalbum/css/downloadalbum_menu.css
new file mode 100644
index 0000000..e3c4c67
--- /dev/null
+++ b/modules/downloadalbum/css/downloadalbum_menu.css
@@ -0,0 +1,3 @@
+#g-view-menu #g-download-album-link {
+  background-image: url('../images/ico-view-downloadalbum.png');
+}
diff --git a/modules/downloadalbum/helpers/downloadalbum_event.php b/modules/downloadalbum/helpers/downloadalbum_event.php
new file mode 100644
index 0000000..c5e875c
--- /dev/null
+++ b/modules/downloadalbum/helpers/downloadalbum_event.php
@@ -0,0 +1,40 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2012 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class downloadalbum_event_Core {
+  static function album_menu($menu, $theme) {
+    $downloadLink = url::site("downloadalbum/zip/album/{$theme->item->id}");
+    $menu
+      ->append(Menu::factory("link")
+          ->id("downloadalbum")
+          ->label(t("Download Album"))
+          ->url($downloadLink)
+          ->css_id("g-download-album-link"));
+  }
+
+  static function tag_menu($menu, $theme) {
+    $downloadLink = url::site("downloadalbum/zip/tag/{$theme->tag()->id}");
+    $menu
+      ->append(Menu::factory("link")
+          ->id("downloadalbum")
+          ->label(t("Download Album"))
+          ->url($downloadLink)
+          ->css_id("g-download-album-link"));
+  } 
+}
diff --git a/modules/downloadalbum/helpers/downloadalbum_theme.php b/modules/downloadalbum/helpers/downloadalbum_theme.php
new file mode 100644
index 0000000..800ab3f
--- /dev/null
+++ b/modules/downloadalbum/helpers/downloadalbum_theme.php
@@ -0,0 +1,24 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2012 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class downloadalbum_theme {
+  static function head($theme) {
+    return $theme->css("downloadalbum_menu.css");
+  }
+}
diff --git a/modules/downloadalbum/images/ico-view-downloadalbum.png b/modules/downloadalbum/images/ico-view-downloadalbum.png
new file mode 100644
index 0000000..ce7804d
Binary files /dev/null and b/modules/downloadalbum/images/ico-view-downloadalbum.png differ
diff --git a/modules/downloadalbum/module.info b/modules/downloadalbum/module.info
new file mode 100644
index 0000000..f547fd4
--- /dev/null
+++ b/modules/downloadalbum/module.info
@@ -0,0 +1,7 @@
+name = "DownloadAlbum"
+description = "Displays a link to download a ZIP archive of the current album."
+version = 2
+author_name = ""
+author_url = ""
+info_url = "http://codex.gallery2.org/Gallery3:Modules:downloadalbum"
+discuss_url = "http://gallery.menalto.com/forum_module_downloadalbum"
diff --git a/modules/downloadfullsize/controllers/admin_downloadfullsize.php b/modules/downloadfullsize/controllers/admin_downloadfullsize.php
new file mode 100644
index 0000000..3befd33
--- /dev/null
+++ b/modules/downloadfullsize/controllers/admin_downloadfullsize.php
@@ -0,0 +1,93 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2012 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class Admin_DownloadFullsize_Controller extends Admin_Controller {
+  public function index() {
+    // Generate a new admin page.
+    $view = new Admin_View("admin.html");
+    $view->content = new View("admin_downloadfullsize.html");
+    $view->content->downloadlinks_form = $this->_get_admin_form();
+    print $view;
+  }
+
+  public function saveprefs() {
+    // Prevent Cross Site Request Forgery
+    access::verify_csrf();
+
+    // Figure out which boxes where checked
+    $dlLinks_array = Input::instance()->post("DownloadLinkOptions");
+    $fButton = false;
+    $download_original_button = false;
+    for ($i = 0; $i < count($dlLinks_array); $i++) {
+      if ($dlLinks_array[$i] == "fButton") {
+        $fButton = true;
+      }
+    }
+
+    if (module::is_active("keeporiginal")) {
+      $keeporiginal_array = Input::instance()->post("DownloadOriginalOptions");
+      for ($i = 0; $i < count($keeporiginal_array); $i++) {
+        if ($keeporiginal_array[$i] == "DownloadOriginalImage") {
+          $download_original_button = true;
+        }
+      }
+      module::set_var("downloadfullsize", "DownloadOriginalImage", $download_original_button);
+    }
+
+    // Save Settings.
+    module::set_var("downloadfullsize", "fButton", $fButton);
+    message::success(t("Your Selection Has Been Saved."));
+
+    // Load Admin page.
+    $view = new Admin_View("admin.html");
+    $view->content = new View("admin_downloadfullsize.html");
+    $view->content->downloadlinks_form = $this->_get_admin_form();
+    print $view;
+
+  }
+
+  private function _get_admin_form() {
+    // Make a new Form.
+    $form = new Forge("admin/downloadfullsize/saveprefs", "", "post",
+                      array("id" => "g-download-fullsize-adminForm"));
+
+    // Make an array for the different types of download links.
+    $linkOptions["fButton"] = array(t("Show Floppy Disk Picture Link"), module::get_var("downloadfullsize", "fButton"));
+
+    // Setup a few checkboxes on the form.
+    $add_links = $form->group("DownloadLinks");
+    $add_links->checklist("DownloadLinkOptions")
+      ->options($linkOptions);
+
+    if (module::is_active("keeporiginal")) {
+      $KeepOriginalOptions["DownloadOriginalImage"] = array(t("Allow visitors to download the original image when available?"), module::get_var("downloadfullsize", "DownloadOriginalImage"));
+      $keeporiginal_group = $form->group("KeepOriginalPrefs")
+                               ->label(t("KeepOriginal Preferences"));
+      $keeporiginal_group->checklist("DownloadOriginalOptions")
+                       ->options($KeepOriginalOptions);
+    }
+
+    // Add a save button to the form.
+    $form->submit("SaveLinks")->value(t("Save"));
+
+    // Return the newly generated form.
+    return $form;
+  }
+}
\ No newline at end of file
diff --git a/modules/downloadfullsize/controllers/downloadfullsize.php b/modules/downloadfullsize/controllers/downloadfullsize.php
new file mode 100644
index 0000000..9fa43f7
--- /dev/null
+++ b/modules/downloadfullsize/controllers/downloadfullsize.php
@@ -0,0 +1,37 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2012 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class downloadfullsize_Controller extends Controller {
+
+  public function send($id) {
+    $item = ORM::factory("item", $id);
+    access::required("view_full", $item);
+
+    if (module::is_active("keeporiginal") && $item->is_photo() && module::get_var("downloadfullsize", "DownloadOriginalImage")) {
+      $original_image = VARPATH . "original/" . str_replace(VARPATH . "albums/", "", $item->file_path());
+      if (file_exists($original_image)) {        
+        download::force($original_image);
+        } else {
+          download::force($item->file_path());
+        }
+    } else {
+      download::force($item->file_path());
+    }
+  }
+}
diff --git a/modules/downloadfullsize/css/downloadfullsize_menu.css b/modules/downloadfullsize/css/downloadfullsize_menu.css
new file mode 100644
index 0000000..a608a66
--- /dev/null
+++ b/modules/downloadfullsize/css/downloadfullsize_menu.css
@@ -0,0 +1,3 @@
+#g-view-menu #g-download-fullsize-link {
+  background-image: url('../images/ico-view-downloadfullsize.png');
+}
diff --git a/modules/downloadfullsize/helpers/downloadfullsize_block.php b/modules/downloadfullsize/helpers/downloadfullsize_block.php
new file mode 100644
index 0000000..f894442
--- /dev/null
+++ b/modules/downloadfullsize/helpers/downloadfullsize_block.php
@@ -0,0 +1,51 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2012 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class downloadfullsize_block_Core {
+  static function get_site_list() {
+    return array("downloadfullsize" => t("Download Item"));
+  }
+
+  static function get($block_id, $theme) {
+    $item = $theme->item;
+    switch ($block_id) {
+    case "downloadfullsize":
+
+      // If Item is movie then...
+      if ($item && $item->is_movie() && access::can("view_full", $item)) {
+        $block = new Block();
+        $block->css_id = "g-download-fullsize";
+        $block->title = t("Download Movie");
+        $block->content = new View("downloadfullsize_block.html");
+        return $block;
+      }
+
+      // If Item is photo then...
+      if ($item && $item->is_photo() && access::can("view_full", $item)) {
+        $block = new Block();
+        $block->css_id = "g-download-fullsize";
+        $block->title = t("Download Photo");
+        $block->content = new View("downloadfullsize_block.html");
+        return $block;
+      }
+    }
+    return "";
+  }
+
+}
diff --git a/modules/downloadfullsize/helpers/downloadfullsize_event.php b/modules/downloadfullsize/helpers/downloadfullsize_event.php
new file mode 100644
index 0000000..9c4b990
--- /dev/null
+++ b/modules/downloadfullsize/helpers/downloadfullsize_event.php
@@ -0,0 +1,57 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2012 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class downloadfullsize_event_Core {
+  static function photo_menu($menu, $theme) {
+    if (access::can("view_full", $theme->item)) {
+      if (module::get_var("downloadfullsize", "fButton")) {
+        $downloadLink = url::site("downloadfullsize/send/{$theme->item->id}");
+        $menu
+          ->append(Menu::factory("link")
+               ->id("downloadfullsize")
+               ->label(t("Download Fullsize Image"))
+               ->url($downloadLink)
+               ->css_id("g-download-fullsize-link"));
+      }
+    }
+  }
+
+  static function movie_menu($menu, $theme) {
+    if (access::can("view_full", $theme->item)) {
+      if (module::get_var("downloadfullsize", "fButton")) {
+        $downloadLink = url::site("downloadfullsize/send/{$theme->item->id}");
+        $menu
+          ->append(Menu::factory("link")
+               ->id("downloadfullsize")
+               ->label(t("Download Video"))
+               ->url($downloadLink)
+               ->css_id("g-download-fullsize-link"));
+      }
+    }
+  }
+
+  static function admin_menu($menu, $theme) {
+    $menu->get("settings_menu")
+      ->append(Menu::factory("link")
+               ->id("downloadfullsize")
+               ->label(t("Download Photo Links"))
+               ->url(url::site("admin/downloadfullsize")));
+  }
+
+}
diff --git a/modules/downloadfullsize/helpers/downloadfullsize_theme.php b/modules/downloadfullsize/helpers/downloadfullsize_theme.php
new file mode 100644
index 0000000..080ff91
--- /dev/null
+++ b/modules/downloadfullsize/helpers/downloadfullsize_theme.php
@@ -0,0 +1,26 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2012 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class downloadfullsize_theme {
+  static function head($theme) {
+    if ($theme->item && access::can("view_full", $theme->item)) {
+      return $theme->css("downloadfullsize_menu.css");
+    }
+  }
+}
diff --git a/modules/downloadfullsize/images/ico-view-downloadfullsize.png b/modules/downloadfullsize/images/ico-view-downloadfullsize.png
new file mode 100644
index 0000000..ce7804d
Binary files /dev/null and b/modules/downloadfullsize/images/ico-view-downloadfullsize.png differ
diff --git a/modules/downloadfullsize/module.info b/modules/downloadfullsize/module.info
new file mode 100644
index 0000000..b2cc391
--- /dev/null
+++ b/modules/downloadfullsize/module.info
@@ -0,0 +1,7 @@
+name = "DownloadFullsize"
+description = "Displays a link to download the fullsize version of the current photo."
+version = 1
+author_name = "rWatcher"
+author_url = "http://codex.gallery2.org/User:RWatcher"
+info_url = "http://codex.gallery2.org/Gallery3:Modules:downloadfullsize"
+discuss_url = "http://gallery.menalto.com/node/103278"
diff --git a/modules/downloadfullsize/views/admin_downloadfullsize.html.php b/modules/downloadfullsize/views/admin_downloadfullsize.html.php
new file mode 100644
index 0000000..5dc5cef
--- /dev/null
+++ b/modules/downloadfullsize/views/admin_downloadfullsize.html.php
@@ -0,0 +1,5 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-download-fullsize-admin">
+  <h2> <?= t("Download Fullsize Links") ?> </h2>
+  <?= $downloadlinks_form ?>
+</div>
diff --git a/modules/downloadfullsize/views/downloadfullsize_block.html.php b/modules/downloadfullsize/views/downloadfullsize_block.html.php
new file mode 100644
index 0000000..a9ccc2a
--- /dev/null
+++ b/modules/downloadfullsize/views/downloadfullsize_block.html.php
@@ -0,0 +1,18 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+
+<? if ($theme->item->is_photo()) { ?>
+<div class="g-download-fullsize-block">
+<a href="<?= url::site("downloadfullsize/send/{$theme->item->id}") ?>"
+   title="<?= t("Download Photo") ?>"
+  class="g-button ui-icon-left ui-state-default ui-corner-all"><?= t("Download Fullsize Image") ?></a>
+</div>
+<? } ?>
+
+<? if ($theme->item->is_movie()) { ?>
+<div class="g-download-fullsize-block">
+<a href="<?= url::site("downloadfullsize/send/{$theme->item->id}") ?>"
+   title="<?= t("Download Video") ?>"
+  class="g-button ui-icon-left ui-state-default ui-corner-all"><?= t("Download Movie") ?></a>
+</div>
+<? } ?>
+
diff --git a/modules/exif/controllers/exif.php b/modules/exif/controllers/exif.php
new file mode 100644
index 0000000..aea8012
--- /dev/null
+++ b/modules/exif/controllers/exif.php
@@ -0,0 +1,33 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Exif_Controller extends Controller {
+  /**
+   * Display the EXIF data for an item.
+   */
+  public function show($item_id) {
+    $item = ORM::factory("item", $item_id);
+    access::required("view", $item);
+
+    $view = new View("exif_dialog.html");
+    $view->details = exif::get($item);
+
+    print $view;
+  }
+}
diff --git a/modules/exif/helpers/exif.php b/modules/exif/helpers/exif.php
new file mode 100644
index 0000000..b17f460
--- /dev/null
+++ b/modules/exif/helpers/exif.php
@@ -0,0 +1,167 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling exif data.
+ */
+class exif_Core {
+
+  protected static $exif_keys;
+
+  static function extract($item) {
+    $keys = array();
+    // Only try to extract EXIF from photos
+    if ($item->is_photo() && $item->mime_type == "image/jpeg") {
+      $data = array();
+      require_once(MODPATH . "exif/lib/exif.php");
+      $exif_raw = read_exif_data_raw($item->file_path(), false);
+      if (isset($exif_raw['ValidEXIFData'])) {
+        foreach(self::_keys() as $field => $exifvar) {
+          if (isset($exif_raw[$exifvar[0]][$exifvar[1]])) {
+            $value = $exif_raw[$exifvar[0]][$exifvar[1]];
+            $value = encoding::convert_to_utf8($value);
+            $keys[$field] = Input::clean($value);
+
+            if ($field == "DateTime") {
+              $time = strtotime($value);
+              if ($time > 0) {
+                $item->captured = $time;
+              }
+            } else if ($field == "Caption" && !$item->description) {
+              $item->description = $value;
+            }
+          }
+        }
+      }
+
+      $size = getimagesize($item->file_path(), $info);
+      if (is_array($info) && !empty($info["APP13"])) {
+        $iptc = iptcparse($info["APP13"]);
+        foreach (array("Keywords" => "2#025", "Caption" => "2#120") as $keyword => $iptc_key) {
+          if (!empty($iptc[$iptc_key])) {
+            $value = implode(" ", $iptc[$iptc_key]);
+            $value = encoding::convert_to_utf8($value);
+            $keys[$keyword] = Input::clean($value);
+
+            if ($keyword == "Caption" && !$item->description) {
+              $item->description = $value;
+            }
+          }
+        }
+      }
+    }
+    $item->save();
+
+    $record = ORM::factory("exif_record")->where("item_id", "=", $item->id)->find();
+    if (!$record->loaded()) {
+      $record->item_id = $item->id;
+    }
+    $record->data = serialize($keys);
+    $record->key_count = count($keys);
+    $record->dirty = 0;
+    $record->save();
+  }
+
+  static function get($item) {
+    $exif = array();
+    $record = ORM::factory("exif_record")
+      ->where("item_id", "=", $item->id)
+      ->find();
+    if (!$record->loaded()) {
+      return array();
+    }
+
+    $definitions = self::_keys();
+    $keys = unserialize($record->data);
+    foreach ($keys as $key => $value) {
+      $exif[] = array("caption" => $definitions[$key][2], "value" => $value);
+    }
+
+    return $exif;
+  }
+
+  private static function _keys() {
+    if (!isset(self::$exif_keys)) {
+      self::$exif_keys = array(
+        "Make"            => array("IFD0",   "Make",              t("Camera Maker"),     ),
+        "Model"           => array("IFD0",   "Model",             t("Camera Model"),     ),
+        "Aperture"        => array("SubIFD", "FNumber",           t("Aperture"),         ),
+        "ColorSpace"      => array("SubIFD", "ColorSpace",        t("Color Space"),      ),
+        "ExposureBias"    => array("SubIFD", "ExposureBiasValue", t("Exposure Value"),   ),
+        "ExposureProgram" => array("SubIFD", "ExposureProgram",   t("Exposure Program"), ),
+        "ExposureTime"    => array("SubIFD", "ExposureTime",      t("Exposure Time"),    ),
+        "Flash"           => array("SubIFD", "Flash",             t("Flash"),            ),
+        "FocalLength"     => array("SubIFD", "FocalLength",       t("Focal Length"),     ),
+        "ISO"             => array("SubIFD", "ISOSpeedRatings",   t("ISO"),              ),
+        "MeteringMode"    => array("SubIFD", "MeteringMode",      t("Metering Mode"),    ),
+        "DateTime"        => array("SubIFD", "DateTimeOriginal",  t("Date/Time"),        ),
+        "Copyright"       => array("IFD0",   "Copyright",         t("Copyright"),        ),
+        "ImageType"       => array("IFD0",   "ImageType",         t("Image Type"),       ),
+        "Orientation"     => array("IFD0",   "Orientation",       t("Orientation"),      ),
+        "ResolutionUnit"  => array("IFD0",   "ResolutionUnit",    t("Resolution Unit"),  ),
+        "xResolution"     => array("IFD0",   "xResolution",       t("X Resolution"),     ),
+        "yResolution"     => array("IFD0",   "yResolution",       t("Y Resolution"),     ),
+        "Compression"     => array("IFD1",   "Compression",       t("Compression"),      ),
+        "BrightnessValue" => array("SubIFD", "BrightnessValue",   t("Brightness Value"), ),
+        "Contrast"        => array("SubIFD", "Contrast",          t("Contrast"),         ),
+        "ExposureMode"    => array("SubIFD", "ExposureMode",      t("Exposure Mode"),    ),
+        "FlashEnergy"     => array("SubIFD", "FlashEnergy",       t("Flash Energy"),     ),
+        "Saturation"      => array("SubIFD", "Saturation",        t("Saturation"),       ),
+        "SceneType"       => array("SubIFD", "SceneType",         t("Scene Type"),       ),
+        "Sharpness"       => array("SubIFD", "Sharpness",         t("Sharpness"),        ),
+        "SubjectDistance" => array("SubIFD", "SubjectDistance",   t("Subject Distance"), ),
+        "Caption"         => array("IPTC",   "Caption",           t("Caption"),          ),
+        "Keywords"        => array("IPTC",   "Keywords",          t("Keywords"),         )
+      );
+    }
+    return self::$exif_keys;
+  }
+
+  static function stats() {
+    $missing_exif = db::build()
+      ->select("items.id")
+      ->from("items")
+      ->join("exif_records", "items.id", "exif_records.item_id", "left")
+      ->where("type", "=", "photo")
+      ->and_open()
+      ->where("exif_records.item_id", "IS", null)
+      ->or_where("exif_records.dirty", "=", 1)
+      ->close()
+      ->execute()
+      ->count();
+
+    $total_items = ORM::factory("item")->where("type", "=", "photo")->count_all();
+    if (!$total_items) {
+      return array(0, 0, 0);
+    }
+    return array($missing_exif, $total_items,
+                 round(100 * (($total_items - $missing_exif) / $total_items)));
+  }
+
+  static function check_index() {
+    list ($remaining) = exif::stats();
+    if ($remaining) {
+      site_status::warning(
+        t('Your Exif index needs to be updated.  <a href="%url" class="g-dialog-link">Fix this now</a>',
+          array("url" => html::mark_clean(url::site("admin/maintenance/start/exif_task::update_index?csrf=__CSRF__")))),
+        "exif_index_out_of_date");
+    }
+  }
+}
diff --git a/modules/exif/helpers/exif_event.php b/modules/exif/helpers/exif_event.php
new file mode 100644
index 0000000..cd5068f
--- /dev/null
+++ b/modules/exif/helpers/exif_event.php
@@ -0,0 +1,39 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class exif_event_Core {
+  static function item_created($item) {
+    if (!$item->is_album()) {
+      exif::extract($item);
+    }
+  }
+
+  static function item_updated_data_file($item) {
+    if (!$item->is_album()) {
+      exif::extract($item);
+    }
+  }
+
+  static function item_deleted($item) {
+    db::build()
+      ->delete("exif_records")
+      ->where("item_id", "=", $item->id)
+      ->execute();
+  }
+}
diff --git a/modules/exif/helpers/exif_installer.php b/modules/exif/helpers/exif_installer.php
new file mode 100644
index 0000000..75d0f83
--- /dev/null
+++ b/modules/exif/helpers/exif_installer.php
@@ -0,0 +1,45 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class exif_installer {
+  static function install() {
+    $db = Database::instance();
+    $db->query("CREATE TABLE IF NOT EXISTS {exif_records} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `item_id` INTEGER(9) NOT NULL,
+                 `key_count` INTEGER(9) default 0,
+                 `data` TEXT,
+                 `dirty` BOOLEAN default 1,
+                 PRIMARY KEY (`id`),
+                 KEY(`item_id`))
+               DEFAULT CHARSET=utf8;");
+  }
+
+  static function activate() {
+    exif::check_index();
+  }
+
+  static function deactivate() {
+    site_status::clear("exif_index_out_of_date");
+  }
+
+  static function uninstall() {
+    Database::instance()->query("DROP TABLE IF EXISTS {exif_records};");
+  }
+}
diff --git a/modules/exif/helpers/exif_task.php b/modules/exif/helpers/exif_task.php
new file mode 100644
index 0000000..f8a108a
--- /dev/null
+++ b/modules/exif/helpers/exif_task.php
@@ -0,0 +1,88 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class exif_task_Core {
+  static function available_tasks() {
+    // Delete extra exif_records
+    db::build()
+      ->delete("exif_records")
+      ->where("item_id", "NOT IN",
+              db::build()->select("id")->from("items")->where("type", "=", "photo"))
+      ->execute();
+
+    list ($remaining, $total, $percent) = exif::stats();
+    return array(Task_Definition::factory()
+                 ->callback("exif_task::update_index")
+                 ->name(t("Extract Exif data"))
+                 ->description($remaining
+                               ? t2("1 photo needs to be scanned",
+                                    "%count (%percent%) of your photos need to be scanned",
+                                    $remaining, array("percent" => (100 - $percent)))
+                               : t("Exif data is up-to-date"))
+                 ->severity($remaining ? log::WARNING : log::SUCCESS));
+  }
+
+  static function update_index($task) {
+    try {
+      $completed = $task->get("completed", 0);
+
+      $start = microtime(true);
+      foreach (ORM::factory("item")
+               ->join("exif_records", "items.id", "exif_records.item_id", "left")
+               ->where("type", "=", "photo")
+               ->and_open()
+               ->where("exif_records.item_id", "IS", null)
+               ->or_where("exif_records.dirty", "=", 1)
+               ->close()
+               ->find_all(100) as $item) {
+        // The query above can take a long time, so start the timer after its done
+        // to give ourselves a little time to actually process rows.
+        if (!isset($start)) {
+          $start = microtime(true);
+        }
+
+        exif::extract($item);
+        $completed++;
+
+        if (microtime(true) - $start > .75) {
+          break;
+        }
+      }
+
+      list ($remaining, $total, $percent) = exif::stats();
+      $task->set("completed", $completed);
+      if ($remaining == 0 || !($remaining + $completed)) {
+        $task->done = true;
+        $task->state = "success";
+        site_status::clear("exif_index_out_of_date");
+        $task->percent_complete = 100;
+      } else {
+        $task->percent_complete = round(100 * $completed / ($remaining + $completed));
+      }
+      $task->status = t2("one record updated, index is %percent% up-to-date",
+                         "%count records updated, index is %percent% up-to-date",
+                         $completed, array("percent" => $percent));
+    } catch (Exception $e) {
+      $task->done = true;
+      $task->state = "error";
+      $task->status = $e->getMessage();
+      $task->log((string)$e);
+    }
+  }
+}
diff --git a/modules/exif/helpers/exif_theme.php b/modules/exif/helpers/exif_theme.php
new file mode 100644
index 0000000..df7c6f4
--- /dev/null
+++ b/modules/exif/helpers/exif_theme.php
@@ -0,0 +1,38 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class exif_theme_Core {
+  static function sidebar_bottom($theme) {
+    $item = $theme->item();
+    if ($item && $item->is_photo()) {
+      $record = db::build()
+        ->select("key_count")
+        ->from("exif_records")
+        ->where("item_id", "=", $item->id)
+        ->execute()
+        ->current();
+      if ($record && $record->key_count) {
+        $view = new View("exif_sidebar.html");
+        $view->item = $item;
+        return $view;
+      }
+    }
+    return null;
+  }
+}
diff --git a/modules/exif/lib/exif.php b/modules/exif/lib/exif.php
new file mode 100644
index 0000000..8ba85c8
--- /dev/null
+++ b/modules/exif/lib/exif.php
@@ -0,0 +1,1135 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/*
+	Exifer 1.6
+	Extracts EXIF information from digital photos.
+	
+	Originally created by:
+	Copyright © 2005 Jake Olefsky
+	http:// www.offsky.com/software/exif/index.php
+	jake@olefsky.com
+	
+	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 for more details. http:// www.gnu.org/copyleft/gpl.html
+	
+	SUMMARY:
+				This script will correctly parse all of the EXIF data included in images taken
+				with digital cameras.  It will read the IDF0, IDF1, SubIDF and InteroperabilityIFD
+				fields as well as parsing some of the MakerNote fields that vary depending on
+				camera make and model.  This script parses more tags than the internal PHP exif
+				implementation and it will correctly identify and decode what all the values mean.
+				
+				This version will correctly parse the MakerNote field for Nikon, Olympus, and Canon 
+				digital cameras.  Others will follow.
+				
+	TESTED WITH:
+				Nikon CoolPix 700
+				Nikon CoolPix E3200
+				Nikon CoolPix 4500
+				Nikon CoolPix 950
+				Nikon Coolpix 5700
+				Canon PowerShot S200
+				Canon PowerShot S110
+				Olympus C2040Z 
+				Olympus C960
+				Olumpus E-300
+				Olympus E-410
+				Olympus E-500
+				Olympus E-510
+				Olympus E-3
+				Canon Ixus
+				Canon EOS 300D
+				Canon Digital Rebel
+				Canon EOS 10D
+				Canon PowerShot G2
+				FujiFilm DX 10
+				FujiFilm MX-1200
+				FujiFilm FinePix2400
+				FujiFilm FinePix2600
+				FujiFilm FinePix S602
+				FujiFilm FinePix40i
+				Sony D700
+				Sony Cybershot
+				Kodak DC210
+				Kodak DC240
+				Kodak DC4800
+				Kodak DX3215
+				Ricoh RDC-5300 
+				Sanyo VPC-G250
+				Sanyo VPC-SX550
+				Epson 3100z
+
+	
+	VERSION HISTORY:
+	
+	1.0   September 23, 2002   
+	
+		+ First Public Release
+	
+	1.1    January 25, 2003
+		
+		+ Gracefully handled the error case where you pass an empty string to this library
+		+ Fixed an inconsistency in the Olympus Camera parsing module
+		+ Added support for parsing the MakerNote of Canon images.
+		+ Modified how the imagefile is opened so it works for windows machines.
+		+ Correctly parses the FocalPlaneResolutionUnit and PhotometricInterpretation fields
+		+ Negative rational numbers are properly displayed
+		+ Strange old cameras that use Motorola endineness are now properly supported
+		+ Tested with several more cameras
+		
+		Potential Problem: Negative Shorts and Negative Longs may not be correctly displayed, but I
+			have not yet found an example of negative shorts or longs being used.
+	
+	1.2    March 30, 2003
+	
+		+ Fixed an error that was displayed if you edited your image with WinXP's image viewer
+		+ Fixed a bug that caused some images saved from 3rd party software to not parse correctly
+		+ Changed the ExposureTime tag to display in fractional seconds rather than decimal
+		+ Updated the ShutterSpeedValue tag to have the units of 'sec'
+		+ Added support for parsing the MakeNote of FujiFilm images
+		+ Added support for parsing the MakeNote of Sanyo images
+		+ Fixed a bug with parsing some Olympus MakerNote tags
+		+ Tested with several more cameras
+			
+	1.3    June 15, 2003
+	
+		+ Fixed Canon MakerNote support for some models
+ 			(Canon has very difficult and inconsistent MakerNote syntax)
+		+ Negative signed shorts and negative signed longs are properly displayed
+		+ Several more tags are defined
+		+ More information in my comments about what each tag is
+		+ Parses and Displays GPS information if available
+		+ Tested with several more cameras
+			
+	1.4    September 14, 2003
+		
+		+ This software is now licensed under the GNU General Public License
+		+ Exposure time is now correctly displayed when the numerator is 10
+		+ Fixed the calculation and display of ShutterSpeedValue, ApertureValue and MaxApertureValue 
+		+ Fixed a bug with the GPS code
+		+ Tested with several more cameras
+			
+	1.5    February 18, 2005
+	
+		+ It now gracefully deals with a passed in file that cannot be found.
+		+ Fixed a GPS bug for the parsing of Altitude and other signed rational numbers
+		+ Defined more values for Canon cameras.
+		+ Added 'bulb' detection for ShutterSpeed
+		+ Made script loading a little faster and less memory intensive.
+		+ Bug fixes
+		+ Better error reporting
+		+ Graceful failure for files with corrupt exif info.
+		+ QuickTime (including iPhoto) messes up the Makernote tag for certain photos (no workaround yet)
+		+ Now reads exif information when the jpeg markers are out of order
+		+ Gives raw data output for IPTC, COM and APP2 fields which are sometimes set by other applications
+		+ Improvements to Nikon Makernote parsing
+			
+	1.6    March 25th, 2007 [Zenphoto]
+	
+		+ Adopted into the Zenphoto gallery project, at http://www.zenphoto.org
+		+ Fixed a bug where strings had trailing null bytes.
+		+ Formatted selected strings better.
+		+ Added calculation of 35mm-equivalent focal length when possible.
+		+ Cleaned up code for readability and efficiency.
+		
+	1.7    April 11th, 2008 [Zenphoto]
+	  
+	  + Fixed bug with newer Olympus cameras where number of fields was miscalculated leading to bad performance.
+		+ More logical fraction calculation for shutter speed.
+
+2009: For all further changes, see the Zenphoto change logs.
+		
+*/
+
+
+
+	
+
+
+//================================================================================================
+// Converts from Intel to Motorola endien.  Just reverses the bytes (assumes hex is passed in)
+//================================================================================================
+
+function intel2Moto($intel) {
+	static $cache = array();
+	if (isset($cache[$intel])) {
+		return $cache[$intel];
+	}
+
+	$cache[$intel] = '';
+	$len  = strlen($intel);
+	if ($len > 1000) { // an unreasonable length, override it.
+		$len = 1000;
+	}
+	for($i = 0; $i <= $len; $i += 2) {		
+		$cache[$intel] .= substr($intel, $len-$i, 2);
+	}
+	return $cache[$intel];
+}
+
+
+//================================================================================================
+// Looks up the name of the tag
+//================================================================================================
+function lookup_tag($tag) {
+	switch($tag) {
+		// used by IFD0 'Camera Tags'
+		case '000b': $tag = 'ACDComment'; break;               // text string up to 999 bytes long
+		case '00fe': $tag = 'ImageType'; break;                // integer -2147483648 to 2147483647
+		case '0106': $tag = 'PhotometricInterpret'; break;     // ?? Please send sample image with this tag
+		case '010e': $tag = 'ImageDescription'; break;         // text string up to 999 bytes long
+		case '010f': $tag = 'Make'; break;                     // text string up to 999 bytes long
+		case '0110': $tag = 'Model'; break;                    // text string up to 999 bytes long
+		case '0112': $tag = 'Orientation'; break;              // integer values 1-9
+		case '0115': $tag = 'SamplePerPixel'; break;           // integer 0-65535
+		case '011a': $tag = 'xResolution'; break;              // positive rational number
+		case '011b': $tag = 'yResolution'; break;              // positive rational number
+		case '011c': $tag = 'PlanarConfig'; break;             // integer values 1-2
+		case '0128': $tag = 'ResolutionUnit'; break;           // integer values 1-3
+		case '0131': $tag = 'Software'; break;                 // text string up to 999 bytes long
+		case '0132': $tag = 'DateTime'; break;                 // YYYY:MM:DD HH:MM:SS
+		case '013b': $tag = 'Artist'; break;                   // text string up to 999 bytes long
+		case '013c': $tag = 'HostComputer'; break;             // text string
+		case '013e': $tag = 'WhitePoint'; break;               // two positive rational numbers
+		case '013f': $tag = 'PrimaryChromaticities'; break;    // six positive rational numbers
+		case '0211': $tag = 'YCbCrCoefficients'; break;        // three positive rational numbers
+		case '0213': $tag = 'YCbCrPositioning'; break;         // integer values 1-2
+		case '0214': $tag = 'ReferenceBlackWhite'; break;      // six positive rational numbers
+		case '8298': $tag = 'Copyright'; break;                // text string up to 999 bytes long
+		case '8649': $tag = 'PhotoshopSettings'; break;        // ??  
+		case '8769': $tag = 'ExifOffset'; break;               // positive integer
+		case '8825': $tag = 'GPSInfoOffset'; break;            
+		case '9286': $tag = 'UserCommentOld'; break;           // ??
+		// used by Exif SubIFD 'Image Tags'                    
+		case '829a': $tag = 'ExposureTime'; break;             // seconds or fraction of seconds 1/x
+		case '829d': $tag = 'FNumber'; break;                  // positive rational number
+		case '8822': $tag = 'ExposureProgram'; break;          // integer value 1-9
+		case '8824': $tag = 'SpectralSensitivity'; break;      // ??
+		case '8827': $tag = 'ISOSpeedRatings'; break;          // integer 0-65535
+		case '9000': $tag = 'ExifVersion'; break;              // ??
+		case '9003': $tag = 'DateTimeOriginal'; break;         // YYYY:MM:DD HH:MM:SS
+		case '9004': $tag = 'DateTimeDigitized'; break;        // YYYY:MM:DD HH:MM:SS
+		case '9101': $tag = 'ComponentsConfiguration'; break;  // ??
+		case '9102': $tag = 'CompressedBitsPerPixel'; break;   // positive rational number
+		case '9201': $tag = 'ShutterSpeedValue'; break;        // seconds or fraction of seconds 1/x
+		case '9202': $tag = 'ApertureValue'; break;            // positive rational number
+		case '9203': $tag = 'BrightnessValue'; break;          // positive rational number
+		case '9204': $tag = 'ExposureBiasValue'; break;        // positive rational number (EV)
+		case '9205': $tag = 'MaxApertureValue'; break;         // positive rational number
+		case '9206': $tag = 'SubjectDistance'; break;          // positive rational number (meters)
+		case '9207': $tag = 'MeteringMode'; break;             // integer 1-6 and 255
+		case '9208': $tag = 'LightSource'; break;              // integer 1-255
+		case '9209': $tag = 'Flash'; break;                    // integer 1-255
+		case '920a': $tag = 'FocalLength'; break;              // positive rational number (mm)
+		case '9213': $tag = 'ImageHistory'; break;             // text string up to 999 bytes long
+		case '927c': $tag = 'MakerNote'; break;                // a bunch of data
+		case '9286': $tag = 'UserComment'; break;              // text string
+		case '9290': $tag = 'SubsecTime'; break;               // text string up to 999 bytes long
+		case '9291': $tag = 'SubsecTimeOriginal'; break;       // text string up to 999 bytes long
+		case '9292': $tag = 'SubsecTimeDigitized'; break;      // text string up to 999 bytes long
+		case 'a000': $tag = 'FlashPixVersion'; break;          // ??
+		case 'a001': $tag = 'ColorSpace'; break;               // values 1 or 65535
+		case 'a002': $tag = 'ExifImageWidth'; break;           // ingeter 1-65535
+		case 'a003': $tag = 'ExifImageHeight'; break;          // ingeter 1-65535
+		case 'a004': $tag = 'RelatedSoundFile'; break;         // text string 12 bytes long
+		case 'a005': $tag = 'ExifInteroperabilityOffset'; break;    // positive integer
+		case 'a20c': $tag = 'SpacialFreqResponse'; break;      // ??
+		case 'a20b': $tag = 'FlashEnergy'; break;              // positive rational number
+		case 'a20e': $tag = 'FocalPlaneXResolution'; break;    // positive rational number
+		case 'a20f': $tag = 'FocalPlaneYResolution'; break;    // positive rational number
+		case 'a210': $tag = 'FocalPlaneResolutionUnit'; break; // values 1-3
+		case 'a214': $tag = 'SubjectLocation'; break;          // two integers 0-65535
+		case 'a215': $tag = 'ExposureIndex'; break;            // positive rational number
+		case 'a217': $tag = 'SensingMethod'; break;            // values 1-8
+		case 'a300': $tag = 'FileSource'; break;               // integer
+		case 'a301': $tag = 'SceneType'; break;                // integer
+		case 'a302': $tag = 'CFAPattern'; break;               // undefined data type
+		case 'a401': $tag = 'CustomerRender'; break;           // values 0 or 1
+		case 'a402': $tag = 'ExposureMode'; break;             // values 0-2
+		case 'a403': $tag = 'WhiteBalance'; break;             // values 0 or 1
+		case 'a404': $tag = 'DigitalZoomRatio'; break;         // positive rational number
+		case 'a405': $tag = 'FocalLengthIn35mmFilm'; break;
+		case 'a406': $tag = 'SceneCaptureMode'; break;         // values 0-3
+		case 'a407': $tag = 'GainControl'; break;              // values 0-4
+		case 'a408': $tag = 'Contrast'; break;                 // values 0-2
+		case 'a409': $tag = 'Saturation'; break;               // values 0-2
+		case 'a40a': $tag = 'Sharpness'; break;                // values 0-2
+
+		// used by Interoperability IFD
+		case '0001': $tag = 'InteroperabilityIndex'; break;    // text string 3 bytes long
+		case '0002': $tag = 'InteroperabilityVersion'; break;  // datatype undefined
+		case '1000': $tag = 'RelatedImageFileFormat'; break;   // text string up to 999 bytes long
+		case '1001': $tag = 'RelatedImageWidth'; break;        // integer in range 0-65535
+		case '1002': $tag = 'RelatedImageLength'; break;       // integer in range 0-65535
+		
+		// used by IFD1 'Thumbnail'
+		case '0100': $tag = 'ImageWidth'; break;               // integer in range 0-65535
+		case '0101': $tag = 'ImageLength'; break;              // integer in range 0-65535
+		case '0102': $tag = 'BitsPerSample'; break;            // integers in range 0-65535
+		case '0103': $tag = 'Compression'; break;              // values 1 or 6
+		case '0106': $tag = 'PhotometricInterpretation'; break;// values 0-4
+		case '010e': $tag = 'ThumbnailDescription'; break;     // text string up to 999 bytes long
+		case '010f': $tag = 'ThumbnailMake'; break;            // text string up to 999 bytes long
+		case '0110': $tag = 'ThumbnailModel'; break;           // text string up to 999 bytes long
+		case '0111': $tag = 'StripOffsets'; break;             // ??
+		case '0112': $tag = 'ThumbnailOrientation'; break;     // integer 1-9
+		case '0115': $tag = 'SamplesPerPixel'; break;          // ??
+		case '0116': $tag = 'RowsPerStrip'; break;             // ??
+		case '0117': $tag = 'StripByteCounts'; break;          // ??
+		case '011a': $tag = 'ThumbnailXResolution'; break;     // positive rational number
+		case '011b': $tag = 'ThumbnailYResolution'; break;     // positive rational number
+		case '011c': $tag = 'PlanarConfiguration'; break;      // values 1 or 2
+		case '0128': $tag = 'ThumbnailResolutionUnit'; break;  // values 1-3    
+		case '0201': $tag = 'JpegIFOffset'; break;        
+		case '0202': $tag = 'JpegIFByteCount'; break;
+		case '0212': $tag = 'YCbCrSubSampling'; break;
+	
+		// misc
+		case '00ff': $tag = 'SubfileType'; break;
+		case '012d': $tag = 'TransferFunction'; break;
+		case '013d': $tag = 'Predictor'; break;
+		case '0142': $tag = 'TileWidth'; break;
+		case '0143': $tag = 'TileLength'; break;
+		case '0144': $tag = 'TileOffsets'; break;
+		case '0145': $tag = 'TileByteCounts'; break;
+		case '014a': $tag = 'SubIFDs'; break;
+		case '015b': $tag = 'JPEGTables'; break;
+		case '828d': $tag = 'CFARepeatPatternDim'; break;
+		case '828e': $tag = 'CFAPattern'; break;
+		case '828f': $tag = 'BatteryLevel'; break;
+		case '83bb': $tag = 'IPTC/NAA'; break;
+		case '8773': $tag = 'InterColorProfile'; break;
+		
+		case '8828': $tag = 'OECF'; break;
+		case '8829': $tag = 'Interlace'; break;
+		case '882a': $tag = 'TimeZoneOffset'; break;
+		case '882b': $tag = 'SelfTimerMode'; break;
+		case '920b': $tag = 'FlashEnergy'; break;
+		case '920c': $tag = 'SpatialFrequencyResponse'; break;
+		case '920d': $tag = 'Noise'; break;
+		case '9211': $tag = 'ImageNumber'; break;
+		case '9212': $tag = 'SecurityClassification'; break;
+		case '9214': $tag = 'SubjectLocation'; break;
+		case '9215': $tag = 'ExposureIndex'; break;
+		case '9216': $tag = 'TIFF/EPStandardID'; break;
+		case 'a20b': $tag = 'FlashEnergy'; break;
+		
+		default: $tag = 'unknown:'.$tag; break;
+	}
+	return $tag;
+
+}
+
+
+//================================================================================================
+// Looks up the datatype
+//================================================================================================
+function lookup_type(&$type,&$size) {
+	switch($type) {
+		case '0001': $type = 'UBYTE'; $size=1; break;
+		case '0002': $type = 'ASCII'; $size=1; break;
+		case '0003': $type = 'USHORT'; $size=2; break;
+		case '0004': $type = 'ULONG'; $size=4; break;
+		case '0005': $type = 'URATIONAL'; $size=8; break;
+		case '0006': $type = 'SBYTE'; $size=1; break;
+		case '0007': $type = 'UNDEFINED'; $size=1; break;
+		case '0008': $type = 'SSHORT'; $size=2; break;
+		case '0009': $type = 'SLONG'; $size=4; break;
+		case '000a': $type = 'SRATIONAL'; $size=8; break;
+		case '000b': $type = 'FLOAT'; $size=4; break;
+		case '000c': $type = 'DOUBLE'; $size=8; break;
+		default: $type = 'error:'.$type; $size=0; break;
+	}
+	return $type;
+}
+
+//================================================================================================
+// processes a irrational number
+//================================================================================================
+function unRational($data, $type, $intel) {
+		$data = bin2hex($data);
+		if ($intel == 1) {
+			$data = intel2Moto($data);
+			$top = hexdec(substr($data,8,8));   // intel stores them bottom-top
+			$bottom = hexdec(substr($data,0,8));  // intel stores them bottom-top
+		} else {
+			$top = hexdec(substr($data,0,8));        // motorola stores them top-bottom
+			$bottom = hexdec(substr($data,8,8));      // motorola stores them top-bottom
+		}
+		
+		if ($type == 'SRATIONAL' && $top > 2147483647) $top = $top - 4294967296;    // this makes the number signed instead of unsigned
+		if ($bottom != 0)
+			$data=$top/$bottom;
+		else 
+			if ($top == 0)
+				$data = 0;
+			else
+				$data = $top.'/'.$bottom;
+	return $data;
+}
+
+//================================================================================================
+// processes a rational number
+//================================================================================================
+function rational($data,$type,$intel) {
+	if (($type == 'USHORT' || $type == 'SSHORT')) {
+		$data = substr($data,0,2);
+	}
+	$data = bin2hex($data);
+	if ($intel == 1) {
+		$data = intel2Moto($data);
+	}
+	$data = hexdec($data);
+	if ($type == 'SSHORT' && $data > 32767)     $data = $data - 65536;  // this makes the number signed instead of unsigned
+	if ($type == 'SLONG' && $data > 2147483647) $data = $data - 4294967296;  // this makes the number signed instead of unsigned
+	return $data;
+}
+
+//================================================================================================
+// Formats Data for the data type
+//================================================================================================
+function formatData($type,$tag,$intel,$data) {
+	switch ($type) {
+		case 'ASCII':
+			if (($pos = strpos($data, chr(0))) !== false) {	// Search for a null byte and stop there.
+				$data = substr($data, 0, $pos);
+			}
+			if ($tag == '010f') $data = ucwords(strtolower(trim($data)));	// Format certain kinds of strings nicely (Camera make etc.)
+			break;
+		case 'URATIONAL':
+		case 'SRATIONAL':
+			switch ($tag) {
+				case '011a': // XResolution
+				case '011b': // YResolution
+					$data = round(unRational($data,$type,$intel)).' dots per ResolutionUnit';
+					break;
+				case '829a': // Exposure Time
+					$data = formatExposure(unRational($data,$type,$intel));
+					break;
+				case '829d': // FNumber
+					$data = 'f/'.unRational($data,$type,$intel);
+					break;
+				case '9204': // ExposureBiasValue
+					$data = round(unRational($data,$type,$intel), 2) . ' EV';
+					break;
+				case '9205': // ApertureValue
+				case '9202': // MaxApertureValue
+					// ApertureValue is given in the APEX Mode. Many thanks to Matthieu Froment for this code
+					// The formula is : Aperture = 2*log2(FNumber) <=> FNumber = e((Aperture.ln(2))/2)
+					$datum = exp((unRational($data,$type,$intel)*log(2))/2);
+					$data = round($datum, 1);// Focal is given with a precision of 1 digit.
+					$data='f/'.$datum; 
+					break;
+				case '920a': // FocalLength
+					$data = unRational($data,$type,$intel).' mm';
+					break;
+				case '9201': // ShutterSpeedValue
+					// The ShutterSpeedValue is given in the APEX mode. Many thanks to Matthieu Froment for this code
+					// The formula is : Shutter = - log2(exposureTime) (Appendix C of EXIF spec.)
+					// Where shutter is in APEX, log2(exposure) = ln(exposure)/ln(2)
+					// So final formula is : exposure = exp(-ln(2).shutter)
+					// The formula can be developed : exposure = 1/(exp(ln(2).shutter))
+					$datum = exp(unRational($data,$type,$intel) * log(2));
+					if ($datum != 0) $datum = 1/$datum;
+					$data = formatExposure($datum);
+					break;
+				default:
+					$data = unRational($data,$type,$intel);
+					break;
+			}
+			break;
+		case 'USHORT':
+		case 'SSHORT':
+		case 'ULONG':
+		case 'SLONG':
+		case 'FLOAT':
+		case 'DOUBLE':
+			$data = rational($data,$type,$intel);
+			switch ($tag) {
+				case '0112':	// Orientation
+					// Example of how all of these tag formatters should be...
+					switch ($data) {
+						case 0	:		// not set, presume normal
+						case 1  :   $data = (string) t('1: Normal (0 deg)');      break;
+						case 2  :   $data = (string) t('2: Mirrored');            break;
+						case 3  :   $data = (string) t('3: Upside-down');          break;
+						case 4  :   $data = (string) t('4: Upside-down Mirrored'); break;
+						case 5  :   $data = (string) t('5: 90 deg CW Mirrored');  break;
+						case 6  :   $data = (string) t('6: 90 deg CCW');          break;
+						case 7  :   $data = (string) t('7: 90 deg CCW Mirrored'); break;
+						case 8  :   $data = (string) t('8: 90 deg CW');           break;
+						default :   $data = sprintf((string) t('%d: Unknown'),$data);	break;
+					}
+					break;
+				case '0128':	// ResolutionUnit
+				case 'a210':	// FocalPlaneResolutionUnit
+				case '0128':	// ThumbnailResolutionUnit
+					switch ($data) {
+						case 1:	$data = (string) t('No Unit');	break;
+						case 2:	$data = (string) t('Inch');	break;
+						case 3:	$data = (string) t('Centimeter');	break;
+					}
+					break;
+				case '0213':	// YCbCrPositioning
+					switch ($data) {
+						case 1:	$data = (string) t('Center of Pixel Array');	break;
+						case 2:	$data = (string) t('Datum Point');	break;
+					}
+					break;
+				case '8822':	// ExposureProgram
+					switch ($data) {
+						case 1:		$data = (string) t('Manual');	break;
+						case 2:		$data = (string) t('Program');	break;
+						case 3:		$data = (string) t('Aperture Priority');	break;
+						case 4:		$data = (string) t('Shutter Priority');	break;
+						case 5:		$data = (string) t('Program Creative');	break;
+						case 6:		$data = (string) t('Program Action');	break;
+						case 7:		$data = (string) t('Portrait');	break;
+						case 8:		$data = (string) t('Landscape');	break;
+						default:	$data = (string) t('Unknown').': '.$data;	break;
+					}
+					break;
+				case '9207':	// MeteringMode
+					switch ($data) {
+						case 1:		$data = (string) t('Average');	break;
+						case 2:		$data = (string) t('Center Weighted Average');	break;
+						case 3:		$data = (string) t('Spot');	break;
+						case 4:		$data = (string) t('Multi-Spot');	break;
+						case 5:		$data = (string) t('Pattern');	break;
+						case 6:		$data = (string) t('Partial');	break;
+						case 255:	$data = (string) t('Other');	break;
+						default:	$data = (string) t('Unknown').': '.$data;	break;
+					}
+					break;
+				case '9208':	// LightSource
+					switch ($data) {
+						case 1:		$data = (string) t('Daylight');	break;
+						case 2:				$data = (string) t('Fluorescent');	break;
+						case 3:			$data = (string) t('Tungsten');	break;	// 3 Tungsten (Incandescent light)
+													// 4 Flash
+													// 9 Fine Weather
+						case 10:		$data = (string) t('Flash');	break;	// 10 Cloudy Weather
+													// 11 Shade
+													// 12 Daylight Fluorescent (D 5700 - 7100K)
+													// 13 Day White Fluorescent (N 4600 - 5400K)
+													// 14 Cool White Fluorescent (W 3900 -4500K)
+													// 15 White Fluorescent (WW 3200 - 3700K)
+													// 10 Flash
+						case 17:		$data = (string) t('Standard Light A');	break;
+						case 18:		$data = (string) t('Standard Light B');	break;
+						case 19:		$data = (string) t('Standard Light C');	break;
+						case 20:		$data = (string) t('D55');	break;
+						case 21:		$data = (string) t('D65');	break;
+						case 22:		$data = (string) t('D75');	break;
+						case 23:		$data = (string) t('D50');	break;
+						case 24:		$data = (string) t('ISO Studio Tungsten');	break;
+						case 255:		$data = (string) t('Other');	break;
+						default:		$data = (string) t('Unknown').': '.$data;	break;
+					}
+					break;
+				case '9209':	// Flash
+					switch ($data) {
+						case 0:			$data = (string) t('No Flash');	break;
+						case 1:			$data = (string) t('Flash');	break;
+						case 5:			$data = (string) t('Flash, strobe return light not detected');	break;
+						case 7:			$data = (string) t('Flash, strobe return light detected');	break;
+						case 9:			$data = (string) t('Compulsory Flash');	break;
+						case 13:		$data = (string) t('Compulsory Flash, Return light not detected');	break;
+						case 15:		$data = (string) t('Compulsory Flash, Return light detected');	break;
+						case 16:		$data = (string) t('No Flash');	break;
+						case 24:		$data = (string) t('No Flash');	break;
+						case 25:		$data = (string) t('Flash, Auto-Mode');	break;
+						case 29:		$data = (string) t('Flash, Auto-Mode, Return light not detected');	break;
+						case 31:		$data = (string) t('Flash, Auto-Mode, Return light detected');	break;
+						case 32:		$data = (string) t('No Flash');	break;
+						case 65:		$data = (string) t('Red Eye');	break;
+						case 69:		$data = (string) t('Red Eye, Return light not detected');	break;
+						case 71:		$data = (string) t('Red Eye, Return light detected');	break;
+						case 73:		$data = (string) t('Red Eye, Compulsory Flash');	break;
+						case 77:		$data = (string) t('Red Eye, Compulsory Flash, Return light not detected');	break;
+						case 79:		$data = (string) t('Red Eye, Compulsory Flash, Return light detected');	break;
+						case 89:		$data = (string) t('Red Eye, Auto-Mode');	break;
+						case 93:		$data = (string) t('Red Eye, Auto-Mode, Return light not detected');	break;
+						case 95:		$data = (string) t('Red Eye, Auto-Mode, Return light detected');	break;
+						default:		$data = (string) t('Unknown').': '.$data;	break;
+					}
+					break;
+				case 'a001':	// ColorSpace
+					if ($data == 1)         $data = (string) t('sRGB');
+					else                    $data = (string) t('Uncalibrated');
+					break;
+				case 'a002':	// ExifImageWidth
+				case 'a003':	// ExifImageHeight
+					$data = $data. ' '.(string) t('pixels');
+					break;
+				case '0103':	// Compression
+					switch ($data) {
+						case 1:		$data = (string) t('No Compression');	break;
+						case 6:		$data = (string) t('Jpeg Compression');	break;
+						default:	$data = (string) t('Unknown').': '.$data;	break;
+					}
+					break;
+				case 'a217':	// SensingMethod
+					switch ($data) {
+						case 1:		$data = (string) t('Not defined');	break;
+						case 2:		$data = (string) t('One Chip Color Area Sensor');	break;
+						case 3:		$data = (string) t('Two Chip Color Area Sensor');	break;
+						case 4:		$data = (string) t('Three Chip Color Area Sensor');	break;
+						case 5:		$data = (string) t('Color Sequential Area Sensor');	break;
+						case 7:		$data = (string) t('Trilinear Sensor');	break;
+						case 8:		$data = (string) t('Color Sequential Linear Sensor');	break;
+						default:	$data = (string) t('Unknown').': '.$data;	break;
+					}
+					break;
+				case '0106':	// PhotometricInterpretation
+					switch ($data) {
+						case 1:		$data = (string) t('Monochrome');	break;
+						case 2:		$data = (string) t('RGB');	break;
+						case 6:		$data = (string) t('YCbCr');	break;
+						default:	$data = (string) t('Unknown').': '.$data;	break;
+					}
+					break;
+				//case "a408":	// Contrast
+				//case "a40a":	//Sharpness
+				//	switch($data) {
+				//		case 0: $data="Normal"; break;
+				//		case 1: $data="Soft"; break;
+				//		case 2: $data="Hard"; break;
+				//		default: $data="Unknown"; break;
+				//	}
+				//	break;
+				//case "a409":	// Saturation
+				//	switch($data) {
+				//		case 0: $data="Normal"; break;
+				//		case 1: $data="Low saturation"; break;
+				//		case 2: $data="High saturation"; break;
+				//		default: $data="Unknown"; break;
+				//	}
+				//	break;
+				//case "a402":	// Exposure Mode
+				//	switch($data) {
+				//		case 0: $data="Auto exposure"; break;
+				//		case 1: $data="Manual exposure"; break;
+				//		case 2: $data="Auto bracket"; break;
+				//		default: $data="Unknown"; break;
+				//	}
+				//	break;
+			}
+			break;
+		case 'UNDEFINED':
+			switch ($tag) {
+				case '9000':	// ExifVersion
+				case 'a000':	// FlashPixVersion
+				case '0002':	// InteroperabilityVersion
+					$data=(string) t('version').' '.$data/100;
+					break;
+				case 'a300':	// FileSource
+					$data = bin2hex($data);
+					$data = str_replace('00','',$data);
+					$data = str_replace('03',(string) t('Digital Still Camera'),$data);
+					break;
+				case 'a301':	// SceneType
+					$data = bin2hex($data);
+					$data = str_replace('00','',$data);
+					$data = str_replace('01',(string) t('Directly Photographed'),$data);
+					break;
+				case '9101':	// ComponentsConfiguration
+					$data = bin2hex($data);
+					$data = str_replace('01','Y',$data);
+					$data = str_replace('02','Cb',$data);
+					$data = str_replace('03','Cr',$data);
+					$data = str_replace('04','R',$data);
+					$data = str_replace('05','G',$data);
+					$data = str_replace('06','B',$data);
+					$data = str_replace('00','',$data);
+					break;
+				//case "9286":	//UserComment
+				//	$encoding	= rtrim(substr($data, 0, 8));
+				//	$data		= rtrim(substr($data, 8));
+				//	break;
+			}
+			break;
+		default:
+			$data = bin2hex($data);
+			if ($intel == 1) $data = intel2Moto($data);
+			break;
+	}
+	return $data;
+}
+
+function formatExposure($data) {
+	if (strpos($data,'/')===false) {
+		if ($data > 1) {
+			return round($data, 2).' '.(string) t('sec');
+		} else {
+			$n=0; $d=0;
+			ConvertToFraction($data, $n, $d);
+			return $n.'/'.$d.' '.(string) t('sec');
+		}
+	} else {
+		return (string) t('Bulb');
+	}
+}
+
+//================================================================================================
+// Reads one standard IFD entry
+//================================================================================================
+function read_entry(&$result,$in,$seek,$intel,$ifd_name,$globalOffset) {
+	
+	if (feof($in)) { // test to make sure we can still read.
+		$result['Errors'] = $result['Errors']+1;
+		return;
+	}
+	
+	// 2 byte tag
+	$tag = bin2hex(fread($in, 2));
+	if ($intel == 1) $tag = intel2Moto($tag);
+	$tag_name = lookup_tag($tag);
+	
+	// 2 byte datatype
+	$type = bin2hex(fread($in, 2));
+	if ($intel == 1) $type = intel2Moto($type);
+	lookup_type($type, $size);
+	
+	if (strpos($tag_name, 'unknown:') !== false && strpos($type, 'error:') !== false) { // we have an error
+		$result['Errors'] = $result['Errors']+1;
+		return;
+	}
+	
+	// 4 byte number of elements
+	$count = bin2hex(fread($in, 4));
+	if ($intel == 1) $count = intel2Moto($count);
+	$bytesofdata = $size*hexdec($count);
+	
+	// 4 byte value or pointer to value if larger than 4 bytes
+	$value = fread( $in, 4 );
+	
+	if ($bytesofdata <= 4) {   // if datatype is 4 bytes or less, its the value
+		$data = $value;
+	} else if ($bytesofdata < 100000) {        // otherwise its a pointer to the value, so lets go get it
+		$value = bin2hex($value);
+		if ($intel == 1) $value = intel2Moto($value);
+		$v = fseek($seek, $globalOffset+hexdec($value));  // offsets are from TIFF header which is 12 bytes from the start of the file
+		if ($v == 0) {
+			$data = fread($seek, $bytesofdata);
+		} else if ($v == -1) {
+			$result['Errors'] = $result['Errors']+1;
+		}
+	} else { // bytesofdata was too big, so the exif had an error
+		$result['Errors'] = $result['Errors']+1;
+		return;
+	}
+	if ($tag_name == 'MakerNote') { // if its a maker tag, we need to parse this specially
+		$make = $result['IFD0']['Make'];
+		
+		if ($result['VerboseOutput'] == 1) {
+			$result[$ifd_name]['MakerNote']['RawData'] = $data;
+		}
+		if (preg_match('/NIKON/i',$make)) {
+			require_once(dirname(__FILE__).'/makers/nikon.php');
+			parseNikon($data,$result);
+			$result[$ifd_name]['KnownMaker'] = 1;
+		} else if (preg_match('/OLYMPUS/i',$make)) {
+			require_once(dirname(__FILE__).'/makers/olympus.php');
+			parseOlympus($data,$result,$seek,$globalOffset);
+			$result[$ifd_name]['KnownMaker'] = 1;
+		} else if (preg_match('/Canon/i',$make)) {
+			require_once(dirname(__FILE__).'/makers/canon.php');
+			parseCanon($data,$result,$seek,$globalOffset);
+			$result[$ifd_name]['KnownMaker'] = 1;
+		} else if (preg_match('/FUJIFILM/i',$make)) {
+			require_once(dirname(__FILE__).'/makers/fujifilm.php');
+			parseFujifilm($data,$result);
+			$result[$ifd_name]['KnownMaker'] = 1;
+		} else if (preg_match('/SANYO/i',$make)) {
+			require_once(dirname(__FILE__).'/makers/sanyo.php');
+			parseSanyo($data,$result,$seek,$globalOffset);
+			$result[$ifd_name]['KnownMaker'] = 1;
+		} else if (preg_match('/Panasonic/i',$make)) { 
+			require_once(dirname(__FILE__).'/makers/panasonic.php'); 
+			parsePanasonic($data,$result,$seek,$globalOffset); 
+			$result[$ifd_name]['KnownMaker'] = 1; 
+		} else {
+			$result[$ifd_name]['KnownMaker'] = 0;
+		}
+	} else if ($tag_name == 'GPSInfoOffset') {
+		require_once(dirname(__FILE__).'/makers/gps.php');
+		$formated_data = formatData($type,$tag,$intel,$data);
+		$result[$ifd_name]['GPSInfo'] = $formated_data;
+		parseGPS($data,$result,$formated_data,$seek,$globalOffset);
+	} else {
+		// Format the data depending on the type and tag
+		$formated_data = formatData($type,$tag,$intel,$data);
+		
+		$result[$ifd_name][$tag_name] = $formated_data;
+		
+		if ($result['VerboseOutput'] == 1) {
+			if ($type == 'URATIONAL' || $type == 'SRATIONAL' || $type == 'USHORT' || $type == 'SSHORT' || $type == 'ULONG' || $type == 'SLONG' || $type == 'FLOAT' || $type == 'DOUBLE') {
+				$data = bin2hex($data);
+				if ($intel == 1) $data = intel2Moto($data);
+			}
+		$result[$ifd_name][$tag_name.'_Verbose']['RawData'] = $data;
+		$result[$ifd_name][$tag_name.'_Verbose']['Type'] = $type;
+		$result[$ifd_name][$tag_name.'_Verbose']['Bytes'] = $bytesofdata;
+		}
+	}
+}
+
+
+//================================================================================================
+// Pass in a file and this reads the EXIF data
+//
+// Usefull resources
+// http:// www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html
+// http:// www.w3.org/Graphics/JPEG/jfif.txt
+// http:// exif.org/
+// http:// www.ozhiker.com/electronics/pjmt/library/list_contents.php4
+// http:// www.ozhiker.com/electronics/pjmt/jpeg_info/makernotes.html
+// http:// pel.sourceforge.net/
+// http:// us2.php.net/manual/en/function.exif-read-data.php
+//================================================================================================
+function read_exif_data_raw($path,$verbose) {
+	
+	if ($path == '' || $path == 'none') return;
+	
+	$in = @fopen($path, 'rb'); // the b is for windows machines to open in binary mode
+	$seek = @fopen($path, 'rb'); // There may be an elegant way to do this with one file handle.
+	
+	$globalOffset = 0;
+	
+	if (!isset($verbose)) $verbose=0;
+	
+	$result['VerboseOutput'] = $verbose;
+	$result['Errors'] = 0;
+	
+	if (!$in || !$seek) {  // if the path was invalid, this error will catch it
+		$result['Errors'] = 1;
+		$result['Error'][$result['Errors']] = (string) t('The file could not be found.');
+		return $result;
+	}
+
+	$GLOBALS['exiferFileSize'] = filesize($path);
+	
+	// First 2 bytes of JPEG are 0xFFD8 
+	$data = bin2hex(fread( $in, 2 ));
+	if ($data == 'ffd8') {
+		$result['ValidJpeg'] = 1;
+	} else {
+		$result['ValidJpeg'] = 0;
+		fseek($in, 0);
+	}  
+	
+	$result['ValidIPTCData'] = 0;
+	$result['ValidJFIFData'] = 0;
+	$result['ValidEXIFData'] = 0;
+	$result['ValidAPP2Data'] = 0;
+	$result['ValidCOMData'] = 0;
+	
+if ($result['ValidJpeg'] == 1) {
+	// Next 2 bytes are MARKER tag (0xFFE#)
+	$data = bin2hex(fread( $in, 2 ));
+	$size = bin2hex(fread( $in, 2 ));
+
+	// LOOP THROUGH MARKERS TILL YOU GET TO FFE1  (exif marker)
+	$abortCount = 0;
+	while(!feof($in) && $data!='ffe1' && $data!='ffc0' && $data!='ffd9' && ++$abortCount < 200) {
+		if ($data == 'ffe0') { // JFIF Marker
+			$result['ValidJFIFData'] = 1;
+			$result['JFIF']['Size'] = hexdec($size);
+			
+			if (hexdec($size)-2 > 0) {
+				$data = fread( $in, hexdec($size)-2);
+				$result['JFIF']['Data'] = $data;
+			} 
+			
+			$result['JFIF']['Identifier'] = substr($data,0,5);;
+			$result['JFIF']['ExtensionCode'] =  bin2hex(substr($data,6,1));
+			
+			$globalOffset+=hexdec($size)+2;
+			
+		} else if ($data == 'ffed') {  // IPTC Marker
+			$result['ValidIPTCData'] = 1;
+			$result['IPTC']['Size'] = hexdec($size);
+			
+			if (hexdec($size)-2 > 0) {
+				$data = fread( $in, hexdec($size)-2);
+				$result['IPTC']['Data'] = $data ;
+			} 
+			$globalOffset+=hexdec($size)+2;
+			
+		} else if ($data == 'ffe2') {  // EXIF extension Marker
+			$result['ValidAPP2Data'] = 1;
+			$result['APP2']['Size'] = hexdec($size);
+			
+			if (hexdec($size)-2 > 0) {
+				$data = fread( $in, hexdec($size)-2);
+				$result['APP2']['Data'] = $data ;
+			} 
+			$globalOffset+=hexdec($size)+2;
+			
+		} else if ($data == 'fffe') {  // COM extension Marker
+			$result['ValidCOMData'] = 1;
+			$result['COM']['Size'] = hexdec($size);
+			
+			if (hexdec($size)-2 > 0) {
+				$data = fread( $in, hexdec($size)-2);
+				$result['COM']['Data'] = $data ;
+			} 
+			$globalOffset+=hexdec($size)+2;
+			
+		} else if ($data == 'ffe1') {
+			$result['ValidEXIFData'] = 1;
+		}
+	
+		$data = bin2hex(fread( $in, 2 ));
+		$size = bin2hex(fread( $in, 2 ));
+	}
+	// END MARKER LOOP
+	
+	if ($data == 'ffe1') {
+		$result['ValidEXIFData'] = 1;
+	} else {
+		fclose($in);
+		fclose($seek);
+		return $result;
+	}
+	
+	// Size of APP1 
+	$result['APP1Size'] = hexdec($size);
+	
+	// Start of APP1 block starts with 'Exif' header (6 bytes)
+	$header = fread( $in, 6 );
+
+} // END IF ValidJpeg
+	
+	// Then theres a TIFF header with 2 bytes of endieness (II or MM) 
+	$header = fread( $in, 2 );
+	if ($header==='II') {
+		$intel=1;
+		$result['Endien'] = 'Intel';
+	} else if ($header==='MM') {
+		$intel=0;
+		$result['Endien'] = 'Motorola';
+	} else {
+		$intel=1; // not sure what the default should be, but this seems reasonable
+		$result['Endien'] = 'Unknown';
+	}
+	
+	// 2 bytes of 0x002a
+	$tag = bin2hex(fread( $in, 2 ));
+	
+	// Then 4 bytes of offset to IFD0 (usually 8 which includes all 8 bytes of TIFF header)
+	$offset = bin2hex(fread( $in, 4 ));
+	if ($intel == 1) $offset = intel2Moto($offset);
+	
+	// Check for extremely large values here
+	if (hexdec($offset) > 100000) {
+			$result['ValidEXIFData'] = 0;
+		fclose($in);
+		fclose($seek);
+		return $result;
+	}
+
+	if (hexdec($offset)>8) $unknown = fread( $in, hexdec($offset)-8); // fixed this bug in 1.3
+	
+	// add 12 to the offset to account for TIFF header
+	if ($result['ValidJpeg'] == 1) {
+		$globalOffset+=12;
+	}
+	
+	
+	//===========================================================
+	// Start of IFD0
+	$num = bin2hex(fread( $in, 2 ));
+	if ($intel == 1) $num = intel2Moto($num);
+	$num = hexdec($num);
+	$result['IFD0NumTags'] = $num;
+	
+	if ($num<1000) { // 1000 entries is too much and is probably an error.
+		for($i=0; $i<$num; $i++) {
+			read_entry($result,$in,$seek,$intel,'IFD0',$globalOffset);
+		}
+	} else {
+		$result['Errors'] = $result['Errors']+1;
+		$result['Error'][$result['Errors']] = 'Illegal size for IFD0';
+	}
+	
+	// store offset to IFD1
+	$offset = bin2hex(fread( $in, 4 ));
+	if ($intel == 1) $offset = intel2Moto($offset);
+	$result['IFD1Offset'] = hexdec($offset);
+	
+	// Check for SubIFD
+	if (!isset($result['IFD0']['ExifOffset']) || $result['IFD0']['ExifOffset'] == 0) {
+		fclose($in);
+		fclose($seek);
+		return $result;
+	}
+	
+	// seek to SubIFD (Value of ExifOffset tag) above.
+	$ExitOffset = $result['IFD0']['ExifOffset'];
+	$v = fseek($in,$globalOffset+$ExitOffset);
+	if ($v == -1) {
+		$result['Errors'] = $result['Errors']+1;
+		$result['Error'][$result['Errors']] = (string) t('Could not Find SubIFD');
+	}
+	
+	//===========================================================
+	// Start of SubIFD
+	$num = bin2hex(fread( $in, 2 ));
+	if ($intel == 1) $num = intel2Moto($num);
+	$num = hexdec($num);
+	$result['SubIFDNumTags'] = $num;
+	
+	if ($num<1000) { // 1000 entries is too much and is probably an error.
+		for($i=0; $i<$num; $i++) {
+			read_entry($result,$in,$seek,$intel,'SubIFD',$globalOffset);
+		}
+	} else {
+		$result['Errors'] = $result['Errors']+1;
+		$result['Error'][$result['Errors']] = (string) t('Illegal size for SubIFD');
+	}
+	
+	// Add the 35mm equivalent focal length:
+	if (isset($result['IFD0']['FocalLengthIn35mmFilm']) && !isset($result['SubIFD']['FocalLengthIn35mmFilm'])) { // found in the wrong place
+		$result['SubIFD']['FocalLengthIn35mmFilm'] = $result['IFD0']['FocalLengthIn35mmFilm'];
+	}
+	if (!isset($result['SubIFD']['FocalLengthIn35mmFilm'])) {
+		$result['SubIFD']['FocalLengthIn35mmFilm'] = get35mmEquivFocalLength($result);
+	}
+	
+	// Check for IFD1
+	if (!isset($result['IFD1Offset']) || $result['IFD1Offset'] == 0) {
+		fclose($in);
+		fclose($seek);
+		return $result;
+	}
+	// seek to IFD1
+	$v = fseek($in,$globalOffset+$result['IFD1Offset']);
+	if ($v == -1) {
+		$result['Errors'] = $result['Errors']+1;
+		$result['Error'][$result['Errors']] = (string) t('Could not Find IFD1');
+	}
+	
+	//===========================================================
+	// Start of IFD1
+	$num = bin2hex(fread( $in, 2 ));
+	if ($intel == 1) $num = intel2Moto($num);
+	$num = hexdec($num);
+	$result['IFD1NumTags'] = $num;
+	
+	if ($num<1000) { // 1000 entries is too much and is probably an error.
+		for($i=0; $i<$num; $i++) {
+			read_entry($result,$in,$seek,$intel,'IFD1',$globalOffset);
+		}
+	} else {
+		$result['Errors'] = $result['Errors']+1;
+		$result['Error'][$result['Errors']] = (string) t('Illegal size for IFD1');
+	}
+	// If verbose output is on, include the thumbnail raw data...
+	if ($result['VerboseOutput'] == 1 && $result['IFD1']['JpegIFOffset']>0 && $result['IFD1']['JpegIFByteCount']>0) {
+			$v = fseek($seek,$globalOffset+$result['IFD1']['JpegIFOffset']);
+			if ($v == 0) {
+				$data = fread($seek, $result['IFD1']['JpegIFByteCount']);
+			} else if ($v == -1) {
+				$result['Errors'] = $result['Errors']+1;
+			}
+			$result['IFD1']['ThumbnailData'] = $data;
+	} 
+	
+	
+	// Check for Interoperability IFD
+	if (!isset($result['SubIFD']['ExifInteroperabilityOffset']) || $result['SubIFD']['ExifInteroperabilityOffset'] == 0) {
+		fclose($in);
+		fclose($seek);
+		return $result;
+	}
+	// Seek to InteroperabilityIFD
+	$v = fseek($in,$globalOffset+$result['SubIFD']['ExifInteroperabilityOffset']);
+	if ($v == -1) {
+		$result['Errors'] = $result['Errors']+1;
+		$result['Error'][$result['Errors']] = (string) t('Could not Find InteroperabilityIFD');
+	}
+	
+	//===========================================================
+	// Start of InteroperabilityIFD
+	$num = bin2hex(fread( $in, 2 ));
+	if ($intel == 1) $num = intel2Moto($num);
+	$num = hexdec($num);
+	$result['InteroperabilityIFDNumTags'] = $num;
+	
+	if ($num<1000) { // 1000 entries is too much and is probably an error.
+		for($i=0; $i<$num; $i++) {
+			read_entry($result,$in,$seek,$intel,'InteroperabilityIFD',$globalOffset);
+		}
+	} else {
+		$result['Errors'] = $result['Errors']+1;
+		$result['Error'][$result['Errors']] = (string) t('Illegal size for InteroperabilityIFD');
+	}
+	fclose($in);
+	fclose($seek);
+	return $result;
+}
+
+//================================================================================================
+// Converts a floating point number into a fraction.  Many thanks to Matthieu Froment for this code
+//================================================================================================
+function ConvertToFraction($v, &$n, &$d)
+{
+	if ($v == 0) {
+		$n = 0;
+		$d = 1;
+		return;
+	}
+	for ($n=1; $n<100; $n++) {
+		$v1 = 1/$v*$n;
+		$d = round($v1, 0);
+		if (abs($d - $v1) < 0.02) return;// within tolarance
+	}
+}  
+
+//================================================================================================
+// Calculates the 35mm-equivalent focal length from the reported sensor resolution, by Tristan Harward.
+//================================================================================================
+function get35mmEquivFocalLength(&$result) {
+	if (isset($result['SubIFD']['ExifImageWidth'])) {
+		$width = $result['SubIFD']['ExifImageWidth'];
+	} else {
+		$width = 0;
+	}
+	if (isset($result['SubIFD']['FocalPlaneResolutionUnit'])) {
+		$units = $result['SubIFD']['FocalPlaneResolutionUnit'];
+	} else {
+		$units = '';
+	}
+	$unitfactor = 1;
+	switch ($units) {
+		case 'Inch' :       $unitfactor = 25.4; break;
+		case 'Centimeter' : $unitfactor = 10;   break;
+		case 'No Unit' :    $unitfactor = 25.4; break;
+		default :           $unitfactor = 25.4;
+	}
+	if (isset($result['SubIFD']['FocalPlaneXResolution'])) {
+		$xres = $result['SubIFD']['FocalPlaneXResolution'];
+	} else {
+		$xres = '';
+	}
+	if (isset($result['SubIFD']['FocalLength'])) {
+		$fl = $result['SubIFD']['FocalLength'];
+	} else {
+		$fl = 0;
+	}
+
+	if (($width != 0) && !empty($units) && !empty($xres) && !empty($fl) && !empty($width)) {
+		$ccdwidth = ($width * $unitfactor) / $xres;
+		$equivfl = $fl / $ccdwidth*36+0.5;
+		return $equivfl;
+	}
+	return null;
+}
+
+?>
diff --git a/modules/exif/lib/makers/canon.php b/modules/exif/lib/makers/canon.php
new file mode 100644
index 0000000..aecd266
--- /dev/null
+++ b/modules/exif/lib/makers/canon.php
@@ -0,0 +1,426 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+//================================================================================================
+//================================================================================================
+/*
+	Exifer
+	Extracts EXIF information from digital photos.
+	
+	Copyright © 2003 Jake Olefsky
+	http://www.offsky.com/software/exif/index.php
+	jake@olefsky.com
+	
+	Please see exif.php for the complete information about this software.
+	
+	------------
+	
+	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 for more details. http://www.gnu.org/copyleft/gpl.html
+*/
+//================================================================================================
+//================================================================================================
+//================================================================================================
+
+
+//=================
+// Looks up the name of the tag for the MakerNote (Depends on Manufacturer)
+//====================================================================
+function lookup_Canon_tag($tag) {
+	
+	switch($tag) {
+		case "0001": $tag = "Settings 1";break;
+		case "0004": $tag = "Settings 4";break;
+		case "0006": $tag = "ImageType";break;
+		case "0007": $tag = "FirmwareVersion";break;
+		case "0008": $tag = "ImageNumber";break;
+		case "0009": $tag = "OwnerName";break;
+		case "000c": $tag = "CameraSerialNumber";break;	
+		case "000f": $tag = "CustomFunctions";break;	
+		case "0095": $tag = "LensInfo";break;	
+		
+		default: $tag = "unknown:".$tag;break;
+	}
+	
+	return $tag;
+}
+
+//=================
+// Formats Data for the data type
+//====================================================================
+function formatCanonData($type,$tag,$intel,$data,$exif,&$result) {
+	$place = 0;
+	
+	
+	if($type=="ASCII") {
+		$result = $data = str_replace("\0", "", $data);
+	} else if($type=="URATIONAL" || $type=="SRATIONAL") {
+		$data = unRational($data,$type,$intel);
+	
+		if($tag=="0204") { //DigitalZoom
+			$data=$data."x";
+		} 
+		
+	} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+		
+		$data = rational($data,$type,$intel);
+		$result['RAWDATA'] = $data;
+	
+		if($tag=="0001") { //first chunk
+			$result['Bytes']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//0
+			if ($result['Bytes'] != strlen($data) / 2) return $result; //Bad chunk
+			$result['Macro']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//1
+			switch($result['Macro']) {
+				case 1: $result['Macro'] = (string) t("Macro"); break;
+				case 2: $result['Macro'] = (string) t("Normal"); break;
+				default: $result['Macro'] = (string) t("Unknown");
+			}
+			$result['SelfTimer']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//2
+			switch($result['SelfTimer']) {
+				case 0: $result['SelfTimer'] = (string) t("Off"); break;
+				default: $result['SelfTimer'] .= (string) t("/10s");
+			}
+			$result['Quality']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//3
+			switch($result['Quality']) {
+				case 2: $result['Quality'] = (string) t("Normal"); break;
+				case 3: $result['Quality'] = (string) t("Fine"); break;
+				case 5: $result['Quality'] = (string) t("Superfine"); break;
+				default: $result['Quality'] = (string) t("Unknown");
+			}
+			$result['Flash']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//4
+			switch($result['Flash']) {
+				case 0: $result['Flash'] = (string) t("Off"); break;
+				case 1: $result['Flash'] = (string) t("Auto"); break;
+				case 2: $result['Flash'] = (string) t("On"); break;
+				case 3: $result['Flash'] = (string) t("Red Eye Reduction"); break;
+				case 4: $result['Flash'] = (string) t("Slow Synchro"); break;
+				case 5: $result['Flash'] = (string) t("Auto + Red Eye Reduction"); break;
+				case 6: $result['Flash'] = (string) t("On + Red Eye Reduction"); break;
+				case 16: $result['Flash'] = (string) t("External Flash"); break;
+				default: $result['Flash'] = (string) t("Unknown");
+			}
+			$result['DriveMode']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//5
+			switch($result['DriveMode']) {
+				case 0: $result['DriveMode'] = (string) t("Single/Timer"); break;
+				case 1: $result['DriveMode'] = (string) t("Continuous"); break;
+				default: $result['DriveMode'] = (string) t("Unknown");
+			}
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//6
+			$result['FocusMode']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//7
+			switch($result['FocusMode']) {
+				case 0: $result['FocusMode'] = (string) t("One-Shot"); break;
+				case 1: $result['FocusMode'] = (string) t("AI Servo"); break;
+				case 2: $result['FocusMode'] = (string) t("AI Focus"); break;
+				case 3: $result['FocusMode'] = (string) t("Manual Focus"); break;
+				case 4: $result['FocusMode'] = (string) t("Single"); break;
+				case 5: $result['FocusMode'] = (string) t("Continuous"); break;
+				case 6: $result['FocusMode'] = (string) t("Manual Focus"); break;
+				default: $result['FocusMode'] = (string) t("Unknown");
+			}
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//8
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//9
+			$result['ImageSize']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//10
+			switch($result['ImageSize']) {
+				case 0: $result['ImageSize'] = (string) t("Large"); break;
+				case 1: $result['ImageSize'] = (string) t("Medium"); break;
+				case 2: $result['ImageSize'] = (string) t("Small"); break;
+				default: $result['ImageSize'] = (string) t("Unknown");
+			}
+			$result['EasyShooting']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//11
+			switch($result['EasyShooting']) {
+				case 0: $result['EasyShooting'] = (string) t("Full Auto"); break;
+				case 1: $result['EasyShooting'] = (string) t("Manual"); break;
+				case 2: $result['EasyShooting'] = (string) t("Landscape"); break;
+				case 3: $result['EasyShooting'] = (string) t("Fast Shutter"); break;
+				case 4: $result['EasyShooting'] = (string) t("Slow Shutter"); break;
+				case 5: $result['EasyShooting'] = (string) t("Night"); break;
+				case 6: $result['EasyShooting'] = (string) t("Black & White"); break;
+				case 7: $result['EasyShooting'] = (string) t("Sepia"); break;
+				case 8: $result['EasyShooting'] = (string) t("Portrait"); break;
+				case 9: $result['EasyShooting'] = (string) t("Sport"); break;
+				case 10: $result['EasyShooting'] = (string) t("Macro/Close-Up"); break;
+				case 11: $result['EasyShooting'] = (string) t("Pan Focus"); break;
+				default: $result['EasyShooting'] = (string) t("Unknown");
+			}
+			$result['DigitalZoom']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//12
+			switch($result['DigitalZoom']) {
+				case 0:
+				case 65535: $result['DigitalZoom'] = (string) t("None"); break;
+				case 1: $result['DigitalZoom'] = (string) t("2x"); break;
+				case 2: $result['DigitalZoom'] = (string) t("4x"); break;
+				default: $result['DigitalZoom'] = (string) t("Unknown");
+			}
+			$result['Contrast']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//13
+			switch($result['Contrast']) {
+				case 0: $result['Contrast'] = (string) t("Normal"); break;
+				case 1: $result['Contrast'] = (string) t("High"); break;
+				case 65535: $result['Contrast'] = (string) t("Low"); break;
+				default: $result['Contrast'] = (string) t("Unknown");
+			}
+			$result['Saturation']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//14
+			switch($result['Saturation']) {
+				case 0: $result['Saturation'] = (string) t("Normal"); break;
+				case 1: $result['Saturation'] = (string) t("High"); break;
+				case 65535: $result['Saturation'] = (string) t("Low"); break;
+				default: $result['Saturation'] = (string) t("Unknown");
+			}
+			$result['Sharpness']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//15
+			switch($result['Sharpness']) {
+				case 0: $result['Sharpness'] = (string) t("Normal"); break;
+				case 1: $result['Sharpness'] = (string) t("High"); break;
+				case 65535: $result['Sharpness'] = (string) t("Low"); break;
+				default: $result['Sharpness'] = (string) t("Unknown");
+			}
+			$result['ISO']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//16
+			switch($result['ISO']) {
+				case 32767:
+				case 0: $result['ISO'] = isset($exif['SubIFD']['ISOSpeedRatings'])
+					? $exif['SubIFD']['ISOSpeedRatings'] : 'Unknown'; break;
+				case 15: $result['ISO'] = (string) t("Auto"); break;
+				case 16: $result['ISO'] = (string) t("50"); break;
+				case 17: $result['ISO'] = (string) t("100"); break;
+				case 18: $result['ISO'] = (string) t("200"); break;
+				case 19: $result['ISO'] = (string) t("400"); break;
+				default: $result['ISO'] = (string) t("Unknown");
+			}
+			$result['MeteringMode']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//17
+			switch($result['MeteringMode']) {
+				case 3: $result['MeteringMode'] = (string) t("Evaluative"); break;
+				case 4: $result['MeteringMode'] = (string) t("Partial"); break;
+				case 5: $result['MeteringMode'] = (string) t("Center-weighted"); break;
+				default: $result['MeteringMode'] = (string) t("Unknown");
+			}
+			$result['FocusType']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//18
+			switch($result['FocusType']) {
+				case 0: $result['FocusType'] = (string) t("Manual"); break;
+				case 1: $result['FocusType'] = (string) t("Auto"); break;
+				case 3: $result['FocusType'] = (string) t("Close-up (Macro)"); break;
+				case 8: $result['FocusType'] = (string) t("Locked (Pan Mode)"); break;
+				default: $result['FocusType'] = (string) t("Unknown");
+			}
+			$result['AFPointSelected']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//19
+			switch($result['AFPointSelected']) {
+				case 12288: $result['AFPointSelected'] = (string) t("Manual Focus"); break;
+				case 12289: $result['AFPointSelected'] = (string) t("Auto Selected"); break;
+				case 12290: $result['AFPointSelected'] = (string) t("Right"); break;
+				case 12291: $result['AFPointSelected'] = (string) t("Center"); break;
+				case 12292: $result['AFPointSelected'] = (string) t("Left"); break;
+				default: $result['AFPointSelected'] = (string) t("Unknown");
+			}
+			$result['ExposureMode']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//20
+			switch($result['ExposureMode']) {
+				case 0: $result['ExposureMode'] = (string) t("EasyShoot"); break;
+				case 1: $result['ExposureMode'] = (string) t("Program"); break;
+				case 2: $result['ExposureMode'] = (string) t("Tv"); break;
+				case 3: $result['ExposureMode'] = (string) t("Av"); break;
+				case 4: $result['ExposureMode'] = (string) t("Manual"); break;
+				case 5: $result['ExposureMode'] = (string) t("Auto-DEP"); break;
+				default: $result['ExposureMode'] = (string) t("Unknown");
+			}
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//21
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//22
+			$result['LongFocalLength']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//23
+				$result['LongFocalLength'] .= " focal units";
+			$result['ShortFocalLength']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//24
+				$result['ShortFocalLength'] .= " focal units";
+			$result['FocalUnits']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//25
+				$result['FocalUnits'] .= " per mm";
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//26
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//27
+			$result['FlashActivity']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//28
+			switch($result['FlashActivity']) {
+				case 0: $result['FlashActivity'] = (string) t("Flash Did Not Fire"); break;
+				case 1: $result['FlashActivity'] = (string) t("Flash Fired"); break;
+				default: $result['FlashActivity'] = (string) t("Unknown");
+			}
+			$result['FlashDetails']=str_pad(base_convert(intel2Moto(substr($data,$place,4)), 16, 2), 16, "0", STR_PAD_LEFT);$place+=4;//29
+				$flashDetails = array();
+				if (substr($result['FlashDetails'], 1, 1) == 1) { $flashDetails[] = (string) t('External E-TTL'); }
+				if (substr($result['FlashDetails'], 2, 1) == 1) { $flashDetails[] = (string) t('Internal Flash'); }
+				if (substr($result['FlashDetails'], 4, 1) == 1) { $flashDetails[] = (string) t('FP sync used'); }
+				if (substr($result['FlashDetails'], 8, 1) == 1) { $flashDetails[] = (string) t('2nd(rear)-curtain sync used'); }
+				if (substr($result['FlashDetails'], 12, 1) == 1) { $flashDetails[] = (string) t('1st curtain sync'); }
+				$result['FlashDetails']=implode(",", $flashDetails);
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//30
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//31
+			$anotherFocusMode=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//32
+			if(strpos(strtoupper($exif['IFD0']['Model']), "G1") !== false) {
+				switch($anotherFocusMode) {
+					case 0: $result['FocusMode'] = (string) t("Single"); break;
+					case 1: $result['FocusMode'] = (string) t("Continuous"); break;
+					default: $result['FocusMode'] = (string) t("Unknown");
+				}
+			}
+			
+		} else if($tag=="0004") { //second chunk
+			$result['Bytes']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//0
+			if ($result['Bytes'] != strlen($data) / 2) return $result; //Bad chunk
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//1
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//2
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//3
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//4
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//5
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//6
+			$result['WhiteBalance']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//7
+			switch($result['WhiteBalance']) {
+				case 0: $result['WhiteBalance'] = (string) t("Auto"); break;
+				case 1: $result['WhiteBalance'] = (string) t("Sunny"); break;
+				case 2: $result['WhiteBalance'] = (string) t("Cloudy"); break;
+				case 3: $result['WhiteBalance'] = (string) t("Tungsten"); break;
+				case 4: $result['WhiteBalance'] = (string) t("Fluorescent"); break;
+				case 5: $result['WhiteBalance'] = (string) t("Flash"); break;
+				case 6: $result['WhiteBalance'] = (string) t("Custom"); break;
+				default: $result['WhiteBalance'] = (string) t("Unknown");
+			}
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//8
+			$result['SequenceNumber']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//9
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//10
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//11
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//12
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//13
+			$result['AFPointUsed']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//14
+				$afPointUsed = array();
+				if ($result['AFPointUsed'] & 0x0001) $afPointUsed[] = (string) t("Right"); //bit 0
+				if ($result['AFPointUsed'] & 0x0002) $afPointUsed[] = (string) t("Center"); //bit 1
+				if ($result['AFPointUsed'] & 0x0004) $afPointUsed[] = (string) t("Left"); //bit 2
+				if ($result['AFPointUsed'] & 0x0800) $afPointUsed[] = (string) t("12"); //bit 12
+				if ($result['AFPointUsed'] & 0x1000) $afPointUsed[] = (string) t("13"); //bit 13
+				if ($result['AFPointUsed'] & 0x2000) $afPointUsed[] = (string) t("14"); //bit 14
+				if ($result['AFPointUsed'] & 0x4000) $afPointUsed[] = (string) t("15"); //bit 15
+				$result['AFPointUsed'] = implode(",", $afPointUsed);
+			$result['FlashBias']=intel2Moto(substr($data,$place,4));$place+=4;//15
+			switch($result['FlashBias']) {
+				case 'ffc0': $result['FlashBias'] = "-2 EV"; break;
+				case 'ffcc': $result['FlashBias'] = "-1.67 EV"; break;
+				case 'ffd0': $result['FlashBias'] = "-1.5 EV"; break;
+				case 'ffd4': $result['FlashBias'] = "-1.33 EV"; break;
+				case 'ffe0': $result['FlashBias'] = "-1 EV"; break;
+				case 'ffec': $result['FlashBias'] = "-0.67 EV"; break;
+				case 'fff0': $result['FlashBias'] = "-0.5 EV"; break;
+				case 'fff4': $result['FlashBias'] = "-0.33 EV"; break;
+				case '0000': $result['FlashBias'] = "0 EV"; break;
+				case '000c': $result['FlashBias'] = "0.33 EV"; break;
+				case '0010': $result['FlashBias'] = "0.5 EV"; break;
+				case '0014': $result['FlashBias'] = "0.67 EV"; break;
+				case '0020': $result['FlashBias'] = "1 EV"; break;
+				case '002c': $result['FlashBias'] = "1.33 EV"; break;
+				case '0030': $result['FlashBias'] = "1.5 EV"; break;
+				case '0034': $result['FlashBias'] = "1.67 EV"; break;
+				case '0040': $result['FlashBias'] = "2 EV"; break;
+				default: $result['FlashBias'] = (string) t("Unknown");
+			}
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//16
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//17
+			$result['Unknown']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//18
+			$result['SubjectDistance']=hexdec(intel2Moto(substr($data,$place,4)));$place+=4;//19
+				$result['SubjectDistance'] .= "/100 m";
+			
+		} else if($tag=="0008") { //image number
+			if($intel==1) $data = intel2Moto($data);
+			$data=hexdec($data);
+			$result = round($data/10000)."-".$data%10000;
+		} else if($tag=="000c") { //camera serial number
+			if($intel==1) $data = intel2Moto($data);
+			$data=hexdec($data);
+			$result = "#".bin2hex(substr($data,0,16)).substr($data,16,16);
+		}
+		
+	} else if($type=="UNDEFINED") {
+		
+	
+		
+	} else {
+		$data = bin2hex($data);
+		if($intel==1) $data = intel2Moto($data);
+	}
+	
+	return $data;
+}
+
+
+
+//=================
+// Cannon Special data section
+// Useful:  http://www.burren.cx/david/canon.html
+// http://www.burren.cx/david/canon.html
+// http://www.ozhiker.com/electronics/pjmt/jpeg_info/canon_mn.html
+//====================================================================
+function parseCanon($block,&$result,$seek, $globalOffset) {	
+	$place = 0; //current place
+		
+	if($result['Endien']=="Intel") $intel=1;
+	else $intel=0;
+	
+	$model = $result['IFD0']['Model'];
+	
+		//Get number of tags (2 bytes)
+	$num = bin2hex(substr($block,$place,2));$place+=2;
+	if($intel==1) $num = intel2Moto($num);
+	$result['SubIFD']['MakerNote']['MakerNoteNumTags'] = hexdec($num);
+	
+	//loop thru all tags  Each field is 12 bytes
+	for($i=0;$i<hexdec($num);$i++) {
+		
+			//2 byte tag
+		$tag = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $tag = intel2Moto($tag);
+		$tag_name = lookup_Canon_tag($tag);
+		
+			//2 byte type
+		$type = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $type = intel2Moto($type);
+		lookup_type($type,$size);		
+		
+			//4 byte count of number of data units
+		$count = bin2hex(substr($block,$place,4));$place+=4;
+		if($intel==1) $count = intel2Moto($count);
+		$bytesofdata = $size*hexdec($count);
+		if($bytesofdata<=0) {
+			return; //if this value is 0 or less then we have read all the tags we can
+		}
+		
+			//4 byte value of data or pointer to data
+		$value = substr($block,$place,4);$place+=4;
+		if($bytesofdata<=4) {
+			$data = $value;
+		} else {
+			$value = bin2hex($value);
+			if($intel==1) $value = intel2Moto($value);
+			$v = fseek($seek,$globalOffset+hexdec($value));  //offsets are from TIFF header which is 12 bytes from the start of the file
+			if (isset($GLOBALS['exiferFileSize'])) {
+				$exiferFileSize = $GLOBALS['exiferFileSize'];
+			} else {
+				$exiferFileSize = 0;
+			}
+			if($v==0 && $bytesofdata < $exiferFileSize) {
+				$data = fread($seek, $bytesofdata);
+			} else if($v==-1) {
+				$result['Errors'] = $result['Errors']++;
+				$data = '';
+			} else {
+				$data = '';
+			}
+		}
+		$result['SubIFD']['MakerNote'][$tag_name] = ''; // insure the index exists
+		$formated_data = formatCanonData($type,$tag,$intel,$data,$result,$result['SubIFD']['MakerNote'][$tag_name]);
+		
+		if($result['VerboseOutput']==1) {
+			//$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+			if($type=="URATIONAL" || $type=="SRATIONAL" || $type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+				$data = bin2hex($data);
+				if($intel==1) $data = intel2Moto($data);
+			}
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['RawData'] = $data;
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Type'] = $type;
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Bytes'] = $bytesofdata;
+		} else {
+			//$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+		}
+	}
+}
+
+
+?>
\ No newline at end of file
diff --git a/modules/exif/lib/makers/fujifilm.php b/modules/exif/lib/makers/fujifilm.php
new file mode 100644
index 0000000..a1f2f41
--- /dev/null
+++ b/modules/exif/lib/makers/fujifilm.php
@@ -0,0 +1,247 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+//================================================================================================
+//================================================================================================
+/*
+	Exifer
+	Extracts EXIF information from digital photos.
+	
+	Copyright � 2003 Jake Olefsky
+	http://www.offsky.com/software/exif/index.php
+	jake@olefsky.com
+	
+	Please see exif.php for the complete information about this software.
+	
+	------------
+	
+	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 for more details. http://www.gnu.org/copyleft/gpl.html
+*/
+//================================================================================================
+//================================================================================================
+//================================================================================================
+
+
+//=================
+// Looks up the name of the tag for the MakerNote (Depends on Manufacturer)
+//====================================================================
+function lookup_Fujifilm_tag($tag) {
+	
+	switch($tag) {
+		case "0000": $tag = "Version";break;
+		case "1000": $tag = "Quality";break;
+		case "1001": $tag = "Sharpness";break;
+		case "1002": $tag = "WhiteBalance";break;
+		case "1003": $tag = "Color";break;	
+		case "1004": $tag = "Tone";break;	
+		case "1010": $tag = "FlashMode";break;	
+		case "1011": $tag = "FlashStrength";break;	
+		case "1020": $tag = "Macro";break;	
+		case "1021": $tag = "FocusMode";break;	
+		case "1030": $tag = "SlowSync";break;	
+		case "1031": $tag = "PictureMode";break;	
+		case "1100": $tag = "ContinuousTakingBracket";break;	
+		case "1200": $tag = "Unknown";break;	
+		case "1300": $tag = "BlurWarning";break;	
+		case "1301": $tag = "FocusWarning";break;	
+		case "1302": $tag = "AEWarning";break;	
+		
+		default: $tag = "unknown:".$tag;break;
+	}
+	
+	return $tag;
+}
+
+//=================
+// Formats Data for the data type
+//====================================================================
+function formatFujifilmData($type,$tag,$intel,$data) {
+
+	if($type=="ASCII") {
+		
+		
+	} else if($type=="URATIONAL" || $type=="SRATIONAL") {
+		$data = unRational($data,$type,$intel);
+	
+		if($tag=="1011") { //FlashStrength
+			$data=$data." EV";
+		} 
+		
+	} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+		$data =rational($data,$type,$intel);
+		
+		if($tag=="1001") { //Sharpness
+			if($data == 1) $data = (string) t("Soft");
+			else if($data == 2) $data = (string) t("Soft");
+			else if($data == 3) $data = (string) t("Normal");
+			else if($data == 4) $data = (string) t("Hard");
+			else if($data == 5) $data = (string) t("Hard");
+			else $data = (string) t("Unknown").": ".$data;
+		}
+		if($tag=="1002") { //WhiteBalance
+			if($data == 0) $data = (string) t("Auto");
+			else if($data == 256) $data = (string) t("Daylight");
+			else if($data == 512) $data = (string) t("Cloudy");
+			else if($data == 768) $data = (string) t("DaylightColor-fluorescence");
+			else if($data == 769) $data = (string) t("DaywhiteColor-fluorescence");
+			else if($data == 770) $data = (string) t("White-fluorescence");
+			else if($data == 1024) $data = (string) t("Incandescence");
+			else if($data == 3840) $data = (string) t("Custom");
+			else $data = (string) t("Unknown").": ".$data;
+		}
+		if($tag=="1003") { //Color
+			if($data == 0) $data = (string) t("Chroma Saturation Normal(STD)");
+			else if($data == 256) $data = (string) t("Chroma Saturation High");
+			else if($data == 512) $data = (string) t("Chroma Saturation Low(ORG)");
+			else $data = (string) t("Unknown: ").$data;
+		}
+		if($tag=="1004") { //Tone
+			if($data == 0) $data = (string) t("Contrast Normal(STD)");
+			else if($data == 256) $data = (string) t("Contrast High(HARD)");
+			else if($data == 512) $data = (string) t("Contrast Low(ORG)");
+			else $data = (string) t("Unknown: ").$data;
+		}
+		if($tag=="1010") { //FlashMode
+			if($data == 0) $data = (string) t("Auto");
+			else if($data == 1) $data = (string) t("On");
+			else if($data == 2) $data = (string) t("Off");
+			else if($data == 3) $data = (string) t("Red-Eye Reduction");
+			else $data = (string) t("Unknown: ").$data;
+		}
+		if($tag=="1020") { //Macro
+			if($data == 0) $data = (string) t("Off");
+			else if($data == 1) $data = (string) t("On");
+			else $data = (string) t("Unknown: ").$data;
+		}
+		if($tag=="1021") { //FocusMode
+			if($data == 0) $data = (string) t("Auto");
+			else if($data == 1) $data = (string) t("Manual");
+			else $data = (string) t("Unknown: ").$data;
+		}
+		if($tag=="1030") { //SlowSync
+			if($data == 0) $data = (string) t("Off");
+			else if($data == 1) $data = (string) t("On");
+			else $data = (string) t("Unknown: ").$data;
+		}
+		if($tag=="1031") { //PictureMode
+			if($data == 0) $data = (string) t("Auto");
+			else if($data == 1) $data = (string) t("Portrait");
+			else if($data == 2) $data = (string) t("Landscape");
+			else if($data == 4) $data = (string) t("Sports");
+			else if($data == 5) $data = (string) t("Night");
+			else if($data == 6) $data = (string) t("Program AE");
+			else if($data == 256) $data = (string) t("Aperture Priority AE");
+			else if($data == 512) $data = (string) t("Shutter Priority");
+			else if($data == 768) $data = (string) t("Manual Exposure");
+			else $data = (string) t("Unknown: ").$data;
+		}
+		if($tag=="1100") { //ContinuousTakingBracket
+			if($data == 0) $data = (string) t("Off");
+			else if($data == 1) $data = (string) t("On");
+			else $data = (string) t("Unknown: ").$data;
+		}
+		if($tag=="1300") { //BlurWarning
+			if($data == 0) $data = (string) t("No Warning");
+			else if($data == 1) $data = (string) t("Warning");
+			else $data = (string) t("Unknown: ").$data;
+		}
+		if($tag=="1301") { //FocusWarning
+			if($data == 0) $data = (string) t("Auto Focus Good");
+			else if($data == 1) $data = (string) t("Out of Focus");
+			else $data = (string) t("Unknown: ").$data;
+		}
+		if($tag=="1302") { //AEWarning
+			if($data == 0) $data = (string) t("AE Good");
+			else if($data == 1) $data = (string) t("Over Exposure");
+			else $data = (string) t("Unknown: ").$data;
+		}
+	} else if($type=="UNDEFINED") {
+		
+	
+		
+	} else {
+		$data = bin2hex($data);
+		if($intel==1) $data = intel2Moto($data);
+	}
+	
+	return $data;
+}
+
+
+
+//=================
+// Fujifilm Special data section
+//====================================================================
+function parseFujifilm($block,&$result) {	
+		
+	//if($result['Endien']=="Intel") $intel=1;
+	//else $intel=0;
+	$intel=1;
+	
+	$model = $result['IFD0']['Model'];
+
+	$place=8; //current place
+	$offset=8;
+	
+	
+	$num = bin2hex(substr($block,$place,4));$place+=4;
+	if($intel==1) $num = intel2Moto($num);
+	$result['SubIFD']['MakerNote']['Offset'] = hexdec($num);
+	
+		//Get number of tags (2 bytes)
+	$num = bin2hex(substr($block,$place,2));$place+=2;
+	if($intel==1) $num = intel2Moto($num);
+	$result['SubIFD']['MakerNote']['MakerNoteNumTags'] = hexdec($num);
+	
+	//loop thru all tags  Each field is 12 bytes
+	for($i=0;$i<hexdec($num);$i++) {
+		
+			//2 byte tag
+		$tag = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $tag = intel2Moto($tag);
+		$tag_name = lookup_Fujifilm_tag($tag);
+		
+			//2 byte type
+		$type = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $type = intel2Moto($type);
+		lookup_type($type,$size);
+		
+			//4 byte count of number of data units
+		$count = bin2hex(substr($block,$place,4));$place+=4;
+		if($intel==1) $count = intel2Moto($count);
+		$bytesofdata = $size*hexdec($count);
+		
+			//4 byte value of data or pointer to data
+		$value = substr($block,$place,4);$place+=4;
+
+		
+		if($bytesofdata<=4) {
+			$data = $value;
+		} else {
+			$value = bin2hex($value);
+			if($intel==1) $value = intel2Moto($value);
+			$data = substr($block,hexdec($value)-$offset,$bytesofdata*2);
+		}
+		$formated_data = formatFujifilmData($type,$tag,$intel,$data);
+		
+		if($result['VerboseOutput']==1) {
+			$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+			if($type=="URATIONAL" || $type=="SRATIONAL" || $type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+				$data = bin2hex($data);
+				if($intel==1) $data = intel2Moto($data);
+			}
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['RawData'] = $data;
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Type'] = $type;
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Bytes'] = $bytesofdata;
+		} else {
+			$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+		}
+	}
+}
+
+
+?>
\ No newline at end of file
diff --git a/modules/exif/lib/makers/gps.php b/modules/exif/lib/makers/gps.php
new file mode 100644
index 0000000..462aae6
--- /dev/null
+++ b/modules/exif/lib/makers/gps.php
@@ -0,0 +1,218 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+//================================================================================================
+//================================================================================================
+/*
+	Exifer
+	Extracts EXIF information from digital photos.
+	
+	Copyright © 2003 Jake Olefsky
+	http://www.offsky.com/software/exif/index.php
+	jake@olefsky.com
+	
+	Please see exif.php for the complete information about this software.
+	
+	------------
+	
+	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 for more details. http://www.gnu.org/copyleft/gpl.html
+*/
+//================================================================================================
+//================================================================================================
+//================================================================================================
+
+
+
+//=================
+// Looks up the name of the tag
+//====================================================================
+function lookup_GPS_tag($tag) {
+
+	switch($tag) {
+		case "0000": $tag = "Version";break;
+		case "0001": $tag = "Latitude Reference";break;			//north or south
+		case "0002": $tag = "Latitude";break;					//dd mm.mm or dd mm ss
+		case "0003": $tag = "Longitude Reference";break;		//east or west
+		case "0004": $tag = "Longitude";break;					//dd mm.mm or dd mm ss
+		case "0005": $tag = "Altitude Reference";break;			//sea level or below sea level
+		case "0006": $tag = "Altitude";break;					//positive rational number
+		case "0007": $tag = "Time";break;						//three positive rational numbers
+		case "0008": $tag = "Satellite";break;					//text string up to 999 bytes long
+		case "0009": $tag = "ReceiveStatus";break;				//in progress or interop
+		case "000a": $tag = "MeasurementMode";break;			//2D or 3D
+		case "000b": $tag = "MeasurementPrecision";break;		//positive rational number
+		case "000c": $tag = "SpeedUnit";break;					//KPH, MPH, knots
+		case "000d": $tag = "ReceiverSpeed";break;				//positive rational number	
+		case "000e": $tag = "MovementDirectionRef";break;		//true or magnetic north
+		case "000f": $tag = "MovementDirection";break;			//positive rational number
+		case "0010": $tag = "ImageDirectionRef";break;			//true or magnetic north
+		case "0011": $tag = "ImageDirection";break;				//positive rational number
+		case "0012": $tag = "GeodeticSurveyData";break;			//text string up to 999 bytes long
+		case "0013": $tag = "DestLatitudeRef";break;			//north or south
+		case "0014": $tag = "DestinationLatitude";break;		//three positive rational numbers
+		case "0015": $tag = "DestLongitudeRef";break;			//east or west
+		case "0016": $tag = "DestinationLongitude";break;		//three positive rational numbers
+		case "0017": $tag = "DestBearingRef";break;				//true or magnetic north
+		case "0018": $tag = "DestinationBearing";break;			//positive rational number
+		case "0019": $tag = "DestDistanceRef";break;			//km, miles, knots
+		case "001a": $tag = "DestinationDistance";break;		//positive rational number
+		case "001b": $tag = "ProcessingMethod";break;			
+		case "001c": $tag = "AreaInformation";break;
+		case "001d": $tag = "Datestamp";break;					//text string 10 bytes long
+		case "001e": $tag = "DifferentialCorrection";break;		//integer in range 0-65535
+		
+		
+		default: $tag = "unknown:".$tag;break;
+	}
+	
+	return $tag;
+}
+
+//=================
+// Formats Data for the data type
+//====================================================================
+function formatGPSData($type,$tag,$intel,$data) {
+
+	if($type=="ASCII") {
+		if($tag=="0001" || $tag=="0003"){ // Latitude Reference, Longitude Reference
+			$data = ($data{1} == $data{2} && $data{1} == $data{3}) ? $data{0} : $data;
+		}
+
+	} else if($type=="URATIONAL" || $type=="SRATIONAL") {
+		if($tag=="0002" || $tag=="0004" || $tag=='0007') { //Latitude, Longitude, Time
+			$datum = array();
+			for ($i=0;$i<strlen($data);$i=$i+8) {
+				array_push($datum,substr($data, $i, 8));
+			}
+			$hour = unRational($datum[0],$type,$intel);
+			$minutes = unRational($datum[1],$type,$intel);
+			$seconds = unRational($datum[2],$type,$intel);
+			if($tag=="0007") { //Time
+				$data = $hour.":".$minutes.":".$seconds;
+			} else {
+				$data = $hour+$minutes/60+$seconds/3600;
+			}
+		} else {
+			$data = unRational($data,$type,$intel);
+			
+			if($tag=="0006"){
+				$data .= 'm';
+			}
+		}
+	} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+		$data = rational($data,$type,$intel);
+
+
+	} else if($type=="UNDEFINED") {
+
+
+
+	} else if($type=="UBYTE") {
+		$data = bin2hex($data);
+		if($intel==1) $num = intel2Moto($data);
+
+			
+		if($tag=="0000") { // VersionID
+			$data =  hexdec(substr($data,0,2)) .
+												".". hexdec(substr($data,2,2)) .
+												".". hexdec(substr($data,4,2)) .
+												".". hexdec(substr($data,6,2));
+
+		} else if($tag=="0005"){ // Altitude Reference
+			if($data == "00000000"){ $data = '+'; }
+			else if($data == "01000000"){ $data = '-'; }
+		}
+
+	} else {
+		$data = bin2hex($data);
+		if($intel==1) $data = intel2Moto($data);
+	}
+
+	return $data;
+}
+
+
+//=================
+// GPS Special data section
+// Useful websites
+// http://drewnoakes.com/code/exif/sampleOutput.html
+// http://www.geosnapper.com
+//====================================================================
+function parseGPS($block,&$result,$offset,$seek, $globalOffset) {	
+	
+	if($result['Endien']=="Intel") $intel=1;
+	else $intel=0;
+		
+	$v = fseek($seek,$globalOffset+$offset);  //offsets are from TIFF header which is 12 bytes from the start of the file
+	if($v==-1) {
+		$result['Errors'] = $result['Errors']++;
+	}
+
+	$num = bin2hex(fread( $seek, 2 ));
+	if($intel==1) $num = intel2Moto($num);
+	$num=hexdec($num);
+	$result['GPS']['NumTags'] = $num;
+
+	if ($num == 0) {
+		return;
+	}
+
+	$block = fread( $seek, $num*12 );
+	$place = 0;
+	
+	//loop thru all tags  Each field is 12 bytes
+	for($i=0;$i<$num;$i++) {
+			//2 byte tag
+		$tag = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $tag = intel2Moto($tag);
+		$tag_name = lookup_GPS_tag($tag);
+		
+		//2 byte datatype
+		$type = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $type = intel2Moto($type);
+		lookup_type($type,$size);
+		
+		//4 byte number of elements
+		$count = bin2hex(substr($block,$place,4));$place+=4;
+		if($intel==1) $count = intel2Moto($count);
+		$bytesofdata = $size*hexdec($count);
+		
+		//4 byte value or pointer to value if larger than 4 bytes
+		$value = substr($block,$place,4);$place+=4;
+		if($bytesofdata<=4) {
+			$data = $value;
+		} else {
+			if (strpos('unknown',$tag_name) !== false || $bytesofdata > 1024) {
+				$result['Errors'] = $result['Errors']++;
+				$data = '';
+				$type = 'ASCII';
+			} else {
+				$value = bin2hex($value);
+				if($intel==1) $value = intel2Moto($value);
+				$v = fseek($seek,$globalOffset+hexdec($value));  //offsets are from TIFF header which is 12 bytes from the start of the file
+				if($v==0) {
+					$data = fread($seek, $bytesofdata);
+				} else {
+					$result['Errors'] = $result['Errors']++;
+					$data = '';
+					$type = 'ASCII';
+				}
+			}
+		}
+		if($result['VerboseOutput']==1) {
+			$result['GPS'][$tag_name] = formatGPSData($type,$tag,$intel,$data);
+			$result['GPS'][$tag_name."_Verbose"]['RawData'] = bin2hex($data);
+			$result['GPS'][$tag_name."_Verbose"]['Type'] = $type;
+			$result['GPS'][$tag_name."_Verbose"]['Bytes'] = $bytesofdata;
+		} else {
+			$result['GPS'][$tag_name] = formatGPSData($type,$tag,$intel,$data);
+		}
+	}
+}
+
+
+?>
diff --git a/modules/exif/lib/makers/nikon.php b/modules/exif/lib/makers/nikon.php
new file mode 100644
index 0000000..d2fff9a
--- /dev/null
+++ b/modules/exif/lib/makers/nikon.php
@@ -0,0 +1,411 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+//================================================================================================
+//================================================================================================
+/*
+	Exifer
+	Extracts EXIF information from digital photos.
+	
+	Copyright � 2003 Jake Olefsky
+	http://www.offsky.com/software/exif/index.php
+	jake@olefsky.com
+	
+	Please see exif.php for the complete information about this software.
+	
+	------------
+	
+	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 for more details. http://www.gnu.org/copyleft/gpl.html
+*/
+//================================================================================================
+//================================================================================================
+//================================================================================================
+
+
+
+//=================
+// Looks up the name of the tag for the MakerNote (Depends on Manufacturer)
+//====================================================================
+function lookup_Nikon_tag($tag,$model) {
+	
+	if($model==0) {
+		switch($tag) {
+			case "0003": $tag = "Quality";break;
+			case "0004": $tag = "ColorMode";break;
+			case "0005": $tag = "ImageAdjustment";break;
+			case "0006": $tag = "CCDSensitivity";break;	
+			case "0007": $tag = "WhiteBalance";break;	
+			case "0008": $tag = "Focus";break;	
+			case "0009": $tag = "Unknown2";break;	
+			case "000a": $tag = "DigitalZoom";break;	
+			case "000b": $tag = (string) t("Converter");break;	
+			
+			default: $tag = "unknown:".$tag;break;
+		}
+	} else if($model==1) {
+		switch($tag) {
+			case "0002": $tag = "ISOSetting";break;
+			case "0003": $tag = "ColorMode";break;
+			case "0004": $tag = "Quality";break;
+			case "0005": $tag = "Whitebalance";break;
+			case "0006": $tag = "ImageSharpening";break;
+			case "0007": $tag = "FocusMode";break;
+			case "0008": $tag = "FlashSetting";break;
+			case "0009": $tag = "FlashMode";break;
+			case "000b": $tag = "WhiteBalanceFine";break;
+			case "000c": $tag = "WB_RBLevels";break;
+			case "000d": $tag = "ProgramShift";break;
+			case "000e": $tag = "ExposureDifference";break;
+			case "000f": $tag = "ISOSelection";break;
+			case "0010": $tag = "DataDump";break;
+			case "0011": $tag = "NikonPreview";break;
+			case "0012": $tag = "FlashExposureComp";break;
+			case "0013": $tag = "ISOSetting2";break;
+			case "0014": $tag = "ColorBalanceA";break;
+			case "0016": $tag = "ImageBoundary";break;
+			case "0017": $tag = "FlashExposureComp";break;
+			case "0018": $tag = "FlashExposureBracketValue";break;
+			case "0019": $tag = "ExposureBracketValue";break;
+			case "001a": $tag = "ImageProcessing";break;
+			case "001b": $tag = "CropHiSpeed";break;
+			case "001c": $tag = "ExposureTuning";break;
+			case "001d": $tag = "SerialNumber";break;
+			case "001e": $tag = "ColorSpace";break;
+			case "001f": $tag = "VRInfo";break;
+			case "0020": $tag = "ImageAuthentication";break;
+			case "0022": $tag = "ActiveD-Lighting";break;
+			case "0023": $tag = "PictureControl";break;
+			case "0024": $tag = "WorldTime";break;
+			case "0025": $tag = "ISOInfo";break;
+			case "002a": $tag = "VignetteControl";break;
+			case "002b": $tag = "DistortInfo";break;
+			case "0080": $tag = "ImageAdjustment";break;
+			case "0081": $tag = "ToneCompensation";break;
+			case "0082": $tag = "Adapter";break;
+			case "0083": $tag = "LensType";break;
+			case "0084": $tag = "LensInfo";break;
+			case "0085": $tag = "ManualFocusDistance";break; 
+			case "0086": $tag = "DigitalZoom";break;
+			case "0087": $tag = "FlashUsed";break;
+			case "0088": $tag = "AFFocusPosition";break;
+			case "0089": $tag = "ShootingMode";break;
+			case "008b": $tag = "LensFStops";break;
+			case "008c": $tag = "ContrastCurve";break;
+			case "008d": $tag = "ColorMode";break;
+			case "0090": $tag = "LightType";break;
+			case "0092": $tag = "HueAdjustment";break;
+			case "0093": $tag = "NEFCompression";break;
+			case "0094": $tag = "Saturation";break;
+			case "0095": $tag = "NoiseReduction";break;
+			case "009a": $tag = "SensorPixelSize";break;
+			
+			default: $tag = "unknown:".$tag;break;
+		}
+	} 
+	
+	return $tag;
+}
+
+
+//=================
+// Formats Data for the data type
+//====================================================================
+function formatNikonData($type,$tag,$intel,$model,$data) {
+	switch ($type) {
+		case "ASCII":
+			break;	// do nothing!
+		case "URATIONAL":
+		case"SRATIONAL":
+			switch ($tag) {
+				case '0084':	// LensInfo
+					$minFL = unRational(substr($data,0,8),$type,$intel);
+					$maxFL = unRational(substr($data,8,8),$type,$intel);
+					$minSP = unRational(substr($data,16,8),$type,$intel);
+					$maxSP = unRational(substr($data,24,8),$type,$intel);
+					if ($minFL == $maxFL) {
+						$data = sprintf('%0.0f f/%0.0f',$minFL,$minSP);
+					} elseif ($minSP == $maxSP) {
+						$data = sprintf('%0.0f-%0.0fmm f/%0.1f',$minFL,$maxFL,$minSP);
+					} else {
+						$data = sprintf('%0.0f-%0.0fmm f/%0.1f-%0.1f',$minFL,$maxFL,$minSP,$maxSP);
+					}
+					break;
+				case "0085":
+					if ($model==1) $data=unRational($data,$type,$intel)." m";	//ManualFocusDistance
+					break;
+				case "0086":
+					if ($model==1) $data=unRational($data,$type,$intel)."x";	//DigitalZoom
+					break;
+				case "000a":
+					if ($model==0) $data=unRational($data,$type,$intel)."x";	//DigitalZoom
+					break;
+				default:
+					$data=unRational($data,$type,$intel);
+					break;
+			}
+			break;
+		case "USHORT":
+		case $type=="SSHORT":
+		case $type=="ULONG":
+		case $type=="SLONG":
+		case $type=="FLOAT":
+		case $type=="DOUBLE":
+			$data = rational($data,$type,$intel);
+			switch ($tag) {
+				case "0003":
+					if ($model==0) { //Quality
+						switch ($data) {
+							case 1:		$data = (string) t("VGA Basic");	break;
+							case 2:		$data = (string) t("VGA Normal");	break;
+							case 3:		$data = (string) t("VGA Fine");	break;
+							case 4:		$data = (string) t("SXGA Basic");	break;
+							case 5:		$data = (string) t("SXGA Normal");	break;
+							case 6:		$data = (string) t("SXGA Fine");	break;
+							default:	$data = (string) t("Unknown").": ".$data;	break;
+						}
+					}
+					break;
+				case "0004":
+					if ($model==0) { //Color
+						switch ($data) {
+							case 1:		$data = (string) t("Color");	break;
+							case 2:		$data = (string) t("Monochrome");	break;
+							default:	$data = (string) t("Unknown").": ".$data;	break;
+						}
+					}
+					break;
+				case "0005":
+					if ($model==0) { //Image Adjustment
+						switch ($data) {
+							case 0:		$data = (string) t("Normal");	break;
+							case 1:		$data = (string) t("Bright+");	break;
+							case 2:		$data = (string) t("Bright-");	break;
+							case 3:		$data = (string) t("Contrast+");	break;
+							case 4:		$data = (string) t("Contrast-");	break;
+							default:	$data = (string) t("Unknown").": ".$data;	break;
+						}
+					}
+					break;
+				case "0006":
+					if ($model==0) { //CCD Sensitivity
+						switch($data) {
+							case 0:		$data = "ISO-80";	break;
+							case 2:		$data = "ISO-160";	break;
+							case 4:		$data = "ISO-320";	break;
+							case 5:		$data = "ISO-100";	break;
+							default:	$data = (string) t("Unknown").": ".$data;	break;
+						}
+					}
+					break;
+				case "0007":
+					if ($model==0) { //White Balance
+						switch ($data) {
+							case 0:		 $data = (string) t("Auto");	break;
+							case 1:		$data = (string) t("Preset");	break;
+							case 2:		$data = (string) t("Daylight");	break;
+							case 3:		$data = (string) t("Incandescence");	break;
+							case 4:		$data = (string) t("Fluorescence");	break;
+							case 5:		$data = (string) t("Cloudy");	break;
+							case 6:		$data = (string) t("SpeedLight");	break;
+							default:	$data = (string) t("Unknown").": ".$data;	break;
+						}
+					}
+					break;
+				case "000b":
+					if ($model==0) { //Converter
+						switch ($data) {
+							case 0:	$data = (string) t("None");	break;
+							case 1:	$data = (string) t("Fisheye");	break;
+							default:	$data = (string) t("Unknown").": ".$data;	break;
+						}
+					}
+					break;
+			}
+			break;
+		case "UNDEFINED":
+			switch ($tag) {
+				case "0001":
+					if ($model==1) $data=$data/100;	break;	//Unknown (Version?)
+					break;
+				case "0088":
+					if ($model==1) { //AF Focus Position
+						$temp = (string) t("Center");
+						$data = bin2hex($data);
+						$data = str_replace("01","Top",$data);
+						$data = str_replace("02","Bottom",$data);
+						$data = str_replace("03","Left",$data);
+						$data = str_replace("04","Right",$data);
+						$data = str_replace("00","",$data);
+						if(strlen($data)==0) $data = $temp;
+					}
+					break;
+			}
+			break;
+		default:
+			$data = bin2hex($data);
+			if($intel==1) $data = intel2Moto($data);
+				switch ($tag) {
+				case "0083":
+					if ($model==1) { //Lens Type
+						$data = hexdec(substr($data,0,2));
+						switch ($data) {
+							case 0: $data = (string) t("AF non D"); break;
+							case 1: $data = (string) t("Manual"); break;
+							case 2: $data = "AF-D or AF-S"; break;
+							case 6: $data = "AF-D G"; break;
+							case 10: $data = "AF-D VR"; break;
+							case 14: $data = "AF-D G VR"; break;
+							default: $data = (string) t("Unknown").": ".$data; break;
+						}
+					}
+					break;
+				case "0087":
+					if ($model==1) { //Flash type
+						$data = hexdec(substr($data,0,2));
+						if($data == 0) $data = (string) t("Did Not Fire");
+						else if($data == 4) $data = (string) t("Unknown");
+						else if($data == 7) $data = (string) t("External");
+						else if($data == 9) $data = (string) t("On Camera");
+						else $data = (string) t("Unknown").": ".$data;
+					}
+					break;
+			}
+			break;
+	}
+	return $data;
+}
+
+
+//=================
+// Nikon Special data section
+//====================================================================
+function parseNikon($block,&$result) {	
+	
+	if($result['Endien']=="Intel") $intel=1;
+	else $intel=0;
+	
+	$model = $result['IFD0']['Model'];
+
+	//these 6 models start with "Nikon".  Other models dont.
+	if($model=="E700\0" || $model=="E800\0" || $model=="E900\0" || $model=="E900S\0" || $model=="E910\0" || $model=="E950\0") {
+		$place=8; //current place
+		$model = 0;
+		
+		//Get number of tags (2 bytes)
+		$num = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $num = intel2Moto($num);
+		$result['SubIFD']['MakerNote']['MakerNoteNumTags'] = hexdec($num);
+		
+		//loop thru all tags  Each field is 12 bytes
+		for($i=0;$i<hexdec($num);$i++) {
+			//2 byte tag
+			$tag = bin2hex(substr($block,$place,2));$place+=2;
+			if($intel==1) $tag = intel2Moto($tag);
+			$tag_name = lookup_Nikon_tag($tag, $model);
+			
+			//2 byte type
+			$type = bin2hex(substr($block,$place,2));$place+=2;
+			if($intel==1) $type = intel2Moto($type);
+			lookup_type($type,$size);
+			
+			//4 byte count of number of data units
+			$count = bin2hex(substr($block,$place,4));$place+=4;
+			if($intel==1) $count = intel2Moto($count);
+			$bytesofdata = $size*hexdec($count);
+			
+			//4 byte value of data or pointer to data
+			$value = substr($block,$place,4);$place+=4;
+			
+			//if tag is 0002 then its the ASCII value which we know is at 140 so calc offset
+			//THIS HACK ONLY WORKS WITH EARLY NIKON MODELS
+			if($tag=="0002") $offset = hexdec($value)-140;
+			if($bytesofdata<=4) {
+				$data = $value;
+			} else {
+				$value = bin2hex($value);
+				if($intel==1) $value = intel2Moto($value);
+				$data = substr($block,hexdec($value)-$offset,$bytesofdata*2);
+			}
+			$formated_data = formatNikonData($type,$tag,$intel,$model,$data);
+		
+			if($result['VerboseOutput']==1) {
+				$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+				$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['RawData'] = $data;
+				$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Type'] = $type;
+				$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Bytes'] = $bytesofdata;
+			} else {
+				$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+			}
+		}
+	
+	} else {
+		$place=0;//current place
+		$model = 1;
+		
+		$nikon = substr($block,$place,8);$place+=8;
+		$endien = substr($block,$place,4);$place+=4;
+		
+		//2 bytes of 0x002a
+		$tag = bin2hex(substr($block,$place,2));$place+=2;
+		
+		//Then 4 bytes of offset to IFD0 (usually 8 which includes all 8 bytes of TIFF header)
+		$offset = bin2hex(substr($block,$place,4));$place+=4;
+		if($intel==1) $offset = intel2Moto($offset);
+		if(hexdec($offset)>8) $place+=$offset-8;
+		
+		//Get number of tags (2 bytes)
+		$num = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $num = intel2Moto($num);
+		
+		//loop thru all tags  Each field is 12 bytes
+		for($i=0;$i<hexdec($num);$i++) {
+			//2 byte tag
+			$tag = bin2hex(substr($block,$place,2));$place+=2;
+			if($intel==1) $tag = intel2Moto($tag);
+			$tag_name = lookup_Nikon_tag($tag, $model);
+			
+			//2 byte type
+			$type = bin2hex(substr($block,$place,2));$place+=2;
+			if($intel==1) $type = intel2Moto($type);
+			lookup_type($type,$size);
+			
+			//4 byte count of number of data units
+			$count = bin2hex(substr($block,$place,4));$place+=4;
+			if($intel==1) $count = intel2Moto($count);
+			$bytesofdata = $size*hexdec($count);
+			
+			//4 byte value of data or pointer to data
+			$value = substr($block,$place,4);$place+=4;
+			
+			if($bytesofdata<=4) {
+				$data = $value;
+			} else {
+				$value = bin2hex($value);
+				if($intel==1) $value = intel2Moto($value);
+				$data = substr($block,hexdec($value)+hexdec($offset)+2,$bytesofdata);
+			}
+			$formated_data = formatNikonData($type,$tag,$intel,$model,$data);
+		
+			if($result['VerboseOutput']==1) {
+				$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+				if($type=="URATIONAL" || $type=="SRATIONAL" || $type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+					$data = bin2hex($data);
+					if($intel==1) $data = intel2Moto($data);
+				}
+				$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['RawData'] = $data;
+				$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Type'] = $type;
+				$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Bytes'] = $bytesofdata;
+			} else {
+				$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+			}
+		}
+		
+	}
+}
+
+
+?>
\ No newline at end of file
diff --git a/modules/exif/lib/makers/olympus.php b/modules/exif/lib/makers/olympus.php
new file mode 100644
index 0000000..3382fc7
--- /dev/null
+++ b/modules/exif/lib/makers/olympus.php
@@ -0,0 +1,189 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+//================================================================================================
+//================================================================================================
+/*
+	Exifer
+	Extracts EXIF information from digital photos.
+	
+	Copyright � 2003 Jake Olefsky
+	http://www.offsky.com/software/exif/index.php
+	jake@olefsky.com
+	
+	Please see exif.php for the complete information about this software.
+	
+	------------
+	
+	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 for more details. http://www.gnu.org/copyleft/gpl.html
+*/
+//================================================================================================
+//================================================================================================
+//================================================================================================
+
+
+
+//=================
+// Looks up the name of the tag for the MakerNote (Depends on Manufacturer)
+//====================================================================
+function lookup_Olympus_tag($tag) {
+	switch($tag) {
+		case "0200": $tag = "SpecialMode";break;
+		case "0201": $tag = "JpegQual";break;
+		case "0202": $tag = "Macro";break;
+		case "0203": $tag = "Unknown1";break;
+		case "0204": $tag = "DigiZoom";break;	
+		case "0205": $tag = "Unknown2";break;	
+		case "0206": $tag = "Unknown3";break;	
+		case "0207": $tag = "SoftwareRelease";break;	
+		case "0208": $tag = "PictInfo";break;	
+		case "0209": $tag = "CameraID";break;	
+		case "0f00": $tag = "DataDump";break;	
+		
+		default: $tag = "unknown:".$tag;break;
+	}
+	
+	return $tag;
+}
+
+//=================
+// Formats Data for the data type
+//====================================================================
+function formatOlympusData($type,$tag,$intel,$data) {
+	if($type=="ASCII") {
+		
+	} else if($type=="URATIONAL" || $type=="SRATIONAL") {
+		$data = unRational($data,$type,$intel);
+		if($intel==1) $data = intel2Moto($data);
+	
+		if($tag=="0204") { //DigitalZoom
+			$data=$data."x";
+		} 
+		if($tag=="0205") { //Unknown2
+
+		} 
+	} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+		$data = rational($data,$type,$intel);
+		
+		if($tag=="0201") { //JPEGQuality
+			if($data == 1) $data = "SQ";
+			else if($data == 2) $data = "HQ";
+			else if($data == 3) $data = "SHQ";
+			else $data = (string) t("Unknown").": ".$data;
+		}
+		if($tag=="0202") { //Macro
+			if($data == 0) $data = "Normal";
+			else if($data == 1) $data = "Macro";
+			else $data = (string) t("Unknown").": ".$data;
+		}
+	} else if($type=="UNDEFINED") {
+		
+	} else {
+		$data = bin2hex($data);
+		if($intel==1) $data = intel2Moto($data);
+	}
+	
+	return $data;
+}
+
+
+
+//==============================================================================
+// Olympus Special data section
+// - Updated by Zenphoto for new header tag in E-410/E-510/E-3 cameras. 2/24/2008
+//==============================================================================
+function parseOlympus($block, &$result, $seek, $globalOffset) {	
+		
+	if($result['Endien']=="Intel") $intel = 1;
+	else $intel = 0;
+	
+	$model = $result['IFD0']['Model'];
+	
+	// New header for new DSLRs - Check for it because the
+	// number of bytes that count the IFD fields differ in each case.
+	// Fixed by Zenphoto 2/24/08
+	$new = false;
+	if (substr($block, 0, 8) == "OLYMPUS\x00") {
+		$new = true;
+	} else if (substr($block, 0, 7) == "OLYMP\x00\x01"
+		|| substr($block, 0, 7) == "OLYMP\x00\x02") {
+		$new = false;
+	} else {
+		// Header does not match known Olympus headers.
+		// This is not a valid OLYMPUS Makernote.
+		return false;
+	}
+	
+	// Offset of IFD entry after Olympus header.
+	$place = 8;
+	$offset = 8;
+	
+	// Get number of tags (1 or 2 bytes, depending on New or Old makernote)
+	$countfieldbits = $new ? 1 : 2;
+	// New makernote repeats 1-byte value twice, so increment $place by 2 in either case.
+	$num = bin2hex(substr($block, $place, $countfieldbits)); $place += 2;
+	if ($intel == 1) $num = intel2Moto($num);
+	$ntags = hexdec($num);
+	$result['SubIFD']['MakerNote']['MakerNoteNumTags'] = $ntags;
+	
+	//loop thru all tags  Each field is 12 bytes
+	for($i=0; $i < $ntags; $i++) {
+		//2 byte tag
+		$tag = bin2hex(substr($block, $place,2));
+		$place += 2;
+		if ($intel == 1) $tag = intel2Moto($tag);
+		$tag_name = lookup_Olympus_tag($tag);
+		
+		//2 byte type
+		$type = bin2hex(substr($block, $place,2));
+		$place += 2;
+		if ($intel == 1) $type = intel2Moto($type);
+		lookup_type($type,$size);
+		
+		//4 byte count of number of data units
+		$count = bin2hex(substr($block, $place,4));
+		$place+=4;
+		if ($intel == 1) $count = intel2Moto($count);
+		$bytesofdata = $size * hexdec($count);
+		
+		//4 byte value of data or pointer to data
+		$value = substr($block, $place,4);
+		$place += 4;
+
+		
+		if ($bytesofdata <= 4) {
+			$data = $value;
+		} else {
+			$value = bin2hex($value);
+			if($intel==1) $value = intel2Moto($value);
+			$v = fseek($seek,$globalOffset+hexdec($value));  //offsets are from TIFF header which is 12 bytes from the start of the file
+			if(isset($GLOBALS['exiferFileSize']) && $v == 0 && $bytesofdata < $GLOBALS['exiferFileSize']) {
+				$data = fread($seek, $bytesofdata);
+			} else {
+				$result['Errors'] = $result['Errors']++;
+				$data = '';
+			}
+		}
+		$formated_data = formatOlympusData($type,$tag,$intel,$data);
+		
+		if($result['VerboseOutput']==1) {
+			$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+			if($type=="URATIONAL" || $type=="SRATIONAL" || $type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+				$data = bin2hex($data);
+				if($intel==1) $data = intel2Moto($data);
+			}
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['RawData'] = $data;
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Type'] = $type;
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Bytes'] = $bytesofdata;
+		} else {
+			$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+		}
+	}
+}
+
+
+?>
\ No newline at end of file
diff --git a/modules/exif/lib/makers/panasonic.php b/modules/exif/lib/makers/panasonic.php
new file mode 100644
index 0000000..47a0599
--- /dev/null
+++ b/modules/exif/lib/makers/panasonic.php
@@ -0,0 +1,292 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+//================================================================================================
+//================================================================================================
+//================================================================================================
+/*
+	Exifer
+	Extracts EXIF information from digital photos.
+	
+	Copyright � 2003 Jake Olefsky
+	http://www.offsky.com/software/exif/index.php
+	jake@olefsky.com
+	
+	Please see exif.php for the complete information about this software.
+	
+	------------
+	
+	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 for more details. http://www.gnu.org/copyleft/gpl.html
+*/
+//================================================================================================
+//================================================================================================
+//================================================================================================
+
+
+//=================
+// Looks up the name of the tag for the MakerNote (Depends on Manufacturer)
+//====================================================================
+function lookup_Panasonic_tag($tag) {
+	
+	switch($tag) {
+		case "0001": $tag = "Quality";break;
+		case "0002": $tag = "FirmwareVersion";break;
+		case "0003": $tag = "WhiteBalance";break;
+		case "0007": $tag = "FocusMode";break;
+		case "000f": $tag = "AFMode";break;	
+		case "001a": $tag = "ImageStabilizer";break;	
+		case "001c": $tag = "MacroMode";break;	
+		case "001f": $tag = "ShootingMode";break;	
+		case "0020": $tag = "Audio";break;	
+		case "0021": $tag = "DataDump";break;
+		case "0023": $tag = "WhiteBalanceBias";break;	
+		case "0024": $tag = "FlashBias";break;	
+		case "0025": $tag = "SerialNumber";break;	
+		case "0028": $tag = "ColourEffect";break;	
+		case "002a": $tag = "BurstMode";break;	
+		case "002b": $tag = "SequenceNumber";break;	
+		case "002c": $tag = "Contrast";break;	
+		case "002d": $tag = "NoiseReduction";break;	
+		case "002e": $tag = "SelfTimer";break;	
+		case "0030": $tag = "Rotation";break;	
+		case "0032": $tag = "ColorMode";break;	
+		case "0036": $tag = "TravelDay";break;	
+		
+		default: $tag = "unknown:".$tag;break;
+	}
+	
+	return $tag;
+}
+
+//=================
+// Formats Data for the data type
+//====================================================================
+function formatPanasonicData($type,$tag,$intel,$data) {
+
+	if($type=="ASCII") {
+
+	} else if($type=="UBYTE" || $type=="SBYTE") {
+		$data = bin2hex($data);
+		if($intel==1) $data = intel2Moto($data);
+		$data=hexdec($data);
+
+		if($tag=="000f") { //AFMode
+			if($data == 256) $data = "9-area-focusing";
+			else if($data == 16) $data = "1-area-focusing";
+      else if($data == 4096) $data = (string) t("3-area-focusing (High speed)");
+			else if($data == 4112) $data = (string) t("1-area-focusing (High speed)");
+			else if($data == 16) $data = (string) t("1-area-focusing");
+			else if($data == 1) $data = (string) t("Spot-focusing");
+			else $data = "Unknown (".$data.")";
+		} 
+	
+	} else if($type=="URATIONAL" || $type=="SRATIONAL") {
+		$data = unRational($data,$type,$intel);
+
+	} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+		$data = rational($data,$type,$intel);
+		
+		if($tag=="0001") { //Image Quality
+			if($data == 2) $data = (string) t("High");
+			else if($data == 3) $data = (string) t("Standard");
+			else if($data == 6) $data = (string) t("Very High");
+			else if($data == 7) $data = (string) t("RAW");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="0003") { //White Balance
+			if($data == 1) $data = (string) t("Auto");
+			else if($data == 2) $data = (string) t("Daylight");
+			else if($data == 3) $data = (string) t("Cloudy");
+			else if($data == 4) $data = (string) t("Halogen");
+			else if($data == 5) $data = (string) t("Manual");
+			else if($data == 8) $data = (string) t("Flash");
+			else if($data == 10) $data = (string) t("Black and White");
+			else if($data == 11) $data = (string) t("Manual");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="0007") { //Focus Mode
+			if($data == 1) $data = (string) t("Auto");
+			else if($data == 2) $data = (string) t("Manual");
+			else if($data == 4) $data = (string) t("Auto, Focus button");
+			else if($data == 5) $data = (string) t("Auto, Continuous");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="001a") { //Image Stabilizer
+			if($data == 2) $data = (string) t("Mode 1");
+			else if($data == 3) $data = (string) t("Off");
+			else if($data == 4) $data = (string) t("Mode 2");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="001c") { //Macro mode
+			if($data == 1) $data = (string) t("On");
+			else if($data == 2) $data = (string) t("Off");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="001f") { //Shooting Mode
+			if($data == 1) $data = (string) t("Normal");
+			else if($data == 2) $data = (string) t("Portrait");
+			else if($data == 3) $data = (string) t("Scenery");
+			else if($data == 4) $data = (string) t("Sports");
+			else if($data == 5) $data = (string) t("Night Portrait");
+			else if($data == 6) $data = (string) t("Program");
+			else if($data == 7) $data = (string) t("Aperture Priority");
+			else if($data == 8) $data = (string) t("Shutter Priority");
+			else if($data == 9) $data = (string) t("Macro");
+			else if($data == 11) $data = (string) t("Manual");
+			else if($data == 13) $data = (string) t("Panning");
+			else if($data == 14) $data = (string) t("Simple");
+			else if($data == 18) $data = (string) t("Fireworks");
+			else if($data == 19) $data = (string) t("Party");
+			else if($data == 20) $data = (string) t("Snow");
+			else if($data == 21) $data = (string) t("Night Scenery");
+			else if($data == 22) $data = (string) t("Food");
+			else if($data == 23) $data = (string) t("Baby");
+			else if($data == 27) $data = (string) t("High Sensitivity");
+			else if($data == 29) $data = (string) t("Underwater");
+			else if($data == 33) $data = (string) t("Pet");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="0020") { //Audio
+			if($data == 1) $data = (string) t("Yes");
+			else if($data == 2) $data = (string) t("No");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="0023") { //White Balance Bias
+			$data=$data." EV";
+		} 
+		if($tag=="0024") { //Flash Bias
+			$data = $data;
+		}
+		if($tag=="0028") { //Colour Effect
+			if($data == 1) $data = (string) t("Off");
+			else if($data == 2) $data = (string) t("Warm");
+			else if($data == 3) $data = (string) t("Cool");
+			else if($data == 4) $data = (string) t("Black and White");
+			else if($data == 5) $data = (string) t("Sepia");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="002a") { //Burst Mode
+			if($data == 0) $data = (string) t("Off");
+			else if($data == 1) $data = (string) t("Low/High Quality");
+			else if($data == 2) $data = (string) t("Infinite");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="002c") { //Contrast
+			if($data == 0) $data = (string) t("Standard");
+			else if($data == 1) $data = (string) t("Low");
+			else if($data == 2) $data = (string) t("High");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="002d") { //Noise Reduction
+			if($data == 0) $data = (string) t("Standard");
+			else if($data == 1) $data = (string) t("Low");
+			else if($data == 2) $data = (string) t("High");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="002e") { //Self Timer
+			if($data == 1) $data = (string) t("Off");
+			else if($data == 2) $data = (string) t("10s");
+			else if($data == 3) $data = (string) t("2s");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="0030") { //Rotation
+			if($data == 1) $data = (string) t("Horizontal (normal)");
+			else if($data == 6) $data = (string) t("Rotate 90 CW");
+			else if($data == 8) $data = (string) t("Rotate 270 CW");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="0032") { //Color Mode
+			if($data == 0) $data = (string) t("Normal");
+			else if($data == 1) $data = (string) t("Natural");
+			else $data = (string) t("Unknown")." (".$data.")";
+		}
+		if($tag=="0036") { //Travel Day
+			$data=$data;
+		} 
+	} else if($type=="UNDEFINED") {
+
+	} else {
+		$data = bin2hex($data);
+		if($intel==1) $data = intel2Moto($data);
+	}
+	
+	return $data;
+}
+
+
+
+//=================
+// Panasonic Special data section
+//====================================================================
+function parsePanasonic($block,&$result) {	
+		
+	//if($result['Endien']=="Intel") $intel=1;
+	//else $intel=0;
+	$intel=1;
+	
+	$model = $result['IFD0']['Model'];
+
+	$place=8; //current place
+	$offset=8;
+	
+	
+	$num = bin2hex(substr($block,$place,4));$place+=4;
+	if($intel==1) $num = intel2Moto($num);
+	$result['SubIFD']['MakerNote']['Offset'] = hexdec($num);
+	
+	//Get number of tags (2 bytes)
+	$num = bin2hex(substr($block,$place,2));$place+=2;
+	if($intel==1) $num = intel2Moto($num);
+	$result['SubIFD']['MakerNote']['MakerNoteNumTags'] = hexdec($num);
+	
+	//loop thru all tags  Each field is 12 bytes
+	for($i=0;$i<hexdec($num);$i++) {
+		
+		//2 byte tag
+		$tag = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $tag = intel2Moto($tag);
+		$tag_name = lookup_Panasonic_tag($tag);
+		
+		//2 byte type
+		$type = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $type = intel2Moto($type);
+		lookup_type($type,$size);
+		
+		//4 byte count of number of data units
+		$count = bin2hex(substr($block,$place,4));$place+=4;
+		if($intel==1) $count = intel2Moto($count);
+		$bytesofdata = $size*hexdec($count);
+		
+		//4 byte value of data or pointer to data
+		$value = substr($block,$place,4);$place+=4;
+
+		
+		if($bytesofdata<=4) {
+			$data = $value;
+		} else {
+			$value = bin2hex($value);
+			if($intel==1) $value = intel2Moto($value);
+			$data = substr($block,hexdec($value)-$offset,$bytesofdata*2);
+		}
+		$formated_data = formatPanasonicData($type,$tag,$intel,$data);
+		
+		if($result['VerboseOutput']==1) {
+			$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+			if($type=="URATIONAL" || $type=="SRATIONAL" || $type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+				$data = bin2hex($data);
+				if($intel==1) $data = intel2Moto($data);
+			}
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['RawData'] = $data;
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Type'] = $type;
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Bytes'] = $bytesofdata;
+		} else {
+			$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+		}
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/modules/exif/lib/makers/sanyo.php b/modules/exif/lib/makers/sanyo.php
new file mode 100644
index 0000000..3eef201
--- /dev/null
+++ b/modules/exif/lib/makers/sanyo.php
@@ -0,0 +1,158 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+//================================================================================================
+//================================================================================================
+/*
+	Exifer
+	Extracts EXIF information from digital photos.
+	
+	Copyright � 2003 Jake Olefsky
+	http://www.offsky.com/software/exif/index.php
+	jake@olefsky.com
+	
+	Please see exif.php for the complete information about this software.
+	
+	------------
+	
+	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 for more details. http://www.gnu.org/copyleft/gpl.html
+*/
+//================================================================================================
+//================================================================================================
+//================================================================================================
+
+
+
+//=================
+// Looks up the name of the tag for the MakerNote (Depends on Manufacturer)
+//====================================================================
+function lookup_Sanyo_tag($tag) {
+	
+	switch($tag) {
+		case "0200": $tag = "SpecialMode";break;
+		case "0201": $tag = "Quality";break;
+		case "0202": $tag = "Macro";break;
+		case "0203": $tag = "Unknown";break;
+		case "0204": $tag = "DigiZoom";break;
+		case "0f00": $tag = "DataDump";break;
+		default: $tag = "unknown:".$tag;break;
+	}
+	
+	return $tag;
+}
+
+//=================
+// Formats Data for the data type
+//====================================================================
+function formatSanyoData($type,$tag,$intel,$data) {
+
+	if($type=="ASCII") {
+		
+		
+	} else if($type=="URATIONAL" || $type=="SRATIONAL") {
+		$data = unRational($data,$type,$intel);	
+		
+	} else if($type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+		$data = rational($data,$type,$intel);
+		
+		if($tag=="0200") { //SpecialMode
+			if($data == 0) $data = (string) t("Normal");
+			else $data = (string) t("Unknown").": ".$data;
+		}
+		if($tag=="0201") { //Quality
+			if($data == 2) $data = (string) t("High");
+			else $data = (string) t("Unknown").": ".$data;
+		}
+		if($tag=="0202") { //Macro
+			if($data == 0) $data = (string) t("Normal");
+			else $data = (string) t("Unknown").": ".$data;
+		}
+	} else if($type=="UNDEFINED") {
+		
+	
+		
+	} else {
+		$data = bin2hex($data);
+		if($intel==1) $data = intel2Moto($data);
+	}
+	
+	return $data;
+}
+
+
+
+//=================
+// Sanyo Special data section
+//====================================================================
+function parseSanyo($block,&$result,$seek, $globalOffset) {	
+		
+	if($result['Endien']=="Intel") $intel=1;
+	else $intel=0;
+	
+	$model = $result['IFD0']['Model'];
+
+	$place=8; //current place
+	$offset=8;
+	
+		//Get number of tags (2 bytes)
+	$num = bin2hex(substr($block,$place,2));$place+=2;
+	if($intel==1) $num = intel2Moto($num);
+	$result['SubIFD']['MakerNote']['MakerNoteNumTags'] = hexdec($num);
+	
+	//loop thru all tags  Each field is 12 bytes
+	for($i=0;$i<hexdec($num);$i++) {
+		
+			//2 byte tag
+		$tag = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $tag = intel2Moto($tag);
+		$tag_name = lookup_Sanyo_tag($tag);
+		
+			//2 byte type
+		$type = bin2hex(substr($block,$place,2));$place+=2;
+		if($intel==1) $type = intel2Moto($type);
+		lookup_type($type,$size);
+		
+			//4 byte count of number of data units
+		$count = bin2hex(substr($block,$place,4));$place+=4;
+		if($intel==1) $count = intel2Moto($count);
+		$bytesofdata = $size*hexdec($count);
+		
+			//4 byte value of data or pointer to data
+		$value = substr($block,$place,4);$place+=4;
+
+		
+		if($bytesofdata<=4) {
+			$data = $value;
+		} else {
+			$value = bin2hex($value);
+			if($intel==1) $value = intel2Moto($value);
+			$v = fseek($seek,$globalOffset+hexdec($value));  //offsets are from TIFF header which is 12 bytes from the start of the file
+			if($v==0) {
+				$data = fread($seek, $bytesofdata);
+			} else if($v==-1) {
+				$result['Errors'] = $result['Errors']++;
+			}
+		}
+		$formated_data = formatSanyoData($type,$tag,$intel,$data);
+		
+		if($result['VerboseOutput']==1) {
+			$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+			if($type=="URATIONAL" || $type=="SRATIONAL" || $type=="USHORT" || $type=="SSHORT" || $type=="ULONG" || $type=="SLONG" || $type=="FLOAT" || $type=="DOUBLE") {
+				$data = bin2hex($data);
+				if($intel==1) $data = intel2Moto($data);
+			}
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['RawData'] = $data;
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Type'] = $type;
+			$result['SubIFD']['MakerNote'][$tag_name."_Verbose"]['Bytes'] = $bytesofdata;
+		} else {
+			$result['SubIFD']['MakerNote'][$tag_name] = $formated_data;
+		}
+	}
+}
+
+
+?>
\ No newline at end of file
diff --git a/modules/exif/models/exif_key.php b/modules/exif/models/exif_key.php
new file mode 100644
index 0000000..5c45669
--- /dev/null
+++ b/modules/exif/models/exif_key.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Exif_Key_Model_Core extends ORM {
+}
diff --git a/modules/exif/models/exif_record.php b/modules/exif/models/exif_record.php
new file mode 100644
index 0000000..1628ae4
--- /dev/null
+++ b/modules/exif/models/exif_record.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Exif_Record_Model_Core extends ORM {
+}
diff --git a/modules/exif/module.info b/modules/exif/module.info
new file mode 100644
index 0000000..9bbda95
--- /dev/null
+++ b/modules/exif/module.info
@@ -0,0 +1,7 @@
+name = "Exif Data"
+description = "Extract Exif data and display it on photo pages."
+version = 1
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:exif"
+discuss_url = "http://galleryproject.org/forum_module_exif"
diff --git a/modules/exif/views/exif_dialog.html.php b/modules/exif/views/exif_dialog.html.php
new file mode 100644
index 0000000..22744e2
--- /dev/null
+++ b/modules/exif/views/exif_dialog.html.php
@@ -0,0 +1,33 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<style type="text/css">
+  #g-exif-data { font-size: .85em; }
+  .g-odd { background: #bdd2ff; }
+  .g-even { background: #dfeffc; }
+</style>
+<h1 style="display: none;"><?= t("Photo detail") ?></h1>
+<div id="g-exif-data">
+  <table class="g-metadata" >
+    <tbody>
+      <? for ($i = 0; $i < count($details); $i++): ?>
+      <tr>
+         <td class="g-even">
+         <?= $details[$i]["caption"] ?>
+         </td>
+         <td class="g-odd">
+         <?= html::clean($details[$i]["value"]) ?>
+         </td>
+         <? if (!empty($details[++$i])): ?>
+           <td class="g-even">
+           <?= $details[$i]["caption"] ?>
+           </td>
+           <td class="g-odd">
+           <?= html::clean($details[$i]["value"]) ?>
+           </td>
+         <? else: ?>
+           <td class="g-even"></td><td class="g-odd"></td>
+         <? endif ?>
+       </tr>
+       <? endfor ?>
+    </tbody>
+  </table>
+</div>
diff --git a/modules/exif/views/exif_sidebar.html.php b/modules/exif/views/exif_sidebar.html.php
new file mode 100644
index 0000000..8af2eb1
--- /dev/null
+++ b/modules/exif/views/exif_sidebar.html.php
@@ -0,0 +1,6 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<a id="g-exif-data-link" href="<?= url::site("exif/show/{$item->id}") ?>" title="<?= t("Photo details")->for_html_attr() ?>"
+  class="g-dialog-link g-button ui-icon-left ui-state-default ui-corner-all">
+  <span class="ui-icon ui-icon-info"></span>
+  <?= t("View more information") ?>
+</a>
diff --git a/modules/familygallery/controllers/login.php.backup b/modules/familygallery/controllers/login.php.backup
new file mode 100644
index 0000000..4c5d558
--- /dev/null
+++ b/modules/familygallery/controllers/login.php.backup
@@ -0,0 +1,10 @@
+<?php
+class zurLogin_Controller extends Login_Controller {
+  public function html() {
+    $view = new Theme_View("page.html", "other", "login");
+    $view->page_title = t("Familien Fotogalerie");
+    $view->content = new View("login_ajax.html");
+    $view->content->form = auth::get_login_form("login/auth_html");
+    print $view;
+  }
+}
diff --git a/modules/familygallery/helpers/familygallery_event.php b/modules/familygallery/helpers/familygallery_event.php
new file mode 100644
index 0000000..6192455
--- /dev/null
+++ b/modules/familygallery/helpers/familygallery_event.php
@@ -0,0 +1,20 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+
+class familygallery_event {
+  /**
+  * remove the default login link and use our own
+  */
+  static function user_menu($menu, $theme) {
+    $user = identity::active_user();
+    if ($user->guest) {
+      // disable the default login
+//      $menu->remove('user_menu_login');
+      // add ours
+/*      $menu->append(Menu::factory("dialog")
+                    ->id("user_menu_fam")
+                    ->css_id("g-fam-menu")
+                    ->url(url::site("familygallery/html"))
+                    ->label(t("Login")));*/
+    }
+  }
+}
diff --git a/modules/familygallery/module.info b/modules/familygallery/module.info
new file mode 100644
index 0000000..0f4906d
--- /dev/null
+++ b/modules/familygallery/module.info
@@ -0,0 +1,7 @@
+name = "Family Gallery Module"
+description = "This module contains all our customizations"
+version = 1
+author_name = ""
+author_url = ""
+info_url = ""
+discuss_url = ""
diff --git a/modules/forge/libraries/Forge.php b/modules/forge/libraries/Forge.php
new file mode 100644
index 0000000..9179aae
--- /dev/null
+++ b/modules/forge/libraries/Forge.php
@@ -0,0 +1,323 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE (FORm GEneration) library.
+ *
+ * $Id: Forge.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Forge_Core {
+
+	// Template variables
+	protected $template = array
+	(
+		'title' => '',
+		'class' => '',
+		'open'  => '',
+		'close' => '',
+	);
+
+	// Form attributes
+	protected $attr = array();
+
+	// Form inputs and hidden inputs
+	public $inputs = array();
+	public $hidden = array();
+
+	// Error message format, only used with custom templates
+	public $error_format = '<p class="error">{message}</p>';
+	public $newline_char = "\n";
+
+	/**
+	 * Form constructor. Sets the form action, title, method, and attributes.
+	 *
+	 * @return  void
+	 */
+	public function __construct($action = NULL, $title = '', $method = NULL, $attr = array())
+	{
+		// Set form attributes
+		$this->attr['action'] = $action;
+		$this->attr['method'] = empty($method) ? 'post' : $method;
+
+		// Set template variables
+		$this->template['title'] = $title;
+
+		// Empty attributes sets the class to "form"
+		empty($attr) and $attr = array('class' => 'form');
+
+		// String attributes is the class name
+		is_string($attr) and $attr = array('class' => $attr);
+
+		// Extend the template with the attributes
+		$this->attr += $attr;
+	}
+
+	/**
+	 * Magic __get method. Returns the specified form element.
+	 *
+	 * @param   string   unique input name
+	 * @return  object
+	 */
+	public function __get($key)
+	{
+		if (isset($this->inputs[$key]))
+		{
+			return $this->inputs[$key];
+		}
+		elseif (isset($this->hidden[$key]))
+		{
+			return $this->hidden[$key];
+		}
+	}
+
+	/**
+	 * Magic __call method. Creates a new form element object.
+	 *
+	 * @throws  Kohana_Exception
+	 * @param   string   input type
+	 * @param   string   input name
+	 * @return  object
+	 */
+	public function __call($method, $args)
+	{
+		// Class name
+		$input = 'Form_'.ucfirst($method);
+
+		// Create the input
+		switch (count($args))
+		{
+			case 1:
+				$input = new $input($args[0]);
+			break;
+			case 2:
+				$input = new $input($args[0], $args[1]);
+			break;
+			default:
+				throw new Kohana_Exception('forge.invalid_input', $input);
+		}
+
+		if ( ! ($input instanceof Form_Input) AND ! ($input instanceof Forge))
+			throw new Kohana_Exception('forge.unknown_input', get_class($input));
+
+		$input->method = $this->attr['method'];
+
+		if ($name = $input->name)
+		{
+			// Assign by name
+			if ($method == 'hidden')
+			{
+				$this->hidden[$name] = $input;
+			}
+			else
+			{
+				$this->inputs[$name] = $input;
+			}
+		}
+		else
+		{
+			// No name, these are unretrievable
+			$this->inputs[] = $input;
+		}
+
+		return $input;
+	}
+
+	/**
+	 * Set a form attribute. This method is chainable.
+	 *
+	 * @param   string|array  attribute name, or an array of attributes
+	 * @param   string        attribute value
+	 * @return  object
+	 */
+	public function set_attr($key, $val = NULL)
+	{
+		if (is_array($key))
+		{
+			// Merge the new attributes with the old ones
+			$this->attr = array_merge($this->attr, $key);
+		}
+		else
+		{
+			// Set the new attribute
+			$this->attr[$key] = $val;
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Validates the form by running each inputs validation rules.
+	 *
+	 * @return  bool
+	 */
+	public function validate()
+	{
+		$status = TRUE;
+
+		$inputs = array_merge($this->hidden, $this->inputs);
+
+		foreach ($inputs as $input)
+		{
+			if ($input->validate() == FALSE)
+			{
+				$status = FALSE;
+			}
+		}
+
+		return $status;
+	}
+
+	/**
+	 * Returns the form as an array of input names and values.
+	 *
+	 * @return  array
+	 */
+	public function as_array()
+	{
+		$data = array();
+		foreach (array_merge($this->hidden, $this->inputs) as $input)
+		{
+			if (is_object($input->name)) // It's a Forge_Group object (hopefully)
+			{
+				foreach ($input->inputs as $group_input)
+				{
+					if ($name = $group_input->name)
+					{
+						$data[$name] = $group_input->value;
+					}
+				}
+			}
+			else if (is_array($input->inputs))
+			{
+				foreach ($input->inputs as $group_input)
+				{
+					if ($name = $group_input->name)
+					{
+						$data[$name] = $group_input->value;
+					}
+				}
+			}
+			else if ($name = $input->name) // It's a normal input
+			{
+				// Return only named inputs
+				$data[$name] = $input->value;
+			}
+		}
+		return $data;
+	}
+
+	/**
+	 * Changes the error message format. Your message formatting must
+	 * contain a {message} placeholder.
+	 *
+	 * @throws  Kohana_Exception
+	 * @param   string   new message format
+	 * @return  void
+	 */
+	public function error_format($string = '')
+	{
+		if (strpos((string) $string, '{message}') === FALSE)
+			throw new Kohana_Exception('validation.error_format');
+
+		$this->error_format = $string;
+	}
+
+	/**
+	 * Creates the form HTML
+	 *
+	 * @param   string   form view template name
+	 * @param   boolean  use a custom view
+	 * @return  string
+	 */
+	public function render($template = 'forge_template', $custom = FALSE)
+	{
+		// Load template
+		$form = new View($template);
+
+		if ($custom)
+		{
+			// Using a custom view
+
+			$data = array();
+			foreach (array_merge($this->hidden, $this->inputs) as $input)
+			{
+				$data[$input->name] = $input;
+
+				// Groups will never have errors, so skip them
+				if ($input instanceof Form_Group)
+					continue;
+
+				// Compile the error messages for this input
+				$messages = '';
+				$errors = $input->error_messages();
+				if (is_array($errors) AND ! empty($errors))
+				{
+					foreach ($errors as $error)
+					{
+						// Replace the message with the error in the html error string
+						$messages .= str_replace('{message}', $error, $this->error_format).$this->newline_char;
+					}
+				}
+
+				$data[$input->name.'_errors'] = $messages;
+			}
+
+			$form->set($data);
+		}
+		else
+		{
+			// Using a template view
+
+			$form->set($this->template);
+			$hidden = array();
+			if ( ! empty($this->hidden))
+			{
+				foreach ($this->hidden as $input)
+				{
+					$hidden['name'] = $input->name;
+					$hidden['value'] = $input->value;
+				}
+			}
+
+			$form_type = 'open';
+			// See if we need a multipart form
+			$check_inputs = array($this->inputs);
+			while ($check_inputs) {
+				foreach (array_shift($check_inputs) as $input) {
+					if ($input instanceof Form_Upload)
+					{
+						$form_type = 'open_multipart';
+					}
+					if ($input instanceof Form_Group)
+					{
+						$check_inputs += array($input->inputs);
+					}
+				}
+			}
+
+			// Set the form open and close
+			$form->open  = form::$form_type(arr::remove('action', $this->attr), $this->attr);
+                        foreach ($this->hidden as $hidden) {
+                                $form->open .= form::hidden($hidden->name, $hidden->value);
+                        }
+			$form->close = "</form>";
+
+			// Set the inputs
+			$form->inputs = $this->inputs;
+		}
+
+		return $form;
+	}
+
+	/**
+	 * Returns the form HTML
+	 */
+	public function __toString()
+	{
+		return (string) $this->render();
+	}
+
+} // End Forge
diff --git a/modules/forge/libraries/Form_Checkbox.php b/modules/forge/libraries/Form_Checkbox.php
new file mode 100644
index 0000000..aded4fd
--- /dev/null
+++ b/modules/forge/libraries/Form_Checkbox.php
@@ -0,0 +1,83 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE checkbox input library.
+ *
+ * $Id: Form_Checkbox.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Checkbox_Core extends Form_Input {
+
+	protected $data = array
+	(
+		'type' => 'checkbox',
+		'class' => 'checkbox',
+		'value' => '1',
+		'checked' => FALSE,
+	);
+
+	protected $protect = array('type');
+
+	public function __get($key)
+	{
+		if ($key == 'value')
+		{
+			// Return the value if the checkbox is checked
+			return $this->data['checked'] ? $this->data['value'] : NULL;
+		}
+
+		return parent::__get($key);
+	}
+
+	public function label($val = NULL)
+	{
+		if ($val === NULL)
+		{
+			// Do not display labels for checkboxes, labels wrap checkboxes
+			return '';
+		}
+		else
+		{
+			$this->data['label'] = ($val === TRUE) ? utf8::ucwords(inflector::humanize($this->name)) : $val;
+			return $this;
+		}
+	}
+
+	protected function html_element()
+	{
+		// Import the data
+		$data = $this->data;
+
+		if (empty($data['checked']))
+		{
+			// Not checked
+			unset($data['checked']);
+		}
+		else
+		{
+			// Is checked
+			$data['checked'] = 'checked';
+		}
+
+		if ($label = arr::remove('label', $data))
+		{
+			// There must be one space before the text
+			$label = ' '.ltrim($label);
+		}
+
+		return '<label>'.form::input($data).html::clean($label).'</label>';
+	}
+
+	protected function load_value()
+	{
+		if (is_bool($this->valid))
+			return;
+
+		// Makes the box checked if the value from POST is the same as the current value
+		$this->data['checked'] = ($this->input_value($this->name) == $this->data['value']);
+	}
+
+} // End Form Checkbox
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Checklist.php b/modules/forge/libraries/Form_Checklist.php
new file mode 100644
index 0000000..4536d39
--- /dev/null
+++ b/modules/forge/libraries/Form_Checklist.php
@@ -0,0 +1,92 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE checklist input library.
+ *
+ * $Id: Form_Checklist.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Checklist_Core extends Form_Input {
+
+	protected $data = array
+	(
+		'name'    => '',
+		'type'    => 'checkbox',
+		'class'   => 'checklist',
+		'options' => array(),
+	);
+
+	protected $protect = array('name', 'type');
+
+	public function __construct($name)
+	{
+		$this->data['name'] = $name;
+	}
+
+	public function __get($key)
+	{
+		if ($key == 'value')
+		{
+			// Return the currently checked values
+			$array = array();
+			foreach ($this->data['options'] as $id => $opt)
+			{
+				// Return the options that are checked
+				($opt[1] === TRUE) and $array[] = $id;
+			}
+			return $array;
+		}
+
+		return parent::__get($key);
+	}
+
+	public function render()
+	{
+		// Import base data
+		$base_data = $this->data;
+
+		// Make it an array
+		$base_data['name'] .= '[]';
+
+		// Newline
+		$nl = "\n";
+
+		$checklist = '<ul class="'.arr::remove('class', $base_data).'">'.$nl;
+		foreach (arr::remove('options', $base_data) as $val => $opt)
+		{
+			// New set of input data
+			$data = $base_data;
+
+			// Get the title and checked status
+			list ($title, $checked) = $opt;
+
+			// Set the name, value, and checked status
+			$data['value']   = $val;
+			$data['checked'] = $checked;
+
+			$checklist .= '<li><label>'.form::checkbox($data).' '.html::purify($title).'</label></li>'.$nl;
+		}
+		$checklist .= '</ul>';
+
+		return $checklist;
+	}
+
+	protected function load_value()
+	{
+		foreach ($this->data['options'] as $val => $checked)
+		{
+			if ($input = $this->input_value($this->data['name']))
+			{
+				$this->data['options'][$val][1] = in_array($val, $input);
+			}
+			else
+			{
+				$this->data['options'][$val][1] = FALSE;
+			}
+		}
+	}
+
+} // End Form Checklist
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Dateselect.php b/modules/forge/libraries/Form_Dateselect.php
new file mode 100644
index 0000000..a6e752e
--- /dev/null
+++ b/modules/forge/libraries/Form_Dateselect.php
@@ -0,0 +1,138 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE dateselect input library.
+ *
+ * $Id: Form_Dateselect.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Dateselect_Core extends Form_Input {
+
+	protected $data = array
+	(
+		'name'  => '',
+		'class' => 'dropdown',
+	);
+
+	protected $protect = array('type');
+
+	// Precision for the parts, you can use @ to insert a literal @ symbol
+	protected $parts = array
+	(
+		'month'   => array(),
+		'day'     => array(1),
+		'year'    => array(),
+		' @ ',
+		'hour'    => array(),
+		':',
+		'minute'  => array(5),
+		'am_pm'   => array(),
+	);
+
+	public function __construct($name)
+	{
+		// Set name
+		$this->data['name'] = $name;
+
+		// Default to the current time
+		$this->data['value'] = time();
+	}
+
+	public function __call($method, $args)
+	{
+		if (isset($this->parts[substr($method, 0, -1)]))
+		{
+			// Set options for date generation
+			$this->parts[substr($method, 0, -1)] = $args;
+			return $this;
+		}
+
+		return parent::__call($method, $args);
+	}
+
+	public function html_element()
+	{
+		// Import base data
+		$data = $this->data;
+
+		// Get the options and default selection
+		$time = $this->time_array(arr::remove('value', $data));
+
+		// No labels or values
+		unset($data['label']);
+
+		$input = '';
+		foreach ($this->parts as $type => $val)
+		{
+			if (is_int($type))
+			{
+				// Just add the separators
+				$input .= $val;
+				continue;
+			}
+
+			// Set this input name
+			$data['name'] = $this->data['name'].'['.$type.']';
+
+			// Set the selected option
+			$selected = $time[$type];
+
+			if ($type == 'am_pm')
+			{
+				// Options are static
+				$options = array('AM' => 'AM', 'PM' => 'PM');
+			}
+			else
+			{
+				// minute(s), hour(s), etc
+				$type .= 's';
+
+				// Use the date helper to generate the options
+				$options = empty($val) ? date::$type() : call_user_func_array(array('date', $type), $val);
+			}
+
+			$input .= form::dropdown($data, $options, $selected);
+		}
+
+		return $input;
+	}
+
+	protected function time_array($timestamp)
+	{
+		$time = array_combine
+		(
+			array('month', 'day', 'year', 'hour', 'minute', 'am_pm'), 
+			explode('--', date('n--j--Y--g--i--A', $timestamp))
+		);
+
+		// Minutes should always be in 5 minute increments
+		$time['minute'] = num::round($time['minute'], current($this->parts['minute']));
+
+		return $time;
+	}
+
+	protected function load_value()
+	{
+		if (is_bool($this->valid))
+			return;
+
+		$time = $this->input_value($this->name);
+
+		// Make sure all the required inputs keys are set
+		$time += $this->time_array(time());
+
+		$this->data['value'] = mktime
+		(
+			date::adjust($time['hour'], $time['am_pm']),
+			$time['minute'],
+			0,
+			$time['month'],
+			$time['day'],
+			$time['year']
+		);
+	}
+
+} // End Form Dateselect
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Dropdown.php b/modules/forge/libraries/Form_Dropdown.php
new file mode 100644
index 0000000..9aa87a6
--- /dev/null
+++ b/modules/forge/libraries/Form_Dropdown.php
@@ -0,0 +1,78 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE dropdown input library.
+ *
+ * $Id: Form_Dropdown.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Dropdown_Core extends Form_Input {
+
+	protected $data = array
+	(
+		'name'  => '',
+		'class' => 'dropdown',
+	);
+
+	protected $protect = array('type');
+
+	public function __get($key)
+	{
+		if ($key == 'value')
+		{
+			return $this->selected;
+		}
+
+		return parent::__get($key);
+	}
+
+	public function html_element()
+	{
+		// Import base data
+		$base_data = $this->data;
+
+		unset($base_data['label']);
+
+		// Get the options and default selection
+		$options = arr::remove('options', $base_data);
+		$selected = arr::remove('selected', $base_data);
+
+		return form::dropdown($base_data, $options, $selected);
+	}
+
+	protected function load_value()
+	{
+		if (is_bool($this->valid))
+			return;
+
+		$this->data['selected'] = $this->input_value($this->name);
+	}
+
+	public function validate()
+	{
+		// Validation has already run
+		if (is_bool($this->is_valid))
+			return $this->is_valid;
+
+		if ($this->input_value() == FALSE)
+		{
+			// No data to validate
+			return $this->is_valid = FALSE;
+		}
+
+		// Load the submitted value
+		$this->load_value();
+
+		if ( ! array_key_exists($this->value, $this->data['options']))
+		{
+			// Value does not exist in the options
+			return $this->is_valid = FALSE;
+		}
+
+		return parent::validate();
+	}
+
+} // End Form Dropdown
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Group.php b/modules/forge/libraries/Form_Group.php
new file mode 100644
index 0000000..0a04912
--- /dev/null
+++ b/modules/forge/libraries/Form_Group.php
@@ -0,0 +1,89 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE group library.
+ *
+ * $Id: Form_Group.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Group_Core extends Forge {
+
+	protected $data = array
+	(
+		'type'  => 'group',
+		'name'  => '',
+		'class' => 'group',
+		'label' => '',
+		'message' => ''
+	);
+
+	// Input method
+	public $method;
+
+	public function __construct($name = NULL, $class = 'group')
+	{
+		$this->data['name'] = $name;
+		$this->data['class'] = $class;
+
+		// Set dummy data so we don't get errors
+		$this->attr['action'] = '';
+		$this->attr['method'] = 'post';
+	}
+
+	public function __get($key)
+	{
+		if ($key == 'type' || $key == 'name' || $key == 'label')
+		{
+			return $this->data[$key];
+		}
+		return parent::__get($key);
+	}
+
+	public function __set($key, $val)
+	{
+		if ($key == 'method')
+		{
+			$this->attr['method'] = $val;
+		}
+		$this->$key = $val;
+	}
+
+	public function label($val = NULL)
+	{
+		if ($val === NULL)
+		{
+			if ($label = $this->data['label'])
+			{
+				return html::purify($this->data['label']);
+			}
+		}
+		else
+		{
+			$this->data['label'] = ($val === TRUE) ? ucwords(inflector::humanize($this->data['name'])) : $val;
+			return $this;
+		}
+	}
+
+	public function message($val = NULL)
+	{
+		if ($val === NULL)
+		{
+			return $this->data['message'];
+		}
+		else
+		{
+			$this->data['message'] = $val;
+			return $this;
+		}
+	}
+
+	public function render($template = 'forge_template', $custom = FALSE)
+	{
+		// No Sir, we don't want any html today thank you
+		return;
+	}
+
+} // End Form Group
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Hidden.php b/modules/forge/libraries/Form_Hidden.php
new file mode 100644
index 0000000..423f626
--- /dev/null
+++ b/modules/forge/libraries/Form_Hidden.php
@@ -0,0 +1,25 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE hidden input library.
+ *
+ * $Id: Form_Hidden.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Hidden_Core extends Form_Input {
+
+	protected $data = array
+	(
+		'name'  => '',
+		'value' => '',
+	);
+
+	public function render()
+	{
+		return form::hidden($this->data['name'], $this->data['value']);
+	}
+
+} // End Form Hidden
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Input.php b/modules/forge/libraries/Form_Input.php
new file mode 100644
index 0000000..0c57801
--- /dev/null
+++ b/modules/forge/libraries/Form_Input.php
@@ -0,0 +1,555 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE base input library.
+ *
+ * $Id: Form_Input.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Input_Core {
+
+	// Input method
+	public $method;
+
+	// Element data
+	protected $data = array
+	(
+		'type'    => 'text',
+		'class'   => 'textbox',
+		'value'   => ''
+	);
+
+	// Protected data keys
+	protected $protect = array();
+
+	// Validation rules, matches, and callbacks
+	protected $rules = array();
+	protected $matches = array();
+	protected $callbacks = array();
+
+	// Validation check
+	protected $is_valid;
+
+	// Errors
+	protected $errors = array();
+	protected $error_messages = array();
+
+	/**
+	 * Sets the input element name.
+	 */
+	public function __construct($name)
+	{
+		$this->data['name'] = $name;
+	}
+
+	/**
+	 * Sets form attributes, or return rules.
+	 */
+	public function __call($method, $args)
+	{
+		if ($method == 'rules')
+		{
+			if (empty($args))
+				return $this->rules;
+
+			// Set rules and action
+			$rules  = $args[0];
+			$action = substr($rules, 0, 1);
+
+			if (in_array($action, array('-', '+', '=')))
+			{
+				// Remove the action from the rules
+				$rules = substr($rules, 1);
+			}
+			else
+			{
+				// Default action is append
+				$action = '';
+			}
+
+			$this->add_rules(explode('|', $rules), $action);
+		}
+		elseif ($method == 'name')
+		{
+			// Do nothing. The name should stay static once it is set.
+		}
+		else
+		{
+			$this->data[$method] = $args[0];
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Returns form attributes.
+	 *
+	 * @param   string  attribute name
+	 * @return  string
+	 */
+	public function __get($key)
+	{
+		if (isset($this->data[$key]))
+		{
+			return $this->data[$key];
+		}
+	}
+
+	/**
+	 * Sets a form element that this element must match the value of.
+	 *
+	 * @chainable
+	 * @param   object  another Forge input
+	 * @return  object
+	 */
+	public function matches($input)
+	{
+		if ( ! in_array($input, $this->matches, TRUE))
+		{
+			$this->matches[] = $input;
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Sets a callback method as a rule for this input.
+	 *
+	 * @chainable
+	 * @param   callback
+	 * @return  object
+	 */
+	public function callback($callback)
+	{
+		if ( ! in_array($callback, $this->callbacks, TRUE))
+		{
+			$this->callbacks[] = $callback;
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Sets or returns the input label.
+	 *
+	 * @chainable
+	 * @param   string   label to set
+	 * @return  string|object
+	 */
+	public function label($val = NULL)
+	{
+		if ($val === NULL)
+		{
+			if (isset($this->data['name']) AND isset($this->data['label']))
+			{
+				return form::label($this->data['name'], $this->data['label']);
+			}
+			return FALSE;
+		}
+		else
+		{
+			$this->data['label'] = ($val === TRUE) ? utf8::ucwords(inflector::humanize($this->name)) : $val;
+			return $this;
+		}
+	}
+
+	/**
+	 * Set or return the error message.
+	 *
+	 * @chainable
+	 * @param   string  error message
+	 * @return  strong|object
+	 */
+	public function message($val = NULL)
+	{
+		if ($val === NULL)
+		{
+			if (isset($this->data['message']))
+				return $this->data['message'];
+		}
+		else
+		{
+			$this->data['message'] = $val;
+			return $this;
+		}
+	}
+
+	/**
+	 * Runs validation and returns the element HTML.
+	 *
+	 * @return  string
+	 */
+	public function render()
+	{
+		// Make sure validation runs
+		$this->validate();
+
+		return $this->html_element();
+	}
+
+	/**
+	 * Returns the form input HTML.
+	 *
+	 * @return  string
+	 */
+	protected function html_element()
+	{
+		$data = $this->data;
+
+		unset($data['label']);
+		unset($data['message']);
+
+		return form::input($data);
+	}
+
+	/**
+	 * Replace, remove, or append rules.
+	 *
+	 * @param   array   rules to change
+	 * @param   string  action to use: replace, remove, append
+	 */
+	protected function add_rules( array $rules, $action)
+	{
+		if ($action === '=')
+		{
+			// Just replace the rules
+			$this->rules = $rules;
+			return;
+		}
+
+		foreach ($rules as $rule)
+		{
+			if ($action === '-')
+			{
+				if (($key = array_search($rule, $this->rules)) !== FALSE)
+				{
+					// Remove the rule
+					unset($this->rules[$key]);
+				}
+			}
+			else
+			{
+				if ( ! in_array($rule, $this->rules))
+				{
+					if ($action == '+')
+					{
+						array_unshift($this->rules, $rule);
+					}
+					else
+					{
+						$this->rules[] = $rule;
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Add an error to the input.
+	 *
+	 * @chainable
+	 * @return object
+	 */
+	public function add_error($key, $val)
+	{
+		if ( ! isset($this->errors[$key]))
+		{
+			$this->errors[$key] = $val;
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Set or return the error messages.
+	 *
+	 * @chainable
+	 * @param   string|array  failed validation function, or an array of messages
+	 * @param   string        error message
+	 * @return  object|array
+	 */
+	public function error_messages($func = NULL, $message = NULL)
+	{
+		// Set custom error messages
+		if ( ! empty($func))
+		{
+			if (is_array($func))
+			{
+				// Replace all
+				$this->error_messages = $func;
+			}
+			else
+			{
+				if (empty($message))
+				{
+					// Single error, replaces all others
+					$this->error_messages = $func;
+				}
+				else
+				{
+					// Add custom error
+					$this->error_messages[$func] = $message;
+				}
+			}
+			return $this;
+		}
+
+		// Make sure validation runs
+		is_null($this->is_valid) and $this->validate();
+
+		// Return single error
+		if ( ! is_array($this->error_messages) AND ! empty($this->errors))
+			return array($this->error_messages);
+
+		$messages = array();
+		foreach ($this->errors as $func => $args)
+		{
+			if (is_string($args))
+			{
+				$error = $args;
+			}
+			else
+			{
+				// Force args to be an array
+				$args = is_array($args) ? $args : array();
+
+				// Add the label or name to the beginning of the args
+				array_unshift($args, $this->label ? mb_strtolower($this->label) : $this->name);
+
+				if (isset($this->error_messages[$func]))
+				{
+					// Use custom error message
+					$error = vsprintf($this->error_messages[$func], $args);
+				}
+				else
+				{
+					// Get the proper i18n entry, very hacky but it works
+					switch ($func)
+					{
+						case 'valid_url':
+						case 'valid_email':
+						case 'valid_ip':
+							// Fetch an i18n error message
+                                                        $error = 'validation.'.$func;
+							break;
+						case substr($func, 0, 6) === 'valid_':
+							// Strip 'valid_' from func name
+							$func = (substr($func, 0, 6) === 'valid_') ? substr($func, 6) : $func;
+						case 'alpha':
+						case 'alpha_dash':
+						case 'digit':
+						case 'numeric':
+							// i18n strings have to be inserted into valid_type
+							$args[] = 'validation.'.$func;
+							$error = 'validation.valid_type';
+							break;
+						default:
+							$error = 'validation.'.$func;
+					}
+				}
+			}
+
+			// Add error to list
+			$messages[] = $error;
+		}
+
+		return $messages;
+	}
+
+	/**
+	 * Get the global input value.
+	 *
+	 * @return  string|bool
+	 */
+	protected function input_value($name = array())
+	{
+		// Get the Input instance
+		$input = Input::instance();
+
+		// Fetch the method for this object
+		$method = $this->method;
+
+		return $input->$method($name, NULL);
+	}
+
+	/**
+	 * Load the value of the input, if form data is present.
+	 *
+	 * @return  void
+	 */
+	protected function load_value()
+	{
+		if (is_bool($this->is_valid))
+			return;
+
+		if ($name = $this->name)
+		{
+			// Load POSTed value, but only for named inputs
+			$this->data['value'] = $this->input_value($name);
+		}
+
+		if (is_string($this->data['value']))
+		{
+			// Trim string values
+			$this->data['value'] = trim($this->data['value']);
+		}
+	}
+
+	/**
+	 * Validate this input based on the set rules.
+	 *
+	 * @return  bool
+	 */
+	public function validate()
+	{
+		// Validation has already run
+		if (is_bool($this->is_valid))
+			return $this->is_valid;
+
+		// No data to validate
+		if ($this->input_value() == FALSE)
+			return $this->is_valid = FALSE;
+
+		// Load the submitted value
+		$this->load_value();
+
+		// No rules to validate
+		if (count($this->rules) == 0 AND count($this->matches) == 0 AND count($this->callbacks) == 0)
+			return $this->is_valid = TRUE;
+
+		if ( ! empty($this->rules))
+		{
+			foreach ($this->rules as $rule)
+			{
+				if (($offset = strpos($rule, '[')) !== FALSE)
+				{
+					// Get the args
+					$args = preg_split('/, ?/', trim(substr($rule, $offset), '[]'));
+
+					// Remove the args from the rule
+					$rule = substr($rule, 0, $offset);
+				}
+
+				if (substr($rule, 0, 6) === 'valid_' AND method_exists('valid', substr($rule, 6)))
+				{
+					$func = substr($rule, 6);
+
+					if ($this->value AND ! valid::$func($this->value))
+					{
+						$this->errors[$rule] = TRUE;
+					}
+				}
+				elseif (method_exists($this, 'rule_'.$rule))
+				{
+					// The rule function is always prefixed with rule_
+					$rule = 'rule_'.$rule;
+
+					if (isset($args))
+					{
+						// Manually call up to 2 args for speed
+						switch (count($args))
+						{
+							case 1:
+								$this->$rule($args[0]);
+							break;
+							case 2:
+								$this->$rule($args[0], $args[1]);
+							break;
+							default:
+								call_user_func_array(array($this, $rule), $args);
+							break;
+						}
+					}
+					else
+					{
+						// Just call the rule
+						$this->$rule();
+					}
+
+					// Prevent args from being re-used
+					unset($args);
+				}
+				else
+				{
+					throw new Kohana_Exception('validation.invalid_rule', $rule);
+				}
+
+				// Stop when an error occurs
+				if ( ! empty($this->errors))
+					break;
+			}
+		}
+
+		if ( ! empty($this->matches))
+		{
+			foreach ($this->matches as $input)
+			{
+				if ($this->value != $input->value)
+				{
+					// Field does not match
+					$this->errors['matches'] = array($input->label ? mb_strtolower($input->label) : $input->name);
+					break;
+				}
+			}
+		}
+
+		if ( ! empty($this->callbacks))
+		{
+			foreach ($this->callbacks as $callback)
+			{
+				call_user_func($callback, $this);
+
+				// Stop when an error occurs
+				if ( ! empty($this->errors))
+					break;
+			}
+		}
+
+		// If there are errors, validation failed
+		return $this->is_valid = empty($this->errors);
+	}
+
+	/**
+	 * Validate required.
+	 */
+	protected function rule_required()
+	{
+		if ($this->value === '' OR $this->value === NULL)
+		{
+			$this->errors['required'] = TRUE;
+		}
+	}
+
+	/**
+	 * Validate length.
+	 */
+	protected function rule_length($min, $max = NULL)
+	{
+		// Get the length, return if zero
+		if (($length = mb_strlen($this->value)) === 0)
+			return;
+
+		if ($max == NULL)
+		{
+			if ($length != $min)
+			{
+				$this->errors['exact_length'] = array($min);
+			}
+		}
+		else
+		{
+			if ($length < $min)
+			{
+				$this->errors['min_length'] = array($min);
+			}
+			elseif ($length > $max)
+			{
+				$this->errors['max_length'] = array($max);
+			}
+		}
+	}
+
+} // End Form Input
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Password.php b/modules/forge/libraries/Form_Password.php
new file mode 100644
index 0000000..2622ae5
--- /dev/null
+++ b/modules/forge/libraries/Form_Password.php
@@ -0,0 +1,23 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE password input library.
+ *
+ * $Id: Form_Password.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Password_Core extends Form_Input {
+
+	protected $data = array
+	(
+		'type'  => 'password',
+		'class' => 'password',
+		'value' => '',
+	);
+
+	protected $protect = array('type');
+
+} // End Form Password
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Phonenumber.php b/modules/forge/libraries/Form_Phonenumber.php
new file mode 100644
index 0000000..2befef5
--- /dev/null
+++ b/modules/forge/libraries/Form_Phonenumber.php
@@ -0,0 +1,98 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE phone number input library.
+ *
+ * $Id: Form_Phonenumber.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Phonenumber_Core extends Form_Input {
+
+	protected $data = array
+	(
+		'name'  => '',
+		'class' => 'phone_number',
+	);
+
+	protected $protect = array('type');
+
+	// Precision for the parts, you can use @ to insert a literal @ symbol
+	protected $parts = array
+	(
+		'area_code'   => '',
+		'exchange'     => '',
+		'last_four'    => '',
+	);
+
+	public function __construct($name)
+	{
+		// Set name
+		$this->data['name'] = $name;
+	}
+
+	public function __call($method, $args)
+	{
+		if (isset($this->parts[substr($method, 0, -1)]))
+		{
+			// Set options for date generation
+			$this->parts[substr($method, 0, -1)] = $args;
+			return $this;
+		}
+
+		return parent::__call($method, $args);
+	}
+
+	public function html_element()
+	{
+		// Import base data
+		$data = $this->data;
+
+		$input = '';
+		foreach ($this->parts as $type => $val)
+		{
+			isset($data['value']) OR $data['value'] = '';
+			$temp = $data;
+			$temp['name'] = $this->data['name'].'['.$type.']';
+			$offset = (strlen($data['value']) == 10) ? 0 : 3;
+			switch ($type)
+			{
+				case 'area_code':
+					if (strlen($data['value']) == 10)
+					{
+						$temp['value'] = substr($data['value'], 0, 3);
+					}
+					else
+						$temp['value'] = '';
+					$temp['class'] = 'area_code';
+					$input .= form::input(array_merge(array('value' => $val), $temp)).'-';
+					break;
+				case 'exchange':
+					$temp['value'] = substr($data['value'], (3-$offset), 3);
+					$temp['class'] = 'exchange';
+					$input .= form::input(array_merge(array('value' => $val), $temp)).'-';
+					break;
+				case 'last_four':
+					$temp['value'] = substr($data['value'], (6-$offset), 4);
+					$temp['class'] = 'last_four';
+					$input .= form::input(array_merge(array('value' => $val), $temp));
+					break;
+			}
+			
+		}
+
+		return $input;
+	}
+
+	protected function load_value()
+	{
+		if (is_bool($this->valid))
+			return;
+
+		$data = $this->input_value($this->name, $this->data['name']);
+
+		$this->data['value'] = $data['area_code'].$data['exchange'].$data['last_four'];
+	}
+} // End Form Phonenumber
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Radio.php b/modules/forge/libraries/Form_Radio.php
new file mode 100644
index 0000000..6648fd2
--- /dev/null
+++ b/modules/forge/libraries/Form_Radio.php
@@ -0,0 +1,22 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE radio input library.
+ *
+ * $Id: Form_Radio.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Radio_Core extends Form_Checkbox {
+
+	protected $data = array
+	(
+		'type' => 'radio',
+		'class' => 'radio',
+		'value' => '1',
+		'checked' => FALSE,
+	);
+
+} // End Form_Radio
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Submit.php b/modules/forge/libraries/Form_Submit.php
new file mode 100644
index 0000000..6908f6f
--- /dev/null
+++ b/modules/forge/libraries/Form_Submit.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE submit input library.
+ *
+ * $Id: Form_Submit.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Submit_Core extends Form_Input {
+
+	protected $data = array
+	(
+		'type'  => 'submit',
+		'class' => 'submit'
+	);
+
+	protected $protect = array('type');
+
+	public function render()
+	{
+		$data = $this->data;
+		unset($data['label']);
+
+		return form::submit($data);
+	}
+
+} // End Form Submit
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Textarea.php b/modules/forge/libraries/Form_Textarea.php
new file mode 100644
index 0000000..279ea56
--- /dev/null
+++ b/modules/forge/libraries/Form_Textarea.php
@@ -0,0 +1,31 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE textarea input library.
+ *
+ * $Id: Form_Textarea.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Textarea_Core extends Form_Input {
+
+	protected $data = array
+	(
+		'class' => 'textarea',
+		'value' => '',
+	);
+
+	protected $protect = array('type');
+
+	protected function html_element()
+	{
+		$data = $this->data;
+
+		unset($data['label']);
+
+		return form::textarea($data);
+	}
+
+} // End Form Textarea
\ No newline at end of file
diff --git a/modules/forge/libraries/Form_Upload.php b/modules/forge/libraries/Form_Upload.php
new file mode 100644
index 0000000..eda9c8a
--- /dev/null
+++ b/modules/forge/libraries/Form_Upload.php
@@ -0,0 +1,191 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * FORGE upload input library.
+ *
+ * $Id: Form_Upload.php 3326 2008-08-09 21:24:30Z Shadowhand $
+ *
+ * @package    Forge
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Form_Upload_Core extends Form_Input {
+
+	protected $data = array
+	(
+		'class' => 'upload',
+		'value' => '',
+	);
+
+	protected $protect = array('type', 'label', 'value');
+
+	// Upload data
+	protected $upload;
+
+	// Upload directory and filename
+	protected $directory;
+	protected $filename;
+
+	public function __construct($name, $filename = FALSE)
+	{
+		parent::__construct($name);
+
+		if ( ! empty($_FILES[$name]))
+		{
+			if (empty($_FILES[$name]['tmp_name']) OR is_uploaded_file($_FILES[$name]['tmp_name']))
+			{
+				// Cache the upload data in this object
+				$this->upload = $_FILES[$name];
+
+				// Hack to allow file-only inputs, where no POST data is present
+				$_POST[$name] = $this->upload['name'];
+
+				// Set the filename
+				$this->filename = empty($filename) ? FALSE : $filename;
+			}
+			else
+			{
+				// Attempt to delete the invalid file
+				is_writable($_FILES[$name]['tmp_name']) and unlink($_FILES[$name]['tmp_name']);
+
+				// Invalid file upload, possible hacking attempt
+				unset($_FILES[$name]);
+			}
+		}
+	}
+
+	/**
+	 * Sets the upload directory.
+	 *
+	 * @param   string   upload directory
+	 * @return  void
+	 */
+	public function directory($dir = NULL)
+	{
+		// Use the global upload directory by default
+		empty($dir) and $dir = Kohana::config('upload.directory');
+
+		// Make the path asbolute and normalize it
+		$directory = str_replace('\\', '/', realpath($dir)).'/';
+
+		// Make sure the upload director is valid and writable
+		if ($directory === '/' OR ! is_dir($directory) OR ! is_writable($directory))
+			throw new Kohana_Exception('upload.not_writable', $dir);
+
+		$this->directory = $directory;
+	}
+
+	public function validate()
+	{
+		// The upload directory must always be set
+		empty($this->directory) and $this->directory();
+
+		// By default, there is no uploaded file
+		$filename = '';
+
+		if ($status = parent::validate() AND $this->upload['error'] === UPLOAD_ERR_OK)
+		{
+			// Set the filename to the original name
+			$filename = $this->upload['name'];
+
+			if (Kohana::config('upload.remove_spaces'))
+			{
+				// Remove spaces, due to global upload configuration
+				$filename = preg_replace('/\s+/', '_', $this->data['value']);
+			}
+
+			if (file_exists($filepath = $this->directory.$filename))
+			{
+				if ($this->filename !== TRUE OR ! is_writable($filepath))
+				{
+					// Prefix the file so that the filename is unique
+					$filepath = $this->directory.'uploadfile-'.uniqid(time()).'-'.$this->upload['name'];
+				}
+			}
+
+			// Move the uploaded file to the upload directory
+			move_uploaded_file($this->upload['tmp_name'], $filepath);
+		}
+
+		if ( ! empty($_POST[$this->data['name']]))
+		{
+			// Reset the POST value to the new filename
+			$this->data['value'] = $_POST[$this->data['name']] = empty($filepath) ? '' : $filepath;
+		}
+
+		return $status;
+	}
+
+	protected function rule_required()
+	{
+		if (empty($this->upload) OR $this->upload['error'] === UPLOAD_ERR_NO_FILE)
+		{
+			$this->errors['required'] = TRUE;
+		}
+	}
+
+	public function rule_allow()
+	{
+		if (empty($this->upload['tmp_name']) OR count($types = func_get_args()) == 0)
+			return;
+
+		if (($mime = file::mime($this->upload['tmp_name'])) === FALSE)
+		{
+			// Trust the browser
+			$mime = $this->upload['type'];
+		}
+
+                // Get rid of the ";charset=binary" that can occasionally occur and is
+                // legal via RFC2045
+                $mime = preg_replace('/; charset=binary/', '', $mime);
+
+		// Allow nothing by default
+		$allow = FALSE;
+
+		foreach ($types as $type)
+		{
+			// Load the mime types
+			$type = Kohana::config('mimes.'.$type);
+
+			if (is_array($type) AND in_array($mime, $type))
+			{
+				// Type is valid
+				$allow = TRUE;
+				break;
+			}
+		}
+
+		if ($allow === FALSE)
+		{
+			$this->errors['invalid_type'] = TRUE;
+		}
+	}
+
+	public function rule_size($size)
+	{
+		// Skip the field if it is empty
+		if (empty($this->upload) OR $this->upload['error'] === UPLOAD_ERR_NO_FILE)
+			return;
+
+		$bytes = (int) $size;
+
+		switch (substr($size, -2))
+		{
+			case 'GB': $bytes *= 1024;
+			case 'MB': $bytes *= 1024;
+			case 'KB': $bytes *= 1024;
+			default: break;
+		}
+
+		if (empty($this->upload['size']) OR $this->upload['size'] > $bytes)
+		{
+			$this->errors['max_size'] = array($size);
+		}
+	}
+
+	protected function html_element()
+	{
+		return form::upload($this->data);
+	}
+
+} // End Form Upload
diff --git a/modules/g2_import/controllers/admin_g2_import.php b/modules/g2_import/controllers/admin_g2_import.php
new file mode 100644
index 0000000..c4f0390
--- /dev/null
+++ b/modules/g2_import/controllers/admin_g2_import.php
@@ -0,0 +1,136 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_g2_import_Controller extends Admin_Controller {
+  public function index() {
+    g2_import::lower_error_reporting();
+    if (g2_import::is_configured()) {
+      g2_import::init();
+    }
+
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Gallery 2 import");
+    $view->content = new View("admin_g2_import.html");
+
+    if (class_exists("GalleryCoreApi")) {
+      $view->content->g2_stats = $g2_stats = g2_import::g2_stats();
+      $view->content->g3_stats = $g3_stats = g2_import::g3_stats();
+      $view->content->g2_sizes = g2_import::common_sizes();
+      $view->content->g2_version = g2_import::version();
+
+      // Don't count tags because we don't track them in g2_map
+      $view->content->g2_resource_count =
+        $g2_stats["users"] + $g2_stats["groups"] + $g2_stats["albums"] +
+        $g2_stats["photos"] + $g2_stats["movies"] + $g2_stats["comments"];
+      $view->content->g3_resource_count =
+        $g3_stats["user"] + $g3_stats["group"] + $g3_stats["album"] +
+        $g3_stats["item"] + $g3_stats["comment"] + $g3_stats["tag"];
+    }
+
+    $view->content->form = $this->_get_import_form();
+    $view->content->version = "";
+    $view->content->thumb_size = module::get_var("gallery", "thumb_size");
+    $view->content->resize_size = module::get_var("gallery", "resize_size");
+
+    if (g2_import::is_initialized()) {
+      if ((bool)ini_get("eaccelerator.enable") || (bool)ini_get("xcache.cacher")) {
+        message::warning(t("The eAccelerator and XCache PHP performance extensions are known to cause issues.  If you're using either of those and are having problems, please disable them while you do your import.  Add the following lines: <pre>%lines</pre> to gallery3/.htaccess and remove them when the import is done.", array("lines" => "\n\n  php_value eaccelerator.enable 0\n  php_value xcache.cacher off\n  php_value xcache.optimizer off\n\n")));
+      }
+
+      foreach (array("notification", "search", "exif") as $module_id) {
+        if (module::is_active($module_id)) {
+          message::warning(
+            t("<a href=\"%url\">Deactivating</a> the <b>%module_id</b> module during your import will make it faster",
+              array("url" => url::site("admin/modules"), "module_id" => $module_id)));
+        }
+      }
+      if (module::is_active("akismet")) {
+        message::warning(
+          t("The Akismet module may mark some or all of your imported comments as spam.  <a href=\"%url\">Deactivate</a> it to avoid that outcome.",
+            array("url" => url::site("admin/modules"))));
+      }
+    } else if (g2_import::is_configured()) {
+      $view->content->form->configure_g2_import->embed_path->add_error("invalid", 1);
+    }
+    g2_import::restore_error_reporting();
+    print $view;
+  }
+
+  public function save() {
+    access::verify_csrf();
+    g2_import::lower_error_reporting();
+
+    $form = $this->_get_import_form();
+    if ($form->validate()) {
+      $embed_path = $form->configure_g2_import->embed_path->value;
+      if (!is_file($embed_path) && file_exists("$embed_path/embed.php")) {
+        $embed_path = "$embed_path/embed.php";
+      }
+
+      if (($g2_init_error = g2_import::is_valid_embed_path($embed_path)) == "ok") {
+        message::success(t("Gallery 2 path saved"));
+        module::set_var("g2_import", "embed_path", $embed_path);
+        url::redirect("admin/g2_import");
+      } else {
+        $form->configure_g2_import->embed_path->add_error($g2_init_error, 1);
+      }
+    }
+
+    $view = new Admin_View("admin.html");
+    $view->content = new View("admin_g2_import.html");
+    $view->content->form = $form;
+    g2_import::restore_error_reporting();
+    print $view;
+  }
+
+  public function autocomplete() {
+    $directories = array();
+    $path_prefix = Input::instance()->get("q");
+    foreach (glob("{$path_prefix}*") as $file) {
+      if (is_dir($file) && !is_link($file)) {
+        $file = html::clean($file);
+        $directories[] = $file;
+
+        // If we find an embed.php, include it as well
+        if (file_exists("$file/embed.php")) {
+          $directories[] = "$file/embed.php";
+        }
+      }
+    }
+
+    ajax::response(implode("\n", $directories));
+  }
+
+  private function _get_import_form() {
+    $embed_path = module::get_var("g2_import", "embed_path", "");
+    $form = new Forge(
+      "admin/g2_import/save", "", "post", array("id" => "g-admin-configure-g2-import-form"));
+    $group = $form->group("configure_g2_import")->label(t("Configure Gallery 2 Import"));
+    $group->input("embed_path")->label(t("Filesystem path to your Gallery 2 embed.php file"))
+      ->value($embed_path);
+    $group->embed_path->error_messages(
+      "invalid", t("The path you entered is not a Gallery 2 installation."));
+    $group->embed_path->error_messages(
+      "broken", t("Your Gallery 2 install isn't working properly.  Please verify it!"));
+    $group->embed_path->error_messages(
+      "missing", t("The path you entered does not exist."));
+    $group->submit("")->value($embed_path ? t("Change") : t("Continue"));
+    return $form;
+  }
+}
\ No newline at end of file
diff --git a/modules/g2_import/controllers/g2.php b/modules/g2_import/controllers/g2.php
new file mode 100644
index 0000000..c24d52e
--- /dev/null
+++ b/modules/g2_import/controllers/g2.php
@@ -0,0 +1,121 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class G2_Controller extends Controller {
+  /**
+   * Redirect Gallery 2 urls to their appropriate matching Gallery 3 url.
+   *
+   * We use mod_rewrite to create this path, so Gallery2 urls like this:
+   *   /gallery2/v/Family/Wedding.jpg.html
+   *   /gallery2/main.php?g2_view=core.ShowItem&g2_itemId=1234
+   *
+   * Show up here like this:
+   *   /g2/map?path=v/Family/Wedding.jpg.html
+   *   /g2/map?g2_view=core.ShowItem&g2_itemId=1931
+   */
+  public function map() {
+    $input = Input::instance();
+    $path = $input->get("path");
+    $id = $input->get("g2_itemId");
+    $view = $input->get("g2_view");
+
+    // Tags did not have mappings created, so we need to catch them first. However, if a g2_itemId was
+    // passed, we'll want to show lookup the mapping anyway
+    if (($path && 0 === strpos($path, "tag/")) || $view == "tags.VirtualAlbum") {
+      if (0 === strpos($path, "tag/")) {
+        $tag_name = substr($path, 4);
+      }
+      if ($view == "tags.VirtualAlbum") {
+        $tag_name = $input->get("g2_tagName");
+      }
+
+      if (!$id) {
+        url::redirect("tag_name/$tag_name", 301);
+      }
+
+      $tag = ORM::factory("tag")->where("name", "=", $tag_name)->find();
+      if ($tag->loaded()) {
+        item::set_display_context_callback("Tag_Controller::get_display_context", $tag->id);
+        // We want to show the item as part of the tag virtual album. Most of this code is below; we'll
+        // change $path and $view to let it fall through
+        $view = "";
+        $path = "";
+      }
+    }
+
+    if (($path && $path != 'index.php' && $path != 'main.php') || $id) {
+      if ($id) {
+        // Requests by id are either core.DownloadItem or core.ShowItem requests. Later versions of
+        // Gallery 2 don't specify g2_view if it's the default (core.ShowItem). And in some cases
+        // (bbcode, embedding) people are using the id style URLs although URL rewriting is enabled.
+        $where = array(array("g2_id", "=", $id));
+        if ($view == "core.DownloadItem") {
+          $where[] = array("resource_type", "IN", array("file", "resize", "thumbnail", "full"));
+        } else if ($view) {
+          $where[] = array("g2_url", "LIKE", "%" . Database::escape_for_like("g2_view=$view") . "%");
+        } // else: Assuming that the first search hit is sufficiently good.
+      } else if ($path) {
+        $where = array(array("g2_url", "IN", array($path, str_replace(" ", "+", $path))));
+      } else {
+        throw new Kohana_404_Exception();
+      }
+
+      $g2_map = ORM::factory("g2_map")
+        ->merge_where($where)
+        ->find();
+
+      if (!$g2_map->loaded()) {
+        throw new Kohana_404_Exception();
+      }
+
+      $item = ORM::factory("item", $g2_map->g3_id);
+      if (!$item->loaded()) {
+        throw new Kohana_404_Exception();
+      }
+      $resource_type = $g2_map->resource_type;
+    } else {
+      $item = item::root();
+      $resource_type = "album";
+    }
+    access::required("view", $item);
+
+
+    // Redirect the user to the new url
+    switch ($resource_type) {
+    case "thumbnail":
+      url::redirect($item->thumb_url(true), 301);
+
+    case "resize":
+      url::redirect($item->resize_url(true), 301);
+
+    case "file":
+    case "full":
+      url::redirect($item->file_url(true), 301);
+
+    case "item":
+    case "album":
+      url::redirect($item->abs_url(), 301);
+
+    case "group":
+    case "user":
+    default:
+      throw new Kohana_404_Exception();
+    }
+  }
+}
diff --git a/modules/g2_import/data/broken-image.gif b/modules/g2_import/data/broken-image.gif
new file mode 100755
index 0000000..fb9c824
Binary files /dev/null and b/modules/g2_import/data/broken-image.gif differ
diff --git a/modules/g2_import/helpers/g2_import.php b/modules/g2_import/helpers/g2_import.php
new file mode 100644
index 0000000..82850e8
--- /dev/null
+++ b/modules/g2_import/helpers/g2_import.php
@@ -0,0 +1,1375 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class g2_import_Core {
+  public static $init = false;
+  public static $map = array();
+  public static $g2_base_url = null;
+
+  private static $current_g2_item = null;
+  private static $error_reporting = null;
+
+  static function is_configured() {
+    return module::get_var("g2_import", "embed_path");
+  }
+
+  static function is_initialized() {
+    return g2_import::$init == "ok";
+  }
+
+  static function init() {
+    if (g2_import::$init) {
+      return;
+    }
+
+    $embed_path = module::get_var("g2_import", "embed_path");
+    if (empty($embed_path)) {
+      throw new Exception("@todo G2_IMPORT_NOT_CONFIGURED");
+    }
+
+    g2_import::$init = g2_import::init_embed($embed_path);
+  }
+
+  static function is_valid_embed_path($embed_path) {
+    $mod_path = VARPATH . "modules/g2_import/" . md5($embed_path);
+    if (file_exists($mod_path)) {
+      dir::unlink($mod_path);
+    }
+    return g2_import::init_embed($embed_path);
+  }
+
+  /**
+   * Initialize the embedded Gallery 2 instance.  Call this before any other Gallery 2 calls.
+   *
+   * Return values:
+   *  "ok"      - the Gallery 2 install is fine
+   *  "missing" - the embed path does not exist
+   *  "invalid" - the install path is not a valid Gallery 2 code base
+   *  "broken"  - the embed path is correct, but the Gallery 2 install is broken
+   */
+  static function init_embed($embed_path) {
+    if (!is_file($embed_path)) {
+      return "missing";
+    }
+
+    try {
+     // Gallery 2 defines a class called Gallery.  So does Gallery 3.  They don't get along.  So do
+     // a total hack here and copy over a few critical files (embed.php, main.php, bootstrap.inc
+     // and Gallery.class) and munge them so that we can rename the Gallery class to be
+     // G2_Gallery.   Is this retarded?  Why yes it is.
+     //
+     // Store the munged files in a directory that's the md5 hash of the embed path so that
+     // multiple import sources don't interfere with each other.
+
+     $mod_path = VARPATH . "modules/g2_import/" . md5($embed_path);
+     if (!file_exists($mod_path) || !file_exists("$mod_path/embed.php")) {
+       @dir::unlink($mod_path);
+       mkdir($mod_path);
+
+       $config_dir = dirname($embed_path);
+       if (filesize($embed_path) > 200) {
+         // Regular install
+         $base_dir = $config_dir;
+       } else {
+         // Multisite install.  Line 2 of embed.php will be something like:
+         //   require('/usr/home/bharat/public_html/gallery2/embed.php');
+         $lines = file($embed_path);
+         preg_match("#require\('(.*)/embed.php'\);#", $lines[2], $matches);
+         $base_dir = $matches[1];
+       }
+
+       file_put_contents(
+         "$mod_path/embed.php",
+         str_replace(
+           array(
+             "require_once(dirname(__FILE__) . '/modules/core/classes/GalleryDataCache.class');",
+             "require(dirname(__FILE__) . '/modules/core/classes/GalleryEmbed.class');"),
+           array(
+             "require_once('$base_dir/modules/core/classes/GalleryDataCache.class');",
+             "require('$base_dir/modules/core/classes/GalleryEmbed.class');"),
+           array_merge(
+             array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
+             file("$base_dir/embed.php"))));
+
+       file_put_contents(
+         "$mod_path/main.php",
+         str_replace(
+           array(
+             "include(dirname(__FILE__) . '/bootstrap.inc');",
+             "require_once(dirname(__FILE__) . '/init.inc');"),
+           array(
+             "include(dirname(__FILE__) . '/bootstrap.inc');",
+             "require_once('$base_dir/init.inc');"),
+           array_merge(
+             array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
+             file("$base_dir/main.php"))));
+
+       file_put_contents(
+         "$mod_path/bootstrap.inc",
+         str_replace(
+           array(
+             "require_once(dirname(__FILE__) . '/modules/core/classes/Gallery.class');",
+             "require_once(dirname(__FILE__) . '/modules/core/classes/GalleryDataCache.class');",
+             "define('GALLERY_CONFIG_DIR', dirname(__FILE__));",
+             "\$gallery =& new Gallery();",
+             "\$GLOBALS['gallery'] =& new Gallery();",
+             "\$gallery = new Gallery();"),
+           array(
+             "require_once(dirname(__FILE__) . '/Gallery.class');",
+             "require_once('$base_dir/modules/core/classes/GalleryDataCache.class');",
+             "define('GALLERY_CONFIG_DIR', '$config_dir');",
+             "\$gallery =& new G2_Gallery();",
+             "\$GLOBALS['gallery'] =& new G2_Gallery();",
+             "\$gallery = new G2_Gallery();"),
+           array_merge(
+             array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
+             file("$base_dir/bootstrap.inc"))));
+
+       file_put_contents(
+         "$mod_path/Gallery.class",
+         str_replace(
+           array("class Gallery",
+                 "function Gallery"),
+           array("class G2_Gallery",
+                 "function G2_Gallery"),
+           array_merge(
+             array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"),
+             file("$base_dir/modules/core/classes/Gallery.class"))));
+     } else {
+       // Ok, this is a good one.  If you're running a bytecode accelerator and you move your
+       // Gallery install, these files sometimes get cached with the wrong path and then fail to
+       // load properly.
+       // Documented in https://sourceforge.net/apps/trac/gallery/ticket/1253
+       touch("$mod_path/embed.php");
+       touch("$mod_path/main.php");
+       touch("$mod_path/bootstrap.inc");
+       touch("$mod_path/Gallery.class.inc");
+     }
+
+      require("$mod_path/embed.php");
+      if (!class_exists("GalleryEmbed")) {
+        return "invalid";
+      }
+
+      $ret = GalleryEmbed::init();
+      if ($ret) {
+        Kohana_Log::add("error", "Gallery 2 call failed with: " . $ret->getAsText());
+        return "broken";
+      }
+
+      $admin_group_id = g2(GalleryCoreApi::getPluginParameter("module", "core", "id.adminGroup"));
+      $admins = g2(GalleryCoreApi::fetchUsersForGroup($admin_group_id, 1));
+      $admin_id = current(array_flip($admins));
+      $admin = g2(GalleryCoreApi::loadEntitiesById($admin_id));
+      $GLOBALS["gallery"]->setActiveUser($admin);
+
+      // Make sure we have an embed location so that embedded url generation comes out ok.  Without
+      // this, the Gallery2 ModRewrite code won't try to do url generation.
+      $g2_embed_location =
+        g2(GalleryCoreApi::getPluginParameter("module", "rewrite", "modrewrite.embeddedLocation"));
+
+      if (empty($g2_embed_location)) {
+        $g2_embed_location =
+          g2(GalleryCoreApi::getPluginParameter("module", "rewrite", "modrewrite.galleryLocation"));
+        g2(GalleryCoreApi::setPluginParameter("module", "rewrite", "modrewrite.embeddedLocation",
+                                              $g2_embed_location));
+        g2($gallery->getStorage()->checkPoint());
+      }
+
+      if ($g2_embed_location) {
+        self::$g2_base_url = $g2_embed_location;
+      } else {
+        self::$g2_base_url = $GLOBALS["gallery"]->getUrlGenerator()->generateUrl(
+          array(),
+          array("forceSessionId" => false,
+                "htmlEntities" => false,
+                "urlEncode" => false,
+                "useAuthToken" => false));
+      }
+    } catch (ErrorException $e) {
+      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+      return "broken";
+    }
+
+    return "ok";
+  }
+
+  /**
+   * Return the version of Gallery 2 (eg "2.3")
+   */
+  static function version() {
+    $core = g2(GalleryCoreApi::loadPlugin("module", "core"));
+    $versions = $core->getInstalledVersions();
+    return $versions["gallery"];
+  }
+
+  /**
+   * Return true if the given Gallery 2 module is active.
+   */
+  static function g2_module_active($module) {
+    static $plugin_list;
+    if (!$plugin_list) {
+      $plugin_list = g2(GalleryCoreApi::fetchPluginList("module"));
+    }
+
+    return @$plugin_list[$module]["active"];
+  }
+
+  /**
+   * Return a set of statistics about the number of users, groups, albums, photos, movies and
+   * comments available for import from the Gallery 2 instance.
+   */
+  static function g2_stats() {
+    global $gallery;
+    $root_album_id = g2(GalleryCoreApi::getDefaultAlbumId());
+    $stats["users"] = g2(GalleryCoreApi::fetchUserCount());
+    $stats["groups"] = g2(GalleryCoreApi::fetchGroupCount());
+    $stats["albums"] = g2(GalleryCoreApi::fetchItemIdCount("GalleryAlbumItem"));
+    $stats["photos"] = g2(GalleryCoreApi::fetchItemIdCount("GalleryPhotoItem"));
+    $stats["movies"] = g2(GalleryCoreApi::fetchItemIdCount("GalleryMovieItem"));
+
+    if (g2_import::g2_module_active("comment") && module::is_active("comment")) {
+      GalleryCoreApi::requireOnce("modules/comment/classes/GalleryCommentHelper.class");
+      list (, $stats["comments"]) = g2(GalleryCommentHelper::fetchAllComments($root_album_id, 1));
+    } else {
+      $stats["comments"] = 0;
+    }
+
+    if (g2_import::g2_module_active("tags") && module::is_active("tag")) {
+      $result =
+        g2($gallery->search("SELECT COUNT(DISTINCT([TagItemMap::itemId])) FROM [TagItemMap]"))
+        ->nextResult();
+      $stats["tags"] = $result[0];
+    } else {
+      $stats["tags"] = 0;
+    }
+
+    return $stats;
+  }
+
+  /**
+   * Return a set of statistics about the number of users, groups, albums, photos, movies and
+   * comments already imported into the Gallery 3 instance.
+   */
+  static function g3_stats() {
+    $g3_stats = array(
+      "album" => 0, "comment" => 0, "item" => 0, "user" => 0, "group" => 0, "tag" => 0);
+    foreach (db::build()
+             ->select("resource_type")
+             ->select(array("C" => 'COUNT("*")'))
+             ->from("g2_maps")
+             ->where("resource_type", "IN", array("album", "comment", "item", "user", "group"))
+             ->group_by("resource_type")
+             ->execute() as $row) {
+      $g3_stats[$row->resource_type] = $row->C;
+    }
+    return $g3_stats;
+  }
+
+  /**
+   * Import a single group.
+   */
+  static function import_group(&$queue) {
+    $messages = array();
+    $g2_group_id = array_shift($queue);
+    if (self::map($g2_group_id)) {
+      return;
+    }
+
+    try {
+      $g2_group = g2(GalleryCoreApi::loadEntitiesById($g2_group_id));
+    } catch (Exception $e) {
+      throw new G2_Import_Exception(
+          t("Failed to import Gallery 2 group with id: %id,",
+            array("id" => $g2_group_id)),
+          $e);
+    }
+
+    switch ($g2_group->getGroupType()) {
+    case GROUP_NORMAL:
+      try {
+        $group = identity::create_group($g2_group->getGroupName());
+        $messages[] = t("Group '%name' was imported",
+                        array("name" => $g2_group->getGroupname()));
+      } catch (Exception $e) {
+        // Did it fail because of a duplicate group name?
+        $group = identity::lookup_group_by_name($g2_group->getGroupname());
+        if ($group) {
+          $messages[] = t("Group '%name' was mapped to the existing group group of the same name.",
+                          array("name" => $g2_group->getGroupname()));
+        } else {
+          throw new G2_Import_Exception(
+              t("Failed to import group '%name'",
+                array("name" => $g2_group->getGroupname())),
+              $e);
+        }
+      }
+
+      break;
+
+    case GROUP_ALL_USERS:
+      $group = identity::registered_users();
+      $messages[] = t("Group 'Registered' was converted to '%name'", array("name" => $group->name));
+      break;
+
+    case GROUP_SITE_ADMINS:
+      $messages[] = t("Group 'Admin' does not exist in Gallery 3, skipping");
+      break;  // This is not a group in G3
+
+    case GROUP_EVERYBODY:
+      $group = identity::everybody();
+      $messages[] = t("Group 'Everybody' was converted to '%name'", array("name" => $group->name));
+      break;
+    }
+
+    if (isset($group)) {
+      self::set_map($g2_group->getId(), $group->id, "group");
+    }
+
+    return $messages;
+  }
+
+  /**
+   * Import a single user.
+   */
+  static function import_user(&$queue) {
+    $messages = array();
+    $g2_user_id = array_shift($queue);
+    if (self::map($g2_user_id)) {
+      return t("User with id: %id already imported, skipping",
+               array("id" => $g2_user_id));
+    }
+
+    if (g2(GalleryCoreApi::isAnonymousUser($g2_user_id))) {
+      self::set_map($g2_user_id, identity::guest()->id, "group");
+      return t("Skipping anonymous user");
+    }
+
+    $g2_admin_group_id =
+      g2(GalleryCoreApi::getPluginParameter("module", "core", "id.adminGroup"));
+    try {
+      $g2_user = g2(GalleryCoreApi::loadEntitiesById($g2_user_id));
+    } catch (Exception $e) {
+      throw new G2_Import_Exception(
+          t("Failed to import Gallery 2 user with id: %id\n%exception",
+            array("id" => $g2_user_id, "exception" => (string)$e)),
+          $e);
+    }
+    $g2_groups = g2(GalleryCoreApi::fetchGroupsForUser($g2_user->getId()));
+
+    $user = identity::lookup_user_by_name($g2_user->getUsername());
+    if ($user) {
+      $messages[] = t("Loaded existing user: '%name'.", array("name" => $user->name));
+    } else {
+      $email = $g2_user->getEmail();
+      if (empty($email) || !valid::email($email)) {
+        $email = "unknown@unknown.com";
+      }
+      try {
+        $user = identity::create_user($g2_user->getUserName(), $g2_user->getFullName(),
+                                      // Note: The API expects a password in cleartext.
+                                      // Just use the hashed password as an unpredictable
+                                      // value here. The user will have to reset the password.
+                                      $g2_user->getHashedPassword(), $email);
+      } catch (Exception $e) {
+        throw new G2_Import_Exception(
+          t("Failed to create user: '%name' (id: %id)",
+            array("name" => $g2_user->getUserName(), "id" => $g2_user_id)),
+          $e, $messages);
+      }
+      if (class_exists("User_Model") && $user instanceof User_Model) {
+        // This will work if G2's password is a PasswordHash password as well.
+        $user->hashed_password = $g2_user->getHashedPassword();
+      }
+      $messages[] = t("Created user: '%name'.", array("name" => $user->name));
+      if ($email == "unknown@unknown.com") {
+        $messages[] = t("Fixed invalid email (was '%invalid_email')",
+                        array("invalid_email" => $g2_user->getEmail()));
+      }
+    }
+
+    $user->locale = $g2_user->getLanguage();
+    foreach ($g2_groups as $g2_group_id => $g2_group_name) {
+      if ($g2_group_id == $g2_admin_group_id) {
+        $user->admin = true;
+        $messages[] = t("Added 'admin' flag to user");
+      } else {
+        $group = identity::lookup_group(self::map($g2_group_id));
+        $user->add($group);
+        $messages[] = t("Added user to group '%group'.", array("group" => $group->name));
+      }
+    }
+
+    try {
+      $user->save();
+      self::set_map($g2_user->getId(), $user->id, "user");
+    } catch (Exception $e) {
+      throw new G2_Import_Exception(
+          t("Failed to create user: '%name'", array("name" => $user->name)),
+          $e, $messages);
+    }
+
+    return $messages;
+  }
+
+  /**
+   * Import a single album.
+   */
+  static function import_album(&$queue) {
+    // The queue is a set of nested associative arrays where the key is the album id and the
+    // value is an array of similar arrays.  We'll do a breadth first tree traversal using the
+    // queue to keep our state.  Doing it breadth first means that the parent will be created by
+    // the time we get to the child.
+
+    // Dequeue the current album and enqueue its children
+    list($g2_album_id, $children) = each($queue);
+    unset($queue[$g2_album_id]);
+    foreach ($children as $key => $value) {
+      $queue[$key] = $value;
+    }
+
+    if (self::map($g2_album_id)) {
+      return;
+    }
+
+    try {
+      // Load the G2 album item, and figure out its parent in G3.
+      $g2_album = g2(GalleryCoreApi::loadEntitiesById($g2_album_id));
+    } catch (Exception $e) {
+      return t("Failed to load Gallery 2 album with id: %id\n%exception",
+               array("id" => $g2_album_id, "exception" => (string)$e));
+    }
+
+    if ($g2_album->getParentId() == null) {
+      $album = item::root();
+    } else {
+      $parent_album = ORM::factory("item", self::map($g2_album->getParentId()));
+
+      $album = ORM::factory("item");
+      $album->type = "album";
+      $album->parent_id = self::map($g2_album->getParentId());
+
+      g2_import::set_album_values($album, $g2_album);
+
+      try {
+        $album->save();
+      } catch (Exception $e) {
+        throw new G2_Import_Exception(
+            t("Failed to import Gallery 2 album with id %id and name %name.",
+              array("id" => $g2_album_id, "name" => $album->name)),
+            $e);
+      }
+
+      self::import_keywords_as_tags($g2_album->getKeywords(), $album);
+    }
+
+    self::set_map(
+      $g2_album_id, $album->id,
+      "album",
+      self::g2_url(array("view" => "core.ShowItem", "itemId" => $g2_album->getId())));
+
+    self::_import_permissions($g2_album, $album);
+  }
+
+  /**
+   * Transfer over all the values from a G2 album to a G3 album.
+   */
+  static function set_album_values($album, $g2_album) {
+    $album->name = $g2_album->getPathComponent();
+    $album->title = self::_decode_html_special_chars($g2_album->getTitle());
+    $album->title or $album->title = $album->name;
+    $album->description = self::_decode_html_special_chars(self::extract_description($g2_album));
+    $album->owner_id = self::map($g2_album->getOwnerId());
+    try {
+      $album->view_count = (int) g2(GalleryCoreApi::fetchItemViewCount($g2_album->getId()));
+    } catch (Exception $e) {
+      // @todo log
+      $album->view_count = 0;
+    }
+    $album->created = $g2_album->getCreationTimestamp();
+
+    $order_map = array(
+      "originationTimestamp" => "captured",
+      "creationTimestamp" => "created",
+      "description" => "description",
+      "modificationTimestamp" => "updated",
+      "orderWeight" => "weight",
+      "pathComponent" => "name",
+      "summary" => "description",
+      "title" => "title",
+      "viewCount" => "view_count");
+    $direction_map = array(
+      1 => "ASC",
+      ORDER_ASCENDING => "ASC",
+      ORDER_DESCENDING => "DESC");
+    // G2 sorts can either be <sort> or <presort>|<sort>.  Right now we can't
+    // map presorts so ignore them.
+    $g2_order = explode("|", $g2_album->getOrderBy() . "");
+    $g2_order = end($g2_order);
+    if (empty($g2_order)) {
+      $g2_order = g2(GalleryCoreApi::getPluginParameter('module', 'core', 'default.orderBy'));
+    }
+    $g2_order_direction = explode("|", $g2_album->getOrderDirection() . "");
+    $g2_order_direction = $g2_order_direction[0];
+    if (empty($g2_order_direction)) {
+      $g2_order_direction =
+        g2(GalleryCoreApi::getPluginParameter('module', 'core', 'default.orderDirection'));
+    }
+    if (array_key_exists($g2_order, $order_map)) {
+      $album->sort_column = $order_map[$g2_order];
+      $album->sort_order = $direction_map[$g2_order_direction];
+    }
+  }
+
+  /**
+   * Set the highlight properly for a single album
+   */
+  static function set_album_highlight(&$queue) {
+    // Dequeue the current album and enqueue its children
+    list($g2_album_id, $children) = each($queue);
+    unset($queue[$g2_album_id]);
+    if (!empty($children)) {
+      foreach ($children as $key => $value) {
+        $queue[$key] = $value;
+      }
+    }
+
+    $messages = array();
+    $g3_album_id = self::map($g2_album_id);
+    if (!$g3_album_id) {
+      return t("Album with id: %id not imported", array("id" => $g3_album_id));
+    }
+
+    $table = g2(GalleryCoreApi::fetchThumbnailsByItemIds(array($g2_album_id)));
+    if (isset($table[$g2_album_id])) {
+      // Backtrack the source id to an item
+      $orig_g2_source = $g2_source = $table[$g2_album_id];
+      while (GalleryUtilities::isA($g2_source, "GalleryDerivative")) {
+        $g2_source = g2(GalleryCoreApi::loadEntitiesById($g2_source->getDerivativeSourceId()));
+      }
+      $item_id = self::map($g2_source->getId());
+      if ($item_id) {
+        $item = ORM::factory("item", $item_id);
+        $g3_album = ORM::factory("item", $g3_album_id);
+        $g3_album->album_cover_item_id = $item->id;
+        $g3_album->thumb_dirty = 1;
+        try {
+          $g3_album->view_count = (int) g2(GalleryCoreApi::fetchItemViewCount($g2_album_id));
+        } catch (Exception $e) {
+          $g3_album->view_count = 0;
+        }
+        try {
+          $g3_album->save();
+          graphics::generate($g3_album);
+        } catch (Exception $e) {
+          return (string) new G2_Import_Exception(
+              t("Failed to generate an album highlight for album '%name'.",
+                array("name" => $g3_album->name)),
+              $e);
+        }
+
+        self::set_map(
+          $orig_g2_source->getId(), $g3_album->id,
+          "thumbnail",
+          self::g2_url(array("view" => "core.DownloadItem", "itemId" => $orig_g2_source->getId())));
+      }
+    }
+  }
+
+  /**
+   * Import a single photo or movie.
+   */
+  static function import_item(&$queue) {
+    $g2_item_id = array_shift($queue);
+
+    if (self::map($g2_item_id)) {
+      return;
+    }
+
+    try {
+      self::$current_g2_item = $g2_item = g2(GalleryCoreApi::loadEntitiesById($g2_item_id));
+      $g2_path = g2($g2_item->fetchPath());
+    } catch (Exception $e) {
+      return t("Failed to import Gallery 2 item with id: %id\n%exception",
+               array("id" => $g2_item_id, "exception" => (string)$e));
+    }
+
+    $parent = ORM::factory("item", self::map($g2_item->getParentId()));
+
+    $g2_type = $g2_item->getEntityType();
+    $corrupt = 0;
+    if (!file_exists($g2_path)) {
+      // If the Gallery 2 source image isn't available, this operation is going to fail.  That can
+      // happen in cases where there's corruption in the source Gallery 2.  In that case, fall
+      // back on using a broken image.  It's important that we import *something* otherwise
+      // anything that refers to this item in Gallery 2 will have a dangling pointer in Gallery 3
+      //
+      // Note that this will change movies to be photos, if there's a broken movie.  Hopefully
+      // this case is rare enough that we don't need to take any heroic action here.
+      g2_import::log(
+        t("%path missing in import; replacing it with a placeholder", array("path" => $g2_path)));
+      $g2_path = MODPATH . "g2_import/data/broken-image.gif";
+      $g2_type = "GalleryPhotoItem";
+      $corrupt = 1;
+    }
+
+    $messages = array();
+    switch ($g2_type) {
+    case "GalleryPhotoItem":
+      if (!in_array($g2_item->getMimeType(), array("image/jpeg", "image/gif", "image/png"))) {
+        Kohana_Log::add("alert", "$g2_path is an unsupported image type; using a placeholder gif");
+        $messages[] = t("'%path' is an unsupported image type, using a placeholder",
+                        array("path" => $g2_path));
+        $g2_path = MODPATH . "g2_import/data/broken-image.gif";
+        $corrupt = 1;
+      }
+      try {
+        $item = ORM::factory("item");
+        $item->type = "photo";
+        $item->parent_id = $parent->id;
+        $item->set_data_file($g2_path);
+        $item->name = $g2_item->getPathComponent();
+        $item->title = self::_decode_html_special_chars($g2_item->getTitle());
+        $item->title or $item->title = $item->name;
+        $item->description = self::_decode_html_special_chars(self::extract_description($g2_item));
+        $item->owner_id = self::map($g2_item->getOwnerId());
+        $item->save();
+
+        // If the item has a preferred derivative with a rotation, then rotate this image
+        // accordingly.  Should we obey scale rules as well?  I vote no because rotation is less
+        // destructive -- you lose too much data from scaling.
+        $g2_preferred = g2(GalleryCoreApi::fetchPreferredSource($g2_item));
+        if ($g2_preferred && $g2_preferred instanceof GalleryDerivative) {
+          if (preg_match("/rotate\|(-?\d+)/", $g2_preferred->getDerivativeOperations(), $matches)) {
+            $tmpfile = tempnam(TMPPATH, "rotate");
+            gallery_graphics::rotate($item->file_path(), $tmpfile, array("degrees" => $matches[1]), $item);
+            $item->set_data_file($tmpfile);
+            $item->save();
+            unlink($tmpfile);
+          }
+        }
+      } catch (Exception $e) {
+        $exception_info = (string) new G2_Import_Exception(
+            t("Corrupt image '%path'", array("path" => $g2_path)),
+            $e, $messages);
+        Kohana_Log::add("alert", "Corrupt image $g2_path\n" . $exception_info);
+        $messages[] = $exception_info;
+        $corrupt = 1;
+        $item = null;
+      }
+      break;
+
+    case "GalleryMovieItem":
+      // @todo we should transcode other types into FLV
+      if (in_array($g2_item->getMimeType(), array("video/mp4", "video/x-flv"))) {
+        try {
+          $item = ORM::factory("item");
+          $item->type = "movie";
+          $item->parent_id = $parent->id;
+          $item->set_data_file($g2_path);
+          $item->name = $g2_item->getPathComponent();
+          $item->title = self::_decode_html_special_chars($g2_item->getTitle());
+          $item->title or $item->title = $item->name;
+          $item->description = self::_decode_html_special_chars(self::extract_description($g2_item));
+          $item->owner_id = self::map($g2_item->getOwnerId());
+          $item->save();
+        } catch (Exception $e) {
+          $exception_info = (string) new G2_Import_Exception(
+              t("Corrupt movie '%path'", array("path" => $g2_path)),
+              $e, $messages);
+          Kohana_Log::add("alert", "Corrupt movie $g2_path\n" . $exception_info);
+          $messages[] = $exception_info;
+          $corrupt = 1;
+          $item = null;
+        }
+      } else {
+        Kohana_Log::add("alert", "$g2_path is an unsupported movie type");
+        $messages[] = t("'%path' is an unsupported movie type", array("path" => $g2_path));
+        $corrupt = 1;
+      }
+
+      break;
+
+    default:
+      // Ignore
+      break;
+    }
+
+    if (!empty($item)) {
+      self::import_keywords_as_tags($g2_item->getKeywords(), $item);
+    }
+
+    $g2_item_url = self::g2_url(array("view" => "core.ShowItem", "itemId" => $g2_item->getId()));
+    if (isset($item)) {
+      try {
+        $item->view_count = (int) g2(GalleryCoreApi::fetchItemViewCount($g2_item_id));
+      } catch (Exception $e) {
+        $view_count = 1;
+      }
+      $item->save();
+
+      self::set_map($g2_item_id, $item->id, "item", $g2_item_url);
+
+      self::set_map($g2_item_id, $item->id, "file",
+                    self::g2_url(array("view" => "core.DownloadItem", "itemId" => $g2_item_id)));
+
+      $derivatives = g2(GalleryCoreApi::fetchDerivativesByItemIds(array($g2_item_id)));
+      if (!empty($derivatives[$g2_item_id])) {
+        foreach ($derivatives[$g2_item_id] as $derivative) {
+          switch ($derivative->getDerivativeType()) {
+          case DERIVATIVE_TYPE_IMAGE_THUMBNAIL: $resource_type = "thumbnail"; break;
+          case DERIVATIVE_TYPE_IMAGE_RESIZE:    $resource_type = "resize"; break;
+          case DERIVATIVE_TYPE_IMAGE_PREFERRED: $resource_type = "full"; break;
+          }
+
+          self::set_map(
+            $derivative->getId(), $item->id,
+            $resource_type,
+            self::g2_url(array("view" => "core.DownloadItem", "itemId" => $derivative->getId())));
+        }
+      }
+    }
+
+    if ($corrupt) {
+      if (!empty($item)) {
+        $title = $g2_item->getTitle();
+        $title or $title = $g2_item->getPathComponent();
+        $messages[] =
+          t("<a href=\"%g2_url\">%title</a> from Gallery 2 could not be processed; (imported as <a href=\"%g3_url\">%title</a>)",
+            array("g2_url" => $g2_item_url,
+                  "g3_url" => $item->url(),
+                  "title" => $title));
+      } else {
+        $messages[] =
+          t("<a href=\"%g2_url\">%title</a> from Gallery 2 could not be processed",
+            array("g2_url" => $g2_item_url, "title" => $g2_item->getTitle()));
+      }
+    }
+
+    self::$current_g2_item = null;
+    return $messages;
+  }
+
+  /**
+   * g2 encoded'&', '"', '<' and '>' as '&amp;', '&quot;', '&lt;' and '&gt;' respectively.
+   * This function undoes that encoding.
+   */
+  private static function _decode_html_special_chars($value) {
+    return str_replace(array("&amp;", "&quot;", "&lt;", "&gt;"),
+                       array("&", "\"", "<", ">"), $value);
+  }
+
+  private static $_permission_map = array(
+    "core.view" => "view",
+    "core.viewSource" => "view_full",
+    "core.edit" => "edit",
+    "core.addDataItem" => "add",
+    "core.addAlbumItem" => "add");
+
+  /**
+   * Imports G2 permissions, mapping G2's permission model to G3's
+   * much simplified permissions.
+   *
+   *  - Ignores user permissions, G3 only supports group permissions.
+   *  - Ignores item permissions, G3 only supports album permissions.
+   *
+   *  G2 permission   ->  G3 permission
+   *  ---------------------------------
+   *  core.view           view
+   *  core.viewSource     view_full
+   *  core.edit           edit
+   *  core.addDataItem    add
+   *  core.addAlbumItem   add
+   *  core.viewResizes    <ignored>
+   *  core.delete         <ignored>
+   *  comment.*           <ignored>
+   */
+  private static function _import_permissions($g2_album, $g3_album) {
+    // No need to do anything if this album has the same G2 ACL as its parent.
+    if ($g2_album->getParentId() != null &&
+        g2(GalleryCoreApi::fetchAccessListId($g2_album->getId())) ==
+        g2(GalleryCoreApi::fetchAccessListId($g2_album->getParentId()))) {
+      return;
+    }
+
+    $granted_permissions = self::_map_permissions($g2_album->getId());
+
+    if ($g2_album->getParentId() == null) {
+      // Compare to current permissions, and change them if necessary.
+      $g3_parent_album = item::root();
+    } else {
+      $g3_parent_album = $g3_album->parent();
+    }
+    $granted_parent_permissions = array();
+    $perm_ids = array_unique(array_values(self::$_permission_map));
+    foreach (identity::groups() as $group) {
+      $granted_parent_permissions[$group->id] = array();
+      foreach ($perm_ids as $perm_id) {
+        if (access::group_can($group, $perm_id, $g3_parent_album)) {
+          $granted_parent_permissions[$group->id][$perm_id] = 1;
+        }
+      }
+    }
+
+    // Note: Only registering permissions if they're not the same as
+    //       the inherited ones.
+    foreach ($granted_permissions as $group_id => $permissions) {
+      if (!isset($granted_parent_permissions[$group_id])) {
+        foreach (array_keys($permissions) as $perm_id) {
+          access::allow(identity::lookup_group($group_id), $perm_id, $g3_album);
+        }
+      } else if ($permissions != $granted_parent_permissions[$group_id]) {
+        $parent_permissions = $granted_parent_permissions[$group_id];
+        // @todo Probably worth caching the group instances.
+        $group = identity::lookup_group($group_id);
+        // Note: Cannot use array_diff_key.
+        foreach (array_keys($permissions) as $perm_id) {
+          if (!isset($parent_permissions[$perm_id])) {
+            access::allow($group, $perm_id, $g3_album);
+          }
+        }
+        foreach (array_keys($parent_permissions) as $perm_id) {
+          if (!isset($permissions[$perm_id])) {
+            access::deny($group, $perm_id, $g3_album);
+          }
+        }
+      }
+    }
+
+    foreach ($granted_parent_permissions as $group_id => $parent_permissions) {
+      if (isset($granted_permissions[$group_id])) {
+        continue;  // handled above
+      }
+      $group = identity::lookup_group($group_id);
+      foreach (array_keys($parent_permissions) as $perm_id) {
+        access::deny($group, $perm_id, $g3_album);
+      }
+    }
+  }
+
+  /**
+   * Loads all the granted group G2 permissions for a specific
+   * album and returns an array with G3 groups ids and G3 permission ids.
+   */
+  private static function _map_permissions($g2_album_id) {
+    $g2_permissions = g2(GalleryCoreApi::fetchAllPermissionsForItem($g2_album_id));
+    $permissions = array();
+    foreach ($g2_permissions as $entry) {
+      // @todo Do something about user permissions? E.g. map G2's user albums
+      //       to a user-specific group in G3?
+      if (!isset($entry["groupId"])) {
+        continue;
+      }
+      $g2_permission_id = $entry["permission"];
+      if (!isset(self::$_permission_map[$g2_permission_id])) {
+        continue;
+      }
+      $group_id = self::map($entry["groupId"]);
+      if ($group_id == null) {
+        // E.g. the G2 admin group isn't mapped.
+        continue;
+      }
+      $permission_id = self::$_permission_map[$g2_permission_id];
+      if (!isset($permissions[$group_id])) {
+        $permissions[$group_id] = array();
+      }
+      $permissions[$group_id][$permission_id] = 1;
+    }
+    return $permissions;
+  }
+
+  /**
+   * Import a single comment.
+   */
+  static function import_comment(&$queue) {
+    $g2_comment_id = array_shift($queue);
+
+    try {
+      $g2_comment = g2(GalleryCoreApi::loadEntitiesById($g2_comment_id));
+    } catch (Exception $e) {
+      return t("Failed to load Gallery 2 comment with id: %id\%exception",
+               array("id" => $g2_comment_id, "exception" => (string)$e));
+    }
+
+    if ($id = self::map($g2_comment->getId())) {
+      if (ORM::factory("comment", $id)->loaded()) {
+        // Already imported and still exists
+        return;
+      }
+      // This comment was already imported, but now it no longer exists.  Import it again, per
+      // ticket #1736.
+    }
+
+    $item_id = self::map($g2_comment->getParentId());
+    if (empty($item_id)) {
+      // Item was not mapped.
+      return;
+    }
+
+    $text = join("\n", array($g2_comment->getSubject(), $g2_comment->getComment()));
+    $text = html_entity_decode($text);
+
+    // Just import the fields we know about.  Do this outside of the comment API for now so that
+    // we don't trigger spam filtering events
+    $comment = ORM::factory("comment");
+    $comment->author_id = self::map($g2_comment->getCommenterId());
+    $comment->guest_name = "";
+    if ($comment->author_id == identity::guest()->id) {
+      $comment->guest_name = $g2_comment->getAuthor();
+      $comment->guest_name or $comment->guest_name = (string) t("Anonymous coward");
+      $comment->guest_email = "unknown@nobody.com";
+    }
+    $comment->item_id = $item_id;
+    $comment->text = self::_transform_bbcode($text);
+    $comment->state = "published";
+    $comment->server_http_host = $g2_comment->getHost();
+    try {
+      $comment->save();
+    } catch (Exception $e) {
+      return (string) new G2_Import_Exception(
+          t("Failed to import comment with id: %id.",
+            array("id" => $g2_comment_id)),
+          $e);
+    }
+
+    self::set_map($g2_comment->getId(), $comment->id, "comment");
+
+    // Backdate the creation date.  We can't do this at creation time because
+    // Comment_Model::save() will override it.  Leave the updated date alone
+    // so that if the comments get marked as spam, they don't immediately get
+    // flushed (see ticket #1736)
+    db::update("comments")
+      ->set("created", $g2_comment->getDate())
+      ->where("id", "=", $comment->id)
+      ->execute();
+  }
+
+  /**
+   * Import all the tags for a single item
+   */
+  static function import_tags_for_item(&$queue) {
+    if (!module::is_active("tag")) {
+      return t("Gallery 3 tag module is inactive, no tags will be imported");
+    }
+
+    GalleryCoreApi::requireOnce("modules/tags/classes/TagsHelper.class");
+    $g2_item_id = array_shift($queue);
+    $g3_item = ORM::factory("item", self::map($g2_item_id));
+    if (!$g3_item->loaded()) {
+      return;
+    }
+
+    try {
+      $tag_names = array_values(g2(TagsHelper::getTagsByItemId($g2_item_id)));
+    } catch (Exception $e) {
+      return t("Failed to import Gallery 2 tags for item with id: %id\n%exception",
+               array("id" => $g2_item_id, "exception" => (string)$e));
+    }
+
+    foreach ($tag_names as $tag_name) {
+      tag::add($g3_item, $tag_name);
+    }
+
+    // Tag operations are idempotent so we don't need to map them.  Which is good because we don't
+    // have an id for each individual tag mapping anyway so it'd be hard to set up the mapping.
+  }
+
+  static function import_keywords_as_tags($keywords, $item) {
+    // Keywords in G2 are free form.  So we don't know what our user used as a separator.  Try to
+    // be smart about it.  If we see a comma or a semicolon, expect the keywords to be separated
+    // by that delimeter.  Otherwise, use space as the delimiter.
+    if (strpos($keywords, ";")) {
+      $delim = ";";
+    } else if (strpos($keywords, ",")) {
+      $delim = ",";
+    } else {
+      $delim = " ";
+    }
+
+    foreach (preg_split("/$delim/", $keywords) as $keyword) {
+      $keyword = trim($keyword);
+      if ($keyword) {
+        tag::add($item, $keyword);
+      }
+    }
+  }
+
+  /**
+   * If the thumbnails and resizes created for the Gallery 2 photo match the dimensions of the
+   * ones we expect to create for Gallery 3, then copy the files over instead of recreating them.
+   */
+  static function copy_matching_thumbnails_and_resizes($item) {
+    // We only operate on items that are being imported
+    if (empty(self::$current_g2_item)) {
+      return;
+    }
+
+    // Precaution: if the Gallery 2 item was watermarked, or we have the Gallery 3 watermark module
+    // active then we'd have to do something a lot more sophisticated here.  For now, just skip
+    // this step in those cases.
+    // @todo we should probably use an API here, eventually.
+    if (module::is_active("watermark") && module::get_var("watermark", "name")) {
+      return;
+    }
+
+    // For now just do the copy for photos and movies.  Albums are tricky because we're may not
+    // yet be setting their album cover properly.
+    // @todo implement this for albums also
+    if (!$item->is_movie() && !$item->is_photo()) {
+      return;
+    }
+
+    $g2_item_id = self::$current_g2_item->getId();
+    $derivatives = g2(GalleryCoreApi::fetchDerivativesByItemIds(array($g2_item_id)));
+
+    $target_thumb_size = module::get_var("gallery", "thumb_size");
+    $target_resize_size = module::get_var("gallery", "resize_size");
+    if (!empty($derivatives[$g2_item_id])) {
+      foreach ($derivatives[$g2_item_id] as $derivative) {
+        if ($derivative->getPostFilterOperations()) {
+          // Let's assume for now that this is a watermark operation, which we can't handle.
+          continue;
+        }
+
+        if ($derivative->getDerivativeType() == DERIVATIVE_TYPE_IMAGE_THUMBNAIL &&
+            $item->thumb_dirty &&
+            ($derivative->getWidth() == $target_thumb_size ||
+             $derivative->getHeight() == $target_thumb_size)) {
+          if (@copy(g2($derivative->fetchPath()), $item->thumb_path())) {
+            $item->thumb_height = $derivative->getHeight();
+            $item->thumb_width = $derivative->getWidth();
+            $item->thumb_dirty = 0;
+          }
+        }
+
+        if ($derivative->getDerivativeType() == DERIVATIVE_TYPE_IMAGE_RESIZE &&
+            $item->resize_dirty &&
+            ($derivative->getWidth() == $target_resize_size ||
+             $derivative->getHeight() == $target_resize_size)) {
+          if (@copy(g2($derivative->fetchPath()), $item->resize_path())) {
+            $item->resize_height = $derivative->getHeight();
+            $item->resize_width = $derivative->getWidth();
+            $item->resize_dirty = 0;
+          }
+        }
+      }
+    }
+    try {
+      $item->save();
+    } catch (Exception $e) {
+      return (string) new G2_Import_Exception(
+          t("Failed to copy thumbnails and resizes for item '%name' (Gallery 2 id: %id)",
+            array("name" => $item->name, "id" => $g2_item_id)),
+          $e);
+    }
+  }
+
+  /**
+   * Figure out the most common resize and thumb sizes in Gallery 2 so that we can tell the admin
+   * what theme settings to set to make the import go faster.  If we match up the sizes then we
+   * can just copy over derivatives instead of running graphics toolkit operations.
+   */
+  static function common_sizes() {
+    global $gallery;
+    foreach (array("resize" => DERIVATIVE_TYPE_IMAGE_RESIZE,
+                   "thumb" => DERIVATIVE_TYPE_IMAGE_THUMBNAIL) as $type => $g2_enum) {
+      $results = g2($gallery->search(
+        "SELECT COUNT(*) AS c, [GalleryDerivativeImage::width] " .
+        "FROM [GalleryDerivativeImage], [GalleryDerivative] " .
+        "WHERE [GalleryDerivativeImage::id] = [GalleryDerivative::id] " .
+        "  AND [GalleryDerivative::derivativeType] = ? " .
+        "  AND [GalleryDerivativeImage::width] >= [GalleryDerivativeImage::height] " .
+        "GROUP BY [GalleryDerivativeImage::width] " .
+        "ORDER by c DESC",
+        array($g2_enum),
+        array("limit" => array(1))));
+      $row = $results->nextResult();
+      $sizes[$type] = array("size" => $row[1], "count" => $row[0]);
+
+      $results = g2($gallery->search(
+        "SELECT COUNT(*) AS c, [GalleryDerivativeImage::height] " .
+        "FROM [GalleryDerivativeImage], [GalleryDerivative] " .
+        "WHERE [GalleryDerivativeImage::id] = [GalleryDerivative::id] " .
+        "  AND [GalleryDerivative::derivativeType] = ? " .
+        "  AND [GalleryDerivativeImage::height] > [GalleryDerivativeImage::width] " .
+        "GROUP BY [GalleryDerivativeImage::height] " .
+        "ORDER by c DESC",
+        array($g2_enum),
+        array("limit" => array(1))));
+      $row = $results->nextResult();
+      // Compare the counts.  If the best fitting height does not match the best fitting width,
+      // then pick the one with the largest count.  Otherwise, sum them.
+      if ($sizes[$type]["size"] != $row[1]) {
+        if ($row[0] > $sizes[$type]["count"]) {
+          $sizes[$type] = array("size" => $row[1], "count" => $row[0]);
+        }
+      } else {
+        $sizes[$type]["count"] += $row[0];
+      }
+
+      $results = g2($gallery->search(
+        "SELECT COUNT(*) FROM [GalleryDerivative] WHERE [GalleryDerivative::derivativeType] = ?",
+        array($g2_enum)));
+      $row = $results->nextResult();
+      $sizes[$type]["total"] = $row[0];
+    }
+
+    return $sizes;
+  }
+
+  /**
+   * Sensibly concatenate Gallery 2 summary and descriptions into a single field.
+   */
+  static function extract_description($g2_item) {
+    // If the summary is a subset of the description just import the description, else import both.
+    $g2_summary = $g2_item->getSummary();
+    $g2_description = $g2_item->getDescription();
+    if (!$g2_summary ||
+        $g2_summary == $g2_description ||
+        strstr($g2_description, $g2_summary) !== false) {
+      $description = $g2_description;
+    } else {
+      $description = $g2_summary . " " . $g2_description;
+    }
+    return self::_transform_bbcode($description);
+  }
+
+  static $bbcode_mappings = array(
+    "#\\[b\\](.*?)\\[/b\\]#" => "<b>$1</b>",
+    "#\\[i\\](.*?)\\[/i\\]#" => "<i>$1</i>",
+    "#\\[u\\](.*?)\\[/u\\]#" => "<u>$1</u>",
+    "#\\[s\\](.*?)\\[/s\\]#" => "<s>$1</s>",
+    "#\\[url\\](.*?)\[/url\\]#" => "<a href=\"$1\">$1</a>",
+    "#\\[url=(.*?)\\](.*?)\[/url\\]#" => "<a href=\"$1\">$2</a>",
+    "#\\[img\\](.*?)\\[/img\\]#" => "<img src=\"$1\"/>",
+    "#\\[quote\\](.*?)\\[/quote\\]#" => "<blockquote><p>$1</p></blockquote>",
+    "#\\[code\\](.*?)\\[/code\\]#" => "<pre>$1</pre>",
+    "#\\[size=([^\\[]*)\\]([^\\[]*)\\[/size\\]#" => "<font size=\"$1\">$2</font>",
+    "#\\[color=([^\\[]*)\\]([^\\[]*)\\[/color\\]#" => "<font color=\"$1\">$2/font>",
+    "#\\[ul\\](.*?)\\/ul\\]#" => "<ul>$1</ul>",
+    "#\\[li\\](.*?)\\[/li\\]#" => "<li>$1</li>",
+  );
+  private static function _transform_bbcode($text) {
+    if (strpos($text, "[") !== false) {
+      $text = preg_replace(array_keys(self::$bbcode_mappings), array_values(self::$bbcode_mappings),
+                           $text);
+    }
+    return $text;
+  }
+
+  /**
+   * Get a set of photo and movie ids from Gallery 2 greater than $min_id.  We use this to get the
+   * next chunk of photos/movies to import.
+   */
+  static function get_item_ids($min_id) {
+    global $gallery;
+
+    $ids = array();
+    $results = g2($gallery->search(
+      "SELECT [GalleryItem::id] " .
+      "FROM [GalleryEntity], [GalleryItem] " .
+      "WHERE [GalleryEntity::id] = [GalleryItem::id] " .
+      "AND [GalleryEntity::entityType] IN ('GalleryPhotoItem', 'GalleryMovieItem') " .
+      "AND [GalleryItem::id] > ? " .
+      "ORDER BY [GalleryItem::id] ASC",
+      array($min_id),
+      array("limit" => array("count" => 100))));
+    while ($result = $results->nextResult()) {
+      $ids[] = $result[0];
+    }
+    return $ids;
+  }
+
+  /**
+   * Get a set of comment ids from Gallery 2 greater than $min_id.  We use this to get the
+   * next chunk of comments to import.
+   */
+  static function get_comment_ids($min_id) {
+    global $gallery;
+
+    $ids = array();
+    $results = g2($gallery->search(
+      "SELECT [GalleryComment::id] " .
+      "FROM [GalleryComment] " .
+      "WHERE [GalleryComment::publishStatus] = 0 " . // 0 == COMMENT_PUBLISH_STATUS_PUBLISHED
+      "AND [GalleryComment::id] > ? " .
+      "ORDER BY [GalleryComment::id] ASC",
+      array($min_id),
+      array("limit" => array("count" => 100))));
+    while ($result = $results->nextResult()) {
+      $ids[] = $result[0];
+    }
+    return $ids;
+  }
+
+  /**
+   * Get a set of comment ids from Gallery 2 greater than $min_id.  We use this to get the
+   * next chunk of comments to import.
+   */
+  static function get_tag_item_ids($min_id) {
+    global $gallery;
+
+    $ids = array();
+    $results = g2($gallery->search(
+      "SELECT DISTINCT([TagItemMap::itemId]) FROM [TagItemMap] " .
+      "WHERE [TagItemMap::itemId] > ? " .
+      "ORDER BY [TagItemMap::itemId] ASC",
+      array($min_id),
+      array("limit" => array("count" => 100))));
+    while ($result = $results->nextResult()) {
+      $ids[] = $result[0];
+    }
+    return $ids;
+  }
+
+  /**
+   * Get a set of user ids from Gallery 2 greater than $min_id.  We use this to get the
+   * next chunk of users to import.
+   */
+  static function get_user_ids($min_id) {
+    global $gallery;
+
+    $ids = array();
+    $results = g2($gallery->search(
+      "SELECT [GalleryUser::id] " .
+      "FROM [GalleryUser] " .
+      "WHERE [GalleryUser::id] > ? " .
+      "ORDER BY [GalleryUser::id] ASC",
+      array($min_id),
+      array("limit" => array("count" => 100))));
+    while ($result = $results->nextResult()) {
+      $ids[] = $result[0];
+    }
+    return $ids;
+  }
+
+  /**
+   * Get a set of group ids from Gallery 2 greater than $min_id.  We use this to get the
+   * next chunk of groups to import.
+   */
+  static function get_group_ids($min_id) {
+    global $gallery;
+
+    $ids = array();
+    $results = g2($gallery->search(
+      "SELECT [GalleryGroup::id] " .
+      "FROM [GalleryGroup] " .
+      "WHERE [GalleryGroup::id] > ? " .
+      "ORDER BY [GalleryGroup::id] ASC",
+      array($min_id),
+      array("limit" => array("count" => 100))));
+    while ($result = $results->nextResult()) {
+      $ids[] = $result[0];
+    }
+    return $ids;
+  }
+
+  /**
+   * Look in our map to find the corresponding Gallery 3 id for the given Gallery 2 id.
+   */
+  static function map($g2_id) {
+    if (!array_key_exists($g2_id, self::$map)) {
+      $g2_map = ORM::factory("g2_map")->where("g2_id", "=", $g2_id)->find();
+      self::$map[$g2_id] = $g2_map->loaded() ? $g2_map->g3_id : null;
+    }
+
+    return self::$map[$g2_id];
+  }
+
+  /**
+   * Associate a Gallery 2 id with a Gallery 3 item id.
+   */
+  static function set_map($g2_id, $g3_id, $resource_type, $g2_url=null) {
+    self::clear_map($g2_id, $resource_type);
+    $g2_map = ORM::factory("g2_map");
+    $g2_map->g3_id = $g3_id;
+    $g2_map->g2_id = $g2_id;
+    $g2_map->resource_type = $resource_type;
+
+    if (strpos($g2_url, self::$g2_base_url) === 0) {
+      $g2_url = substr($g2_url, strlen(self::$g2_base_url));
+    }
+
+    $g2_map->g2_url = $g2_url;
+    $g2_map->save();
+    self::$map[$g2_id] = $g3_id;
+  }
+
+  /**
+   * Remove all map entries associated with the given Gallery 2 id.
+   */
+  static function clear_map($g2_id, $resource_type) {
+    db::build()
+      ->delete("g2_maps")
+      ->where("g2_id", "=", $g2_id)
+      ->where("resource_type", "=", $resource_type)
+      ->execute();
+  }
+
+  static function log($msg) {
+    message::warning($msg);
+    Kohana_Log::add("alert", $msg);
+  }
+
+  static function g2_url($params) {
+    global $gallery;
+    return $gallery->getUrlGenerator()->generateUrl(
+      $params,
+      array("forceSessionId" => false,
+            "htmlEntities" => false,
+            "urlEncode" => false,
+            "useAuthToken" => false));
+  }
+
+  static function lower_error_reporting() {
+    // Gallery 2 was not designed to run in E_STRICT mode and will barf out errors.  So dial down
+    // the error reporting when we make G2 calls.
+    self::$error_reporting = error_reporting(error_reporting() & ~E_STRICT);
+  }
+
+  static function restore_error_reporting() {
+    error_reporting(self::$error_reporting);
+  }
+}
+
+/**
+ * Wrapper around Gallery 2 calls.  We expect the first response to be a GalleryStatus object.  If
+ * it's not null, then throw an exception.  Strip the GalleryStatus object out of the result and
+ * if there's only an array of 1 return value, turn it into a scalar.  This allows us to simplify
+ * this pattern:
+ *   list ($ret, $foo) = GalleryCoreApi::someCall();
+ *   if ($ret) { handle_error(); }
+ *
+ * to:
+ *   $foo = g2(GalleryCoreApi::someCall());
+ */
+function g2() {
+  $args = func_get_arg(0);
+  $ret = is_array($args) ? array_shift($args) : $args;
+  if ($ret) {
+    Kohana_Log::add("error", "Gallery 2 call failed with: " . $ret->getAsText());
+    throw new Exception("@todo G2_FUNCTION_FAILED");
+  }
+  if (count($args) == 1) {
+    return $args[0];
+  } else {
+    return $args;
+  }
+}
diff --git a/modules/g2_import/helpers/g2_import_event.php b/modules/g2_import/helpers/g2_import_event.php
new file mode 100644
index 0000000..b985281
--- /dev/null
+++ b/modules/g2_import/helpers/g2_import_event.php
@@ -0,0 +1,40 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class g2_import_event_Core {
+  static function item_deleted($item) {
+    db::build()
+      ->delete("g2_maps")
+      ->where("g3_id", "=", $item->id)
+      ->execute();
+  }
+
+  static function item_created($item) {
+    g2_import::copy_matching_thumbnails_and_resizes($item);
+  }
+
+  static function admin_menu($menu, $theme) {
+    $menu
+      ->get("settings_menu")
+      ->append(Menu::factory("link")
+               ->id("g2_import")
+               ->label(t("Gallery 2 import"))
+               ->url(url::site("admin/g2_import")));
+  }
+}
diff --git a/modules/g2_import/helpers/g2_import_installer.php b/modules/g2_import/helpers/g2_import_installer.php
new file mode 100644
index 0000000..c756981
--- /dev/null
+++ b/modules/g2_import/helpers/g2_import_installer.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class g2_import_installer {
+  static function install() {
+    $db = Database::instance();
+    $db->query("CREATE TABLE IF NOT EXISTS {g2_maps} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `g2_id` int(9) NOT NULL,
+                 `g3_id` int(9) NOT NULL,
+                 `g2_url` varchar(255) default NULL,
+                 `resource_type` varchar(64) default NULL,
+               PRIMARY KEY (`id`),
+               KEY `g2_url` (`g2_url`),
+               KEY `g2_id` (`g2_id`))
+               DEFAULT CHARSET=utf8;");
+
+    mkdir(VARPATH . "modules/g2_import");
+  }
+
+  static function upgrade($version) {
+    $db = Database::instance();
+    if ($version == 1) {
+      $db->query("ALTER TABLE {g2_maps} ADD COLUMN `g2_url` VARCHAR(255)");
+      $db->query("ALTER TABLE {g2_maps} ADD COLUMN `resource_type` VARCHAR(64)");
+      $db->query("ALTER TABLE {g2_maps} ADD KEY `g2_url` (`g2_url`)");
+      module::set_version("g2_import", $version = 2);
+    }
+  }
+
+  static function uninstall() {
+    @dir::unlink(VARPATH . "modules/g2_import");
+  }
+}
diff --git a/modules/g2_import/helpers/g2_import_task.php b/modules/g2_import/helpers/g2_import_task.php
new file mode 100644
index 0000000..07eacc4
--- /dev/null
+++ b/modules/g2_import/helpers/g2_import_task.php
@@ -0,0 +1,225 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class g2_import_task_Core {
+  static function available_tasks() {
+    $version = '';
+    g2_import::lower_error_reporting();
+    if (g2_import::is_configured()) {
+      g2_import::init();
+      // Guard from common case where the import has been
+      // completed and the original files have been removed.
+      if (class_exists("GalleryCoreApi")) {
+        $version = g2_import::version();
+      }
+    }
+    g2_import::restore_error_reporting();
+
+    if (g2_import::is_initialized()) {
+      return array(Task_Definition::factory()
+                   ->callback("g2_import_task::import")
+                   ->name(t("Import from Gallery 2"))
+                   ->description(
+                     t("Gallery %version detected", array("version" => $version)))
+                   ->severity(log::SUCCESS));
+    }
+
+    return array();
+  }
+
+  static function import($task) {
+    g2_import::lower_error_reporting();
+
+    $start = microtime(true);
+    g2_import::init();
+
+    $stats = $task->get("stats");
+    $done = $task->get("done");
+    $total = $task->get("total");
+    $completed = $task->get("completed");
+    $mode = $task->get("mode");
+    $queue = $task->get("queue");
+    if (!isset($mode)) {
+      $stats = g2_import::g2_stats();
+      $stats["items"] = $stats["photos"] + $stats["movies"];
+      unset($stats["photos"]);
+      unset($stats["movies"]);
+      $stats["highlights"] = $stats["albums"];
+      $task->set("stats", $stats);
+
+      $task->set("total", $total = array_sum(array_values($stats)));
+      $completed = 0;
+      $mode = 0;
+
+      $done = array();
+      foreach (array_keys($stats) as $key) {
+        $done[$key] = 0;
+      }
+      $task->set("done", $done);
+
+      // Ensure G2 ACLs are compacted to speed up import.
+      g2(GalleryCoreApi::compactAccessLists());
+    }
+
+    $modes = array("groups", "users", "albums", "items", "comments", "tags", "highlights", "done");
+    while (!$task->done && microtime(true) - $start < 1.5) {
+      if ($done[$modes[$mode]] == $stats[$modes[$mode]]) {
+        // Nothing left to do for this mode.  Advance.
+        $mode++;
+        $task->set("last_id", 0);
+        $queue = array();
+
+        // Start the loop from the beginning again.  This way if we get to a mode that requires no
+        // actions (eg, if the G2 comments module isn't installed) we won't try to do any comments
+        // queries.. in the next iteration we'll just skip over that mode.
+        if ($modes[$mode] != "done") {
+          continue;
+        }
+      }
+
+      switch($modes[$mode]) {
+      case "groups":
+        if (empty($queue)) {
+          $task->set("queue", $queue = g2_import::get_group_ids($task->get("last_id", 0)));
+          $task->set("last_id", end($queue));
+        }
+        $log_message = g2_import::import_group($queue);
+        if ($log_message) {
+          $task->log($log_message);
+        }
+        $task->status = t(
+          "Importing groups (%count of %total)",
+          array("count" => $done["groups"] + 1, "total" => $stats["groups"]));
+        break;
+
+      case "users":
+        if (empty($queue)) {
+          $task->set("queue", $queue = g2_import::get_user_ids($task->get("last_id", 0)));
+          $task->set("last_id", end($queue));
+        }
+        $log_message = g2_import::import_user($queue);
+        if ($log_message) {
+          $task->log($log_message);
+        }
+        $task->status = t(
+          "Importing users (%count of %total)",
+          array("count" => $done["users"] + 1, "total" => $stats["users"]));
+        break;
+
+      case "albums":
+        if (empty($queue)) {
+          $g2_root_id = g2(GalleryCoreApi::getDefaultAlbumId());
+          $tree = g2(GalleryCoreApi::fetchAlbumTree());
+          $task->set("queue", $queue = array($g2_root_id => $tree));
+
+          // Update the root album to reflect the Gallery2 root album.
+          $root_album = item::root();
+          g2_import::set_album_values(
+            $root_album, g2(GalleryCoreApi::loadEntitiesById($g2_root_id)));
+          $root_album->save();
+        }
+        $log_message = g2_import::import_album($queue);
+        if ($log_message) {
+          $task->log($log_message);
+        }
+        $task->status = t(
+          "Importing albums (%count of %total)",
+          array("count" => $done["albums"] + 1, "total" => $stats["albums"]));
+        break;
+
+      case "items":
+        if (empty($queue)) {
+          $task->set("queue", $queue = g2_import::get_item_ids($task->get("last_id", 0)));
+          $task->set("last_id", end($queue));
+        }
+        $log_message = g2_import::import_item($queue);
+        if ($log_message) {
+          $task->log($log_message);
+        }
+        $task->status = t(
+          "Importing photos (%count of %total)",
+          array("count" => $done["items"] + 1, "total" => $stats["items"]));
+        break;
+
+      case "comments":
+        if (empty($queue)) {
+          $task->set("queue", $queue = g2_import::get_comment_ids($task->get("last_id", 0)));
+          $task->set("last_id", end($queue));
+        }
+        $log_message = g2_import::import_comment($queue);
+        if ($log_message) {
+          $task->log($log_message);
+        }
+        $task->status = t(
+          "Importing comments (%count of %total)",
+          array("count" => $done["comments"] + 1, "total" => $stats["comments"]));
+
+        break;
+
+      case "tags":
+        if (empty($queue)) {
+          $task->set("queue", $queue = g2_import::get_tag_item_ids($task->get("last_id", 0)));
+          $task->set("last_id", end($queue));
+        }
+        $log_message = g2_import::import_tags_for_item($queue);
+        if ($log_message) {
+          $task->log($log_message);
+        }
+        $task->status = t(
+          "Importing tags (%count of %total)",
+          array("count" => $done["tags"] + 1, "total" => $stats["tags"]));
+
+        break;
+
+      case "highlights":
+        if (empty($queue)) {
+          $task->set("queue", $queue = g2(GalleryCoreApi::fetchAlbumTree()));
+        }
+        $log_message = g2_import::set_album_highlight($queue);
+        if ($log_message) {
+          $task->log($log_message);
+        }
+        $task->status = t(
+          "Album highlights (%count of %total)",
+          array("count" => $done["highlights"] + 1, "total" => $stats["highlights"]));
+
+        break;
+
+      case "done":
+        $task->status = t("Import complete");
+        $task->done = true;
+        $task->state = "success";
+        break;
+      }
+
+      if (!$task->done) {
+        $done[$modes[$mode]]++;
+        $completed++;
+      }
+    }
+
+    $task->percent_complete = 100 * ($completed / $total);
+    $task->set("completed", $completed);
+    $task->set("mode", $mode);
+    $task->set("queue", $queue);
+    $task->set("done", $done);
+
+    g2_import::restore_error_reporting();
+  }
+}
diff --git a/modules/g2_import/libraries/G2_Import_Exception.php b/modules/g2_import/libraries/G2_Import_Exception.php
new file mode 100644
index 0000000..7732cfd
--- /dev/null
+++ b/modules/g2_import/libraries/G2_Import_Exception.php
@@ -0,0 +1,39 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * A wrapper for exceptions to report more details in case
+ * it's a ORM validation exception.
+ */
+class G2_Import_Exception extends Exception {
+  public function __construct($message, Exception $previous=null, $additional_messages=null) {
+    if ($additional_messages) {
+      $message .= "\n" . implode("\n", $additional_messages);
+    }
+    if ($previous && $previous instanceof ORM_Validation_Exception) {
+      $message .= "\nORM validation errors: " . print_r($previous->validation->errors(), true);
+    }
+    if ($previous) {
+      $message .= "\n" . (string) $previous;
+    }
+    // The $previous parameter is supported in PHP 5.3.0+.
+    parent::__construct($message);
+  }
+}
\ No newline at end of file
diff --git a/modules/g2_import/models/g2_map.php b/modules/g2_import/models/g2_map.php
new file mode 100644
index 0000000..5fb566c
--- /dev/null
+++ b/modules/g2_import/models/g2_map.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class G2_Map_Model_Core extends ORM {
+}
diff --git a/modules/g2_import/module.info b/modules/g2_import/module.info
new file mode 100644
index 0000000..32af27d
--- /dev/null
+++ b/modules/g2_import/module.info
@@ -0,0 +1,7 @@
+name = "Gallery 2 Import"
+description = "Import your Gallery 2 content into Gallery 3"
+version = 2
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:g2_import"
+discuss_url = "http://galleryproject.org/forum_module_g2_import"
diff --git a/modules/g2_import/views/admin_g2_import.html.php b/modules/g2_import/views/admin_g2_import.html.php
new file mode 100644
index 0000000..22e19f5
--- /dev/null
+++ b/modules/g2_import/views/admin_g2_import.html.php
@@ -0,0 +1,150 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?= $theme->css("jquery.autocomplete.css") ?>
+<?= $theme->script("jquery.autocomplete.js") ?>
+<script type="text/javascript">
+$("document").ready(function() {
+  $("form input[name=embed_path]").gallery_autocomplete(
+    "<?= url::site("__ARGS__") ?>".replace("__ARGS__", "admin/g2_import/autocomplete"),
+    {
+      max: 256,
+      loadingClass: "g-loading-small",
+    });
+});
+</script>
+
+<div id="g-admin-g2-import" class="g-block">
+  <h1> <?= t("Gallery 2 import") ?> </h1>
+  <p>
+    <?= t("Import your Gallery 2 users, photos, movies, comments and tags into your new Gallery 3 installation.") ?>
+  </p>
+
+  <script type="text/javascript">
+    $(document).ready(function() {
+      $("#g-admin-g2-import-tabs").tabs()
+      <? if (!isset($g2_version)): ?>
+      .tabs("disable", 1)
+      .tabs("disable", 2)
+      <? elseif ($g3_resource_count > .9 * $g2_resource_count):  ?>
+      .tabs("select", 2)
+      <? else: ?>
+      .tabs("select", 1)
+      <? endif ?>
+      ;
+
+      // Show the tabs after the page has loaded to prevent Firefox from rendering the
+      // unstyled page and then flashing.
+      $("#g-admin-g2-import-tabs").show();
+    });
+  </script>
+  <div id="g-admin-g2-import-tabs" class="g-block-content" style="display: none">
+    <ul>
+      <li>
+        <a href="#g-admin-g2-import-configure"><?= t("1. Configure Gallery2 path") ?></a>
+      </li>
+      <li>
+        <a href="#g-admin-g2-import-import"><?= t("2. Import!") ?></a>
+      </li>
+      <li>
+        <a href="#g-admin-g2-import-notes"><?= t("3. After your import") ?></a>
+      </li>
+    </ul>
+    <div id="g-admin-g2-import-configure" class="g-block-content">
+      <?= $form ?>
+    </div>
+    <div id="g-admin-g2-import-import">
+      <? if (isset($g2_version)): ?>
+      <ul>
+        <li>
+          <?= t("Gallery version %version detected", array("version" => $g2_version)) ?>
+        </li>
+        <? if ($g2_sizes["thumb"]["size"] && $thumb_size != $g2_sizes["thumb"]["size"]): ?>
+        <li>
+          <?= t("Your most common thumbnail size in Gallery 2 is %g2_pixels pixels, but your Gallery 3 thumbnail size is set to %g3_pixels pixels. <a href=\"%url\">Using the same value</a> will speed up your import.",
+                array("g2_pixels" => $g2_sizes["thumb"]["size"],
+                      "g3_pixels" => $thumb_size,
+                      "url" => html::mark_clean(url::site("admin/theme_options")))) ?>
+        </li>
+        <? endif ?>
+
+        <? if ($g2_sizes["resize"]["size"] && $resize_size != $g2_sizes["resize"]["size"]): ?>
+        <li>
+          <?= t("Your most common intermediate size in Gallery 2 is %g2_pixels pixels, but your Gallery 3 intermediate size is set to %g3_pixels pixels. <a href=\"%url\">Using the same value</a> will speed up your import.",
+                array("g2_pixels" => $g2_sizes["resize"]["size"],
+                      "g3_pixels" => $resize_size,
+                      "url" => html::mark_clean(url::site("admin/theme_options")))) ?>
+        </li>
+        <? endif ?>
+
+        <li>
+          <?
+          $t = array();
+          $t[] = t2("1 user", "%count users", $g2_stats["users"]);
+          $t[] = t2("1 group", "%count groups", $g2_stats["groups"]);
+          $t[] = t2("1 album", "%count albums", $g2_stats["albums"]);
+          $t[] = t2("1 photo", "%count photos/movies", $g2_stats["photos"] + $g2_stats["movies"]);
+          $t[] = t2("1 comment", "%count comments", $g2_stats["comments"]);
+          $t[] = t2("1 tagged photo/movie/album", "%count tagged photos/movies/albums",
+                    $g2_stats["tags"]);
+          ?>
+          <?= t("Your Gallery 2 has the following importable data in it: %t0, %t1, %t2, %t3, %t4, %t5",
+                array("t0" => $t[0], "t1" => $t[1], "t2" => $t[2],
+                      "t3" => $t[3], "t4" => $t[4], "t5" => $t[5])) ?>
+        </li>
+
+        <? if ($g3_resource_count): ?>
+        <li>
+          <?
+          $t = array();
+          $t[] = t2("1 user", "%count users", $g3_stats["user"]);
+          $t[] = t2("1 group", "%count groups", $g3_stats["group"]);
+          $t[] = t2("1 album", "%count albums", $g3_stats["album"]);
+          $t[] = t2("1 photo/movie", "%count photos/movies", $g3_stats["item"]);
+          $t[] = t2("1 comment", "%count comments", $g3_stats["comment"]);
+          $t[] = t2("1 tagged photo/movie/album", "%count tagged photos/movies/albums", $g3_stats["tag"]);
+          ?>
+          <?= t("It looks like you've imported the following Gallery 2 data already: %t0, %t1, %t2, %t3, %t4, %t5",
+                array("t0" => $t[0], "t1" => $t[1], "t2" => $t[2],
+                      "t3" => $t[3], "t4" => $t[4], "t5" => $t[5])) ?>
+        </li>
+        <? endif ?>
+      </ul>
+      <p>
+        <a class="g-button g-dialog-link ui-state-default ui-corner-all"
+           href="<?= url::site("admin/maintenance/start/g2_import_task::import?csrf=$csrf") ?>">
+          <?= t("Begin import!") ?>
+        </a>
+      </p>
+      <? endif ?>
+    </div>
+    <div id="g-admin-g2-import-notes" class="g-text">
+      <ul>
+        <li>
+          <?= t("Gallery 3 does not support per-user / per-item permissions.  <b>Review permissions!</b>") ?>
+        </li>
+        <li>
+          <?= t("The only supported file formats are JPG, PNG and GIF, FLV and MP4.  Other formats will be skipped.") ?>
+        </li>
+        <li>
+          <p>
+            <?= t("Redirecting Gallery 2 URLs once your migration is complete.  Put this block at the top of your gallery2/.htaccess file and all Gallery 2 urls will be redirected to Gallery 3") ?>
+          </p>
+
+          <textarea id="g-g2-redirect-rules" rows="4" cols="60">&lt;IfModule mod_rewrite.c&gt;
+      Options +FollowSymLinks
+      RewriteEngine On
+      RewriteBase <?= html::clean(g2_import::$g2_base_url) ?>
+
+      RewriteRule ^(.*)$ <?= url::site("g2/map?path=\$1") ?>   [QSA,L,R=301]
+    &lt;/IfModule&gt;</textarea>
+          <script type="text/javascript">
+            $(document).ready(function() {
+              $("#g-g2-redirect-rules").click(function(event) {
+                this.select();
+              });
+            });
+          </script>
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
diff --git a/modules/gallery/config/cache.php b/modules/gallery/config/cache.php
new file mode 100644
index 0000000..746e95c
--- /dev/null
+++ b/modules/gallery/config/cache.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+/*
+ * @package  Cache
+ *
+ * Cache settings, defined as arrays, or "groups". If no group name is
+ * used when loading the cache library, the group named "default" will be used.
+ *
+ * Each group can be used independently, and multiple groups can be used at once.
+ *
+ * Group Options:
+ *  driver   - Cache backend driver. Kohana comes with file, database, and memcache drivers.
+ *              > File cache is fast and reliable, but requires many filesystem lookups.
+ *              > Database cache can be used to cache items remotely, but is slower.
+ *              > Memcache is very high performance, but prevents cache tags from being used.
+ *
+ *  params   - Driver parameters, specific to each driver.
+ *
+ *  lifetime - Default lifetime of caches in seconds. By default caches are stored for
+ *             thirty minutes. Specific lifetime can also be set when creating a new cache.
+ *             Setting this to 0 will never automatically delete caches.
+ *
+ *  requests - Average number of cache requests that will processed before all expired
+ *             caches are deleted. This is commonly referred to as "garbage collection".
+ *             Setting this to 0 or a negative number will disable automatic garbage collection.
+ */
+$config["default"] = array (
+  "driver"   => "database",
+  "params"   => null,
+  "lifetime" => 84600,
+  "requests" => 1000,
+  "prefix"   => null,
+);
diff --git a/modules/gallery/config/cookie.php b/modules/gallery/config/cookie.php
new file mode 100644
index 0000000..b164701
--- /dev/null
+++ b/modules/gallery/config/cookie.php
@@ -0,0 +1,48 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * Domain, to restrict the cookie to a specific website domain. For security,
+ * you are encouraged to set this option. An empty setting allows the cookie
+ * to be read by any website domain.
+ */
+$config['domain'] = '';
+
+/**
+ * Restrict cookies to a specific path, typically the installation directory.
+ */
+$config['path'] = '/';
+
+/**
+ * Lifetime of the cookie. A setting of 0 makes the cookie active until the
+ * users browser is closed or the cookie is deleted.
+ */
+$config['expire'] = 0;
+
+/**
+ * Set the secure bit on the cookie if we're using HTTPS.
+ */
+$config['secure'] = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on';
+
+/**
+ * Enable this option to disable the cookie from being accessed when using a
+ * secure protocol. This option is only available in PHP 5.2 and above.
+ */
+$config['httponly'] = true;
\ No newline at end of file
diff --git a/modules/gallery/config/database.php b/modules/gallery/config/database.php
new file mode 100644
index 0000000..4148757
--- /dev/null
+++ b/modules/gallery/config/database.php
@@ -0,0 +1,23 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+if (file_exists(VARPATH . "database.php")) {
+  include(VARPATH . "database.php");
+}
diff --git a/modules/gallery/config/locale.php b/modules/gallery/config/locale.php
new file mode 100644
index 0000000..cf37de9
--- /dev/null
+++ b/modules/gallery/config/locale.php
@@ -0,0 +1,51 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * @package  Core
+ *
+ * Default language locale name(s).
+ * First item must be a valid i18n directory name, subsequent items are alternative locales
+ * for OS's that don't support the first (e.g. Windows). The first valid locale in the array will be used.
+ * @see http://php.net/setlocale
+ */
+$config['language'] = array('en_US', 'English_United States');
+
+/**
+ * Locale timezone.  Set in 'Advanced' settings, falling back to the server's zone.
+ * @see http://php.net/timezones
+ */
+if (file_exists(VARPATH . "database.php")) {
+  $config['timezone'] = module::get_var("gallery", "timezone", date_default_timezone_get());
+} else {
+  // Gallery3 is not installed yet -- don't make module::get_var() calls.
+  $config['timezone'] = date_default_timezone_get();
+}
+
+// i18n settings
+
+/**
+ * The locale of the built-in localization messages (locale of strings in translate() calls).
+ * This can't be changed easily, unless all localization strings are replaced in all source files
+ * as well.
+ * Although the actual root is "en_US", the configured root is "en" that all en locales inherit the
+ * built-in strings.
+ */
+$config['root_locale'] = 'en';
\ No newline at end of file
diff --git a/modules/gallery/config/log_file.php b/modules/gallery/config/log_file.php
new file mode 100644
index 0000000..a79831e
--- /dev/null
+++ b/modules/gallery/config/log_file.php
@@ -0,0 +1,29 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * Message logging directory.
+ */
+$config['log_directory'] = VARPATH.'logs';
+
+/**
+ * Permissions of the log file
+ */
+$config['posix_permissions'] = 0644;
\ No newline at end of file
diff --git a/modules/gallery/config/routes.php b/modules/gallery/config/routes.php
new file mode 100644
index 0000000..d1ae8bf
--- /dev/null
+++ b/modules/gallery/config/routes.php
@@ -0,0 +1,32 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+// Admin controllers are not available, except via /admin
+$config["^admin_.*"] = null;
+
+// Redirect /form/add/admin/controller and /form/edit/admin/controller to
+// admin/controller/form_(add|edit)/parms. provides the same as below for admin pages
+$config["^form/(edit|add)/admin/(\w+)/(.*)$"] = "admin/$2/form_$1/$3";
+
+// Redirect /form/add and /form/edit to the module/form_(add|edit)/parms.
+$config["^form/(edit|add)/(\w+)/(.*)$"] = "$2/form_$1/$3";
+
+// Default page is the root album
+$config["_default"] = "albums";
diff --git a/modules/gallery/config/session.php b/modules/gallery/config/session.php
new file mode 100644
index 0000000..7ecee58
--- /dev/null
+++ b/modules/gallery/config/session.php
@@ -0,0 +1,66 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * @package Session
+ *
+ * Session driver name.
+ */
+$config['driver'] = 'database';
+
+/**
+ * Session storage parameter, used by drivers.
+ */
+$config['storage'] = '';
+
+/**
+ * Session name.
+ * It must contain only alphanumeric characters and underscores. At least one letter must be present.
+ */
+$config['name'] = 'g3sid';
+
+/**
+ * Session parameters to validate: user_agent, ip_address, expiration.
+ */
+$config['validate'] = array('user_agent', 'expiration');
+
+/**
+ * Enable or disable session encryption.
+ * Note: this has no effect on the native session driver.
+ * Note: the cookie driver always encrypts session data. Set to TRUE for stronger encryption.
+ */
+$config['encryption'] = FALSE;
+
+/**
+ * Session lifetime. Number of seconds that each session will last.
+ * A value of 0 will keep the session active until the browser is closed (with a limit of 24h).
+ */
+$config['expiration'] = 604800; // 7 days
+
+/**
+ * Number of page loads before the session id is regenerated.
+ * A value of 0 will disable automatic session id regeneration.
+ */
+$config['regenerate'] = 0;
+
+/**
+ * Percentage probability that the gc (garbage collection) routine is started.
+ */
+$config['gc_probability'] = 2;
\ No newline at end of file
diff --git a/modules/gallery/config/upload.php b/modules/gallery/config/upload.php
new file mode 100644
index 0000000..a5e8797
--- /dev/null
+++ b/modules/gallery/config/upload.php
@@ -0,0 +1,36 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * @package  Core
+ *
+ * This path is relative to your index file. Absolute paths are also supported.
+ */
+$config['directory'] = VARPATH.'uploads';
+
+/**
+ * Enable or disable directory creation.
+ */
+$config['create_directories'] = FALSE;
+
+/**
+ * Remove spaces from uploaded filenames.
+ */
+$config['remove_spaces'] = FALSE;
\ No newline at end of file
diff --git a/modules/gallery/config/user_agents.php b/modules/gallery/config/user_agents.php
new file mode 100644
index 0000000..dcdbb73
--- /dev/null
+++ b/modules/gallery/config/user_agents.php
@@ -0,0 +1,25 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+include(SYSPATH . "config/user_agents.php");
+$config["robot"]["mj12bot"] = "MJ12bot";
+$config["robot"]["speedy spider"] = "Speedy Spider";
+$config["robot"]["baidu"] = "Baiduspider";
+$config["robot"]["bing"] = "Ezooms";
+$config["robot"]["yandex"] = "YandexBot";
diff --git a/modules/gallery/controllers/admin.php b/modules/gallery/controllers/admin.php
new file mode 100644
index 0000000..b35a929
--- /dev/null
+++ b/modules/gallery/controllers/admin.php
@@ -0,0 +1,94 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Controller extends Controller {
+  private $theme;
+
+  public function __construct($theme=null) {
+    if (!identity::active_user()->admin) {
+      if (identity::active_user()->guest) {
+        Session::instance()->set("continue_url", url::abs_current(true));
+        url::redirect("login");
+      } else {
+        access::forbidden();
+      }
+    }
+
+    parent::__construct();
+  }
+
+  public function __call($controller_name, $args) {
+    if (Input::instance()->get("reauth_check")) {
+      return self::_reauth_check();
+    }
+    if (auth::must_reauth_for_admin_area()) {
+      return self::_prompt_for_reauth($controller_name, $args);
+    }
+
+    if (request::method() == "post") {
+      access::verify_csrf();
+    }
+
+    if ($controller_name == "index") {
+      $controller_name = "dashboard";
+    }
+    $controller_name = "Admin_{$controller_name}_Controller";
+    if ($args) {
+      $method = array_shift($args);
+    } else {
+      $method = "index";
+    }
+
+    if (!class_exists($controller_name) || !method_exists($controller_name, $method)) {
+      throw new Kohana_404_Exception();
+    }
+
+    call_user_func_array(array(new $controller_name, $method), $args);
+  }
+
+  private static function _reauth_check() {
+    $session = Session::instance();
+    $last_active_auth = $session->get("active_auth_timestamp", 0);
+    $last_admin_area_activity = $session->get("admin_area_activity_timestamp", 0);
+    $admin_area_timeout = module::get_var("gallery", "admin_area_timeout");
+
+    $time_remaining = max($last_active_auth, $last_admin_area_activity) +
+      $admin_area_timeout - time();
+
+    $result = new stdClass();
+    $result->result = "success";
+    if ($time_remaining < 30) {
+      message::success(t("Automatically logged out of the admin area for your security"));
+      $result->location = url::abs_site("");
+    }
+
+    json::reply($result);
+  }
+
+  private static function _prompt_for_reauth($controller_name, $args) {
+    if (request::method() == "get") {
+      // Avoid anti-phishing protection by passing the url as session variable.
+      Session::instance()->set("continue_url", url::abs_current(true));
+    }
+    // Save the is_ajax value as we lose it, if set, when we redirect
+    Session::instance()->set("is_ajax_request", request::is_ajax());
+    url::redirect("reauthenticate");
+  }
+}
+
diff --git a/modules/gallery/controllers/admin_advanced_settings.php b/modules/gallery/controllers/admin_advanced_settings.php
new file mode 100644
index 0000000..267ff14
--- /dev/null
+++ b/modules/gallery/controllers/admin_advanced_settings.php
@@ -0,0 +1,57 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Advanced_Settings_Controller extends Admin_Controller {
+  public function index() {
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Advanced settings");
+    $view->content = new View("admin_advanced_settings.html");
+    $view->content->vars = ORM::factory("var")
+      ->order_by("module_name")
+      ->order_by("name")
+      ->find_all();
+    print $view;
+  }
+
+  public function edit($module_name, $var_name) {
+    if (module::is_installed($module_name)) {
+      $value = module::get_var($module_name, $var_name);
+      $form = new Forge("admin/advanced_settings/save/$module_name/$var_name", "", "post");
+      $group = $form->group("edit_var")->label(t("Edit setting"));
+      $group->input("module_name")->label(t("Module"))->value($module_name)->disabled(1);
+      $group->input("var_name")->label(t("Setting"))->value($var_name)->disabled(1);
+      $group->textarea("value")->label(t("Value"))->value($value);
+      $group->submit("")->value(t("Save"));
+      print $form;
+    }
+  }
+
+  public function save($module_name, $var_name) {
+    access::verify_csrf();
+
+    if (module::is_installed($module_name)) {
+      module::set_var($module_name, $var_name, Input::instance()->post("value"));
+      message::success(
+        t("Saved value for %var (%module_name)",
+          array("var" => $var_name, "module_name" => $module_name)));
+
+      json::reply(array("result" => "success"));
+    }
+  }
+}
diff --git a/modules/gallery/controllers/admin_dashboard.php b/modules/gallery/controllers/admin_dashboard.php
new file mode 100644
index 0000000..5317210
--- /dev/null
+++ b/modules/gallery/controllers/admin_dashboard.php
@@ -0,0 +1,97 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Dashboard_Controller extends Admin_Controller {
+  public function index() {
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Dashboard");
+    $view->content = new View("admin_dashboard.html");
+    $view->content->blocks = block_manager::get_html("dashboard_center");
+    $view->sidebar = "<div id=\"g-admin-dashboard-sidebar\">" .
+      block_manager::get_html("dashboard_sidebar") .
+      "</div>";
+    $view->content->obsolete_modules_message = module::get_obsolete_modules_message();
+    print $view;
+  }
+
+  public function add_block() {
+    access::verify_csrf();
+
+    $form = gallery_block::get_add_block_form();
+    if ($form->validate()) {
+      list ($module_name, $id) = explode(":", $form->add_block->id->value);
+      $available = block_manager::get_available_admin_blocks();
+
+      if ($form->add_block->center->value) {
+        block_manager::add("dashboard_center", $module_name, $id);
+        message::success(
+          t("Added <b>%title</b> block to the dashboard center",
+            array("title" => $available["$module_name:$id"])));
+      } else {
+        block_manager::add("dashboard_sidebar", $module_name, $id);
+        message::success(
+          t("Added <b>%title</b> to the dashboard sidebar",
+            array("title" => $available["$module_name:$id"])));
+      }
+    }
+    url::redirect("admin/dashboard");
+  }
+
+  public function remove_block($id) {
+    access::verify_csrf();
+
+    $blocks_center = block_manager::get_active("dashboard_center");
+    $blocks_sidebar = block_manager::get_active("dashboard_sidebar");
+
+    if (array_key_exists($id, $blocks_sidebar)) {
+      $deleted = $blocks_sidebar[$id];
+      block_manager::remove("dashboard_sidebar", $id);
+    } else if (array_key_exists($id, $blocks_center)) {
+      $deleted = $blocks_center[$id];
+      block_manager::remove("dashboard_center", $id);
+    }
+
+    if (!empty($deleted)) {
+      $available = block_manager::get_available_admin_blocks();
+      $title = $available[join(":", $deleted)];
+      message::success(t("Removed <b>%title</b> block", array("title" => $title)));
+    }
+
+    url::redirect("admin");
+  }
+
+  public function reorder() {
+    access::verify_csrf();
+
+    $active_set = array();
+    foreach (array("dashboard_sidebar", "dashboard_center") as $location) {
+      foreach (block_manager::get_active($location) as $id => $info) {
+        $active_set[$id] = $info;
+      }
+    }
+
+    foreach (array("dashboard_sidebar", "dashboard_center") as $location) {
+      $new_blocks = array();
+      foreach (Input::instance()->get($location, array()) as $id) {
+        $new_blocks[$id] = $active_set[$id];
+      }
+      block_manager::set_active($location, $new_blocks);
+    }
+  }
+}
diff --git a/modules/gallery/controllers/admin_graphics.php b/modules/gallery/controllers/admin_graphics.php
new file mode 100644
index 0000000..a24486f
--- /dev/null
+++ b/modules/gallery/controllers/admin_graphics.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Graphics_Controller extends Admin_Controller {
+  public function index() {
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Graphics settings");
+    $view->content = new View("admin_graphics.html");
+    $view->content->tk = graphics::detect_toolkits();
+    $view->content->active = module::get_var("gallery", "graphics_toolkit", "none");
+    print $view;
+  }
+
+  public function choose($toolkit_id) {
+    access::verify_csrf();
+
+    if ($toolkit_id != module::get_var("gallery", "graphics_toolkit")) {
+      $tk = graphics::detect_toolkits();
+      module::set_var("gallery", "graphics_toolkit", $toolkit_id);
+      module::set_var("gallery", "graphics_toolkit_path", $tk->$toolkit_id->dir);
+
+      site_status::clear("missing_graphics_toolkit");
+
+      $msg = t("Changed graphics toolkit to: %toolkit", array("toolkit" => $tk->$toolkit_id->name));
+      message::success($msg);
+      log::success("graphics", $msg);
+
+      module::event("graphics_toolkit_change", $toolkit_id);
+    }
+
+    url::redirect("admin/graphics");
+  }
+}
+
diff --git a/modules/gallery/controllers/admin_languages.php b/modules/gallery/controllers/admin_languages.php
new file mode 100644
index 0000000..50ddc67
--- /dev/null
+++ b/modules/gallery/controllers/admin_languages.php
@@ -0,0 +1,135 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Languages_Controller extends Admin_Controller {
+  public function index($share_translations_form=null) {
+    $v = new Admin_View("admin.html");
+    $v->page_title = t("Languages and translations");
+    $v->content = new View("admin_languages.html");
+                $v->content->available_locales = locales::available();
+    $v->content->installed_locales = locales::installed();
+    $v->content->default_locale = module::get_var("gallery", "default_locale");
+
+    if (empty($share_translations_form)) {
+      $share_translations_form = $this->_share_translations_form();
+    }
+    $v->content->share_translations_form = $share_translations_form;
+    $this->_outgoing_translations_count();
+    print $v;
+  }
+
+  public function save() {
+    access::verify_csrf();
+
+    $input = Input::instance();
+    locales::update_installed($input->post("installed_locales"));
+
+    $installed_locales = array_keys(locales::installed());
+    $new_default_locale = $input->post("default_locale");
+    if (!in_array($new_default_locale, $installed_locales)) {
+      if (!empty($installed_locales)) {
+        $new_default_locale = $installed_locales[0];
+      } else {
+        $new_default_locale = "en_US";
+      }
+    }
+    module::set_var("gallery", "default_locale", $new_default_locale);
+
+    json::reply(array("result" => "success"));
+  }
+
+  public function share() {
+    access::verify_csrf();
+
+    $form = $this->_share_translations_form();
+    if (!$form->validate()) {
+      // Show the page with form errors
+      return $this->index($form);
+    }
+
+    if (Input::instance()->post("share")) {
+      l10n_client::submit_translations();
+      message::success(t("Translations submitted"));
+    } else {
+      return $this->_save_api_key($form);
+    }
+    url::redirect("admin/languages");
+  }
+
+  private function _save_api_key($form) {
+    $new_key = $form->sharing->api_key->value;
+    if ($new_key) {
+      list($connected, $valid) = l10n_client::validate_api_key($new_key);
+      if (!$valid) {
+        $form->sharing->api_key->add_error($connected ? "invalid" : "no_connection", 1);
+      }
+    } else {
+      $valid = true;
+    }
+
+    if ($valid) {
+        $old_key = l10n_client::api_key();
+        l10n_client::api_key($new_key);
+        if ($old_key && !$new_key) {
+          message::success(t("Your API key has been cleared."));
+        } else if ($old_key && $new_key && $old_key != $new_key) {
+          message::success(t("Your API key has been changed."));
+        } else if (!$old_key && $new_key) {
+          message::success(t("Your API key has been saved."));
+        } else if ($old_key && $new_key && $old_key == $new_key) {
+          message::info(t("Your API key was not changed."));
+        }
+
+        log::success(t("gallery"), t("l10n_client API key changed."));
+        url::redirect("admin/languages");
+    } else {
+      // Show the page with form errors
+      $this->index($form);
+    }
+  }
+
+  private function _outgoing_translations_count() {
+    return ORM::factory("outgoing_translation")->count_all();
+  }
+
+  private function _share_translations_form() {
+    $form = new Forge("admin/languages/share", "", "post", array("id" => "g-share-translations-form"));
+    $group = $form->group("sharing")
+      ->label("Translations API Key");
+    $api_key = l10n_client::api_key();
+    $server_link = l10n_client::server_api_key_url();
+    $group->input("api_key")
+      ->label(empty($api_key)
+              ? t("This is a unique key that will allow you to send translations to the remote
+                  server. To get your API key go to %server-link.",
+                  array("server-link" => html::mark_clean(html::anchor($server_link))))
+              : t("API key"))
+      ->value($api_key)
+      ->error_messages("invalid", t("The API key you provided is invalid."))
+      ->error_messages(
+        "no_connection", t("Could not connect to remote server to validate the API key."));
+    $group->submit("save")->value(t("Save settings"));
+    if ($api_key && $this->_outgoing_translations_count()) {
+      // TODO: UI improvement: hide API key / save button when API key is set.
+      $group->submit("share")->value(t("Submit translations"));
+    }
+    return $form;
+  }
+}
+
diff --git a/modules/gallery/controllers/admin_maintenance.php b/modules/gallery/controllers/admin_maintenance.php
new file mode 100644
index 0000000..32f2078
--- /dev/null
+++ b/modules/gallery/controllers/admin_maintenance.php
@@ -0,0 +1,243 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Maintenance_Controller extends Admin_Controller {
+  /**
+   * Show a list of all available, running and finished tasks.
+   */
+  public function index() {
+    $query = db::build()
+      ->update("tasks")
+      ->set("state", "stalled")
+      ->where("done", "=", 0)
+      ->where("state", "<>", "stalled")
+      ->where(db::expr("UNIX_TIMESTAMP(NOW()) - `updated` > 15"))
+      ->execute();
+    $stalled_count = $query->count();
+    if ($stalled_count) {
+      log::warning("tasks",
+                   t2("One task is stalled",
+                      "%count tasks are stalled",
+                      $stalled_count),
+                   t('<a href="%url">view</a>',
+                     array("url" => html::mark_clean(url::site("admin/maintenance")))));
+    }
+
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Maintenance tasks");
+    $view->content = new View("admin_maintenance.html");
+    $view->content->task_definitions = task::get_definitions();
+    $view->content->running_tasks = ORM::factory("task")
+      ->where("done", "=", 0)->order_by("updated", "DESC")->find_all();
+    $view->content->finished_tasks = ORM::factory("task")
+      ->where("done", "=", 1)->order_by("updated", "DESC")->find_all();
+    print $view;
+
+    // Do some maintenance while we're in here
+    db::build()
+      ->delete("caches")
+      ->where("expiration", "<>", 0)
+      ->where("expiration", "<=", time())
+      ->execute();
+    module::deactivate_missing_modules();
+  }
+
+  /**
+   * Start a new task
+   * @param string $task_callback
+   */
+  public function start($task_callback) {
+    access::verify_csrf();
+
+    $task = task::start($task_callback);
+    $view = new View("admin_maintenance_task.html");
+    $view->task = $task;
+
+    log::info("tasks", t("Task %task_name started (task id %task_id)",
+                         array("task_name" => $task->name, "task_id" => $task->id)),
+              html::anchor("admin/maintenance", t("maintenance")));
+    print $view;
+  }
+
+  /**
+   * Resume a stalled task
+   * @param string $task_id
+   */
+  public function resume($task_id) {
+    access::verify_csrf();
+
+    $task = ORM::factory("task", $task_id);
+    if (!$task->loaded()) {
+      throw new Exception("@todo MISSING_TASK");
+    }
+    $view = new View("admin_maintenance_task.html");
+    $view->task = $task;
+
+    $task->log(t("Task %task_name resumed (task id %task_id)",
+                 array("task_name" => $task->name, "task_id" => $task->id)));
+    log::info("tasks", t("Task %task_name resumed (task id %task_id)",
+                         array("task_name" => $task->name, "task_id" => $task->id)),
+              html::anchor("admin/maintenance", t("maintenance")));
+    print $view;
+  }
+
+  /**
+   * Show the task log
+   * @param string $task_id
+   */
+  public function show_log($task_id) {
+    access::verify_csrf();
+
+    $task = ORM::factory("task", $task_id);
+    if (!$task->loaded()) {
+      throw new Exception("@todo MISSING_TASK");
+    }
+    $view = new View("admin_maintenance_show_log.html");
+    $view->task = $task;
+
+    print $view;
+  }
+
+  /**
+   * Save the task log
+   * @param string $task_id
+   */
+  public function save_log($task_id) {
+    access::verify_csrf();
+
+    $task = ORM::factory("task", $task_id);
+    if (!$task->loaded()) {
+      throw new Exception("@todo MISSING_TASK");
+    }
+
+    header("Content-Type: application/text");
+    header("Content-Disposition: filename=gallery3_task_log.txt");
+    print $task->get_log();
+  }
+
+  /**
+   * Cancel a task.
+   * @param string $task_id
+   */
+  public function cancel($task_id) {
+    access::verify_csrf();
+
+    task::cancel($task_id);
+
+    message::success(t("Task cancelled"));
+    url::redirect("admin/maintenance");
+  }
+
+  public function cancel_running_tasks() {
+    access::verify_csrf();
+    db::build()
+      ->update("tasks")
+      ->set("done", 1)
+      ->set("state", "cancelled")
+      ->where("done", "=", 0)
+      ->execute();
+    message::success(t("All running tasks cancelled"));
+    url::redirect("admin/maintenance");
+  }
+
+  /**
+   * Remove a task.
+   * @param string $task_id
+   */
+  public function remove($task_id) {
+    access::verify_csrf();
+
+    task::remove($task_id);
+
+    message::success(t("Task removed"));
+    url::redirect("admin/maintenance");
+  }
+
+  public function remove_finished_tasks() {
+    access::verify_csrf();
+
+    // Do it the long way so we can call delete and remove the cache.
+    $finished = ORM::factory("task")
+      ->where("done", "=", 1)
+      ->find_all();
+    foreach ($finished as $task) {
+      task::remove($task->id);
+    }
+    message::success(t("All finished tasks removed"));
+    url::redirect("admin/maintenance");
+  }
+
+  /**
+   * Run a task.  This will trigger the task to do a small amount of work, then it will report
+   * back with status on the task.
+   * @param string $task_id
+   */
+  public function run($task_id) {
+    access::verify_csrf();
+
+    try {
+      $task = task::run($task_id);
+    } catch (Exception $e) {
+      Kohana_Log::add(
+        "error",
+        sprintf(
+          "%s in %s at line %s:\n%s", $e->getMessage(), $e->getFile(),
+          $e->getLine(), $e->getTraceAsString()));
+      throw $e;
+    }
+
+    if ($task->done) {
+      switch ($task->state) {
+      case "success":
+        log::success("tasks", t("Task %task_name completed (task id %task_id)",
+                                array("task_name" => $task->name, "task_id" => $task->id)),
+                     html::anchor("admin/maintenance", t("maintenance")));
+        message::success(t("Task completed successfully"));
+        break;
+
+      case "error":
+        log::error("tasks", t("Task %task_name failed (task id %task_id)",
+                              array("task_name" => $task->name, "task_id" => $task->id)),
+                   html::anchor("admin/maintenance", t("maintenance")));
+        message::success(t("Task failed"));
+        break;
+      }
+      // Using sprintf("%F") to avoid comma as decimal separator.
+      json::reply(array("result" => "success",
+                        "task" => array(
+                          "percent_complete" => sprintf("%F", $task->percent_complete),
+                          "status" => (string) $task->status,
+                          "done" => (bool) $task->done),
+                        "location" => url::site("admin/maintenance")));
+
+    } else {
+      json::reply(array("result" => "in_progress",
+                        "task" => array(
+                          "percent_complete" => sprintf("%F", $task->percent_complete),
+                          "status" => (string) $task->status,
+                          "done" => (bool) $task->done)));
+    }
+  }
+
+  public function maintenance_mode($value) {
+    access::verify_csrf();
+    module::set_var("gallery", "maintenance_mode", $value);
+    url::redirect("admin/maintenance");
+  }
+}
diff --git a/modules/gallery/controllers/admin_modules.php b/modules/gallery/controllers/admin_modules.php
new file mode 100644
index 0000000..177a925
--- /dev/null
+++ b/modules/gallery/controllers/admin_modules.php
@@ -0,0 +1,119 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Modules_Controller extends Admin_Controller {
+  public function index() {
+    // If modules need upgrading, this will get recreated in module::available()
+    site_status::clear("upgrade_now");
+
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Modules");
+    $view->content = new View("admin_modules.html");
+    $view->content->available = module::available();
+    $view->content->obsolete_modules_message = module::get_obsolete_modules_message();
+    print $view;
+  }
+
+
+  public function confirm() {
+    access::verify_csrf();
+
+    $messages = array("error" => array(), "warn" => array());
+    $desired_list = array();
+    foreach (module::available() as $module_name => $info) {
+      if ($info->locked) {
+        continue;
+      }
+
+      if ($desired = Input::instance()->post($module_name) == 1) {
+        $desired_list[] = $module_name;
+      }
+      if ($info->active && !$desired && module::is_active($module_name)) {
+        $messages = array_merge($messages, module::can_deactivate($module_name));
+      } else if (!$info->active && $desired && !module::is_active($module_name)) {
+        $messages = array_merge($messages, module::can_activate($module_name));
+      }
+    }
+
+    if (empty($messages["error"]) && empty($messages["warn"])) {
+      $this->_do_save();
+      $result["reload"] = 1;
+    } else {
+      $v = new View("admin_modules_confirm.html");
+      $v->messages = $messages;
+      $v->modules = $desired_list;
+      $result["dialog"] = (string)$v;
+      $result["allow_continue"] = empty($messages["error"]);
+    }
+    json::reply($result);
+  }
+
+  public function save() {
+    access::verify_csrf();
+
+    $this->_do_save();
+    url::redirect("admin/modules");
+  }
+
+  private function _do_save() {
+    $changes = new stdClass();
+    $changes->activate = array();
+    $changes->deactivate = array();
+    $activated_names = array();
+    $deactivated_names = array();
+    foreach (module::available() as $module_name => $info) {
+      if ($info->locked) {
+        continue;
+      }
+
+      try {
+        $desired = Input::instance()->post($module_name) == 1;
+        if ($info->active && !$desired && module::is_active($module_name)) {
+          module::deactivate($module_name);
+          $changes->deactivate[] = $module_name;
+          $deactivated_names[] = t($info->name);
+        } else if (!$info->active && $desired && !module::is_active($module_name)) {
+          if (module::is_installed($module_name)) {
+            module::upgrade($module_name);
+          } else {
+            module::install($module_name);
+          }
+          module::activate($module_name);
+          $changes->activate[] = $module_name;
+          $activated_names[] = t($info->name);
+        }
+      } catch (Exception $e) {
+        message::warning(t("An error occurred while installing the <b>%module_name</b> module",
+                           array("module_name" => $info->name)));
+        Kohana_Log::add("error", (string)$e);
+      }
+    }
+
+    module::event("module_change", $changes);
+
+    // @todo this type of collation is questionable from an i18n perspective
+    if ($activated_names) {
+      message::success(t("Activated: %names", array("names" => join(", ", $activated_names))));
+    }
+    if ($deactivated_names) {
+      message::success(t("Deactivated: %names", array("names" => join(", ", $deactivated_names))));
+    }
+  }
+}
+
diff --git a/modules/gallery/controllers/admin_movies.php b/modules/gallery/controllers/admin_movies.php
new file mode 100644
index 0000000..38fa44a
--- /dev/null
+++ b/modules/gallery/controllers/admin_movies.php
@@ -0,0 +1,72 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Movies_Controller extends Admin_Controller {
+  public function index() {
+    // Print screen from new form.
+    $form = $this->_get_admin_form();
+    $this->_print_view($form);
+  }
+
+  public function save() {
+    access::verify_csrf();
+    $form = $this->_get_admin_form();
+    if ($form->validate()) {
+      module::set_var("gallery", "movie_allow_uploads", $form->settings->allow_uploads->value);
+      if ($form->settings->rebuild_thumbs->value) {
+        graphics::mark_dirty(true, false, "movie");
+      }
+      // All done - redirect with message.
+      message::success(t("Movies settings updated successfully"));
+      url::redirect("admin/movies");
+    }
+    // Something went wrong - print view from existing form.
+    $this->_print_view($form);
+  }
+
+  private function _print_view($form) {
+    list ($ffmpeg_version, $ffmpeg_date) = movie::get_ffmpeg_version();
+    $ffmpeg_version = $ffmpeg_date ? "{$ffmpeg_version} ({$ffmpeg_date})" : $ffmpeg_version;
+    $ffmpeg_path = movie::find_ffmpeg();
+    $ffmpeg_dir = substr($ffmpeg_path, 0, strrpos($ffmpeg_path, "/"));
+
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Movies settings");
+    $view->content = new View("admin_movies.html");
+    $view->content->form = $form;
+    $view->content->ffmpeg_dir = $ffmpeg_dir;
+    $view->content->ffmpeg_version = $ffmpeg_version;
+    print $view;
+  }
+
+  private function _get_admin_form() {
+    $form = new Forge("admin/movies/save", "", "post", array("id" => "g-movies-admin-form"));
+    $group = $form->group("settings")->label(t("Settings"));
+    $group->dropdown("allow_uploads")
+      ->label(t("Allow movie uploads into Gallery (does not affect existing movies)"))
+      ->options(array("autodetect"=>t("only if FFmpeg is detected (default)"),
+                      "always"=>t("always"), "never"=>t("never")))
+      ->selected(module::get_var("gallery", "movie_allow_uploads", "autodetect"));
+    $group->checkbox("rebuild_thumbs")
+      ->label(t("Rebuild all movie thumbnails (once FFmpeg is installed, use this to update existing movie thumbnails)"))
+      ->checked(false);  // always set as false
+    $form->submit("save")->value(t("Save"));
+    return $form;
+  }
+}
diff --git a/modules/gallery/controllers/admin_sidebar.php b/modules/gallery/controllers/admin_sidebar.php
new file mode 100644
index 0000000..f150f85
--- /dev/null
+++ b/modules/gallery/controllers/admin_sidebar.php
@@ -0,0 +1,69 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Sidebar_Controller extends Admin_Controller {
+  public function index() {
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Manage sidebar");
+    $view->content = new View("admin_sidebar.html");
+    $view->content->csrf = access::csrf_token();
+    $view->content->available = new View("admin_sidebar_blocks.html");
+    $view->content->active = new View("admin_sidebar_blocks.html");
+    list($view->content->available->blocks, $view->content->active->blocks) = $this->_get_blocks();
+    print $view;
+  }
+
+  public function update() {
+    access::verify_csrf();
+
+    $available_blocks = block_manager::get_available_site_blocks();
+
+    $active_blocks = array();
+    foreach (Input::instance()->get("block", array()) as $block_id) {
+      $active_blocks[md5($block_id)] = explode(":", (string) $block_id);
+    }
+    block_manager::set_active("site_sidebar", $active_blocks);
+
+    $result = array("result" => "success");
+    list($available, $active) = $this->_get_blocks();
+    $v = new View("admin_sidebar_blocks.html");
+    $v->blocks = $available;
+    $result["available"] = $v->render();
+    $v = new View("admin_sidebar_blocks.html");
+    $v->blocks = $active;
+    $result["active"] = $v->render();
+    $message = t("Updated sidebar blocks");
+    $result["message"] = (string) $message;
+    json::reply($result);
+  }
+
+  private function _get_blocks() {
+    $active_blocks = array();
+    $available_blocks = block_manager::get_available_site_blocks();
+    foreach (block_manager::get_active("site_sidebar") as $block) {
+      $id = "{$block[0]}:{$block[1]}";
+      if (!empty($available_blocks[$id])) {
+        $active_blocks[$id] = $available_blocks[$id];
+        unset($available_blocks[$id]);
+      }
+    }
+    return array($available_blocks, $active_blocks);
+  }
+}
+
diff --git a/modules/gallery/controllers/admin_theme_options.php b/modules/gallery/controllers/admin_theme_options.php
new file mode 100644
index 0000000..38d2b0a
--- /dev/null
+++ b/modules/gallery/controllers/admin_theme_options.php
@@ -0,0 +1,120 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Theme_Options_Controller extends Admin_Controller {
+  public function index() {
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Theme options");
+    $view->content = new View("admin_theme_options.html");
+    $view->content->form = $this->_get_edit_form_admin();
+    print $view;
+  }
+
+  public function save() {
+    access::verify_csrf();
+
+    $form = $this->_get_edit_form_admin();
+    if ($form->validate()) {
+      module::set_var("gallery", "page_size", $form->edit_theme->page_size->value);
+
+      $thumb_size = $form->edit_theme->thumb_size->value;
+      if (module::get_var("gallery", "thumb_size") != $thumb_size) {
+        graphics::remove_rule("gallery", "thumb", "gallery_graphics::resize");
+        graphics::add_rule(
+          "gallery", "thumb", "gallery_graphics::resize",
+          array("width" => $thumb_size, "height" => $thumb_size, "master" => Image::AUTO),
+          100);
+        module::set_var("gallery", "thumb_size", $thumb_size);
+      }
+
+      $resize_size = $form->edit_theme->resize_size->value;
+      if (module::get_var("gallery", "resize_size") != $resize_size) {
+        graphics::remove_rule("gallery", "resize", "gallery_graphics::resize");
+        graphics::add_rule(
+          "gallery", "resize", "gallery_graphics::resize",
+          array("width" => $resize_size, "height" => $resize_size, "master" => Image::AUTO),
+          100);
+        module::set_var("gallery", "resize_size", $resize_size);
+      }
+
+      module::set_var("gallery", "header_text", $form->edit_theme->header_text->value);
+      module::set_var("gallery", "footer_text", $form->edit_theme->footer_text->value);
+      module::set_var("gallery", "show_credits", $form->edit_theme->show_credits->value);
+      module::set_var("gallery", "favicon_url", $form->edit_theme->favicon_url->value);
+      module::set_var("gallery", "apple_touch_icon_url", $form->edit_theme->apple_touch_icon_url->value);
+
+      module::event("theme_edit_form_completed", $form);
+
+      message::success(t("Updated theme details"));
+      url::redirect("admin/theme_options");
+    } else {
+      $view = new Admin_View("admin.html");
+      $view->content = new View("admin_theme_options.html");
+      $view->content->form = $form;
+      print $view;
+    }
+  }
+
+  private function _get_edit_form_admin() {
+    $form = new Forge("admin/theme_options/save/", "", null, array("id" =>"g-theme-options-form"));
+    $group = $form->group("edit_theme")->label(t("Theme layout"));
+    $group->input("page_size")->label(t("Items per page"))->id("g-page-size")
+      ->rules("required|valid_digit")
+      ->callback(array($this, "_valididate_page_size"))
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->error_messages("valid_min_value", t("The value must be greater than zero"))
+      ->value(module::get_var("gallery", "page_size"));
+    $group->input("thumb_size")->label(t("Thumbnail size (in pixels)"))->id("g-thumb-size")
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("gallery", "thumb_size"));
+    $group->input("resize_size")->label(t("Resized image size (in pixels)"))->id("g-resize-size")
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("gallery", "resize_size"));
+    $group->input("favicon_url")->label(t("URL (or relative path) to your favicon.ico"))
+      ->id("g-favicon")
+      ->value(module::get_var("gallery", "favicon_url"));
+    $group->input("apple_touch_icon_url")->label(t("URL (or relative path) to your Apple Touch icon"))
+      ->id("g-apple-touch")
+      ->value(module::get_var("gallery", "apple_touch_icon_url"));
+    $group->textarea("header_text")->label(t("Header text"))->id("g-header-text")
+      ->value(module::get_var("gallery", "header_text"));
+    $group->textarea("footer_text")->label(t("Footer text"))->id("g-footer-text")
+      ->value(module::get_var("gallery", "footer_text"));
+    $group->checkbox("show_credits")->label(t("Show site credits"))->id("g-footer-text")
+      ->checked(module::get_var("gallery", "show_credits"));
+
+    module::event("theme_edit_form", $form);
+
+    $group->submit("")->value(t("Save"));
+    return $form;
+  }
+
+  function _valididate_page_size($input) {
+    if ($input->value < 1) {
+      $input->add_error("valid_min_value", true);
+    }
+
+  }
+}
+
diff --git a/modules/gallery/controllers/admin_themes.php b/modules/gallery/controllers/admin_themes.php
new file mode 100644
index 0000000..4ab994f
--- /dev/null
+++ b/modules/gallery/controllers/admin_themes.php
@@ -0,0 +1,80 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Themes_Controller extends Admin_Controller {
+  public function index() {
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Theme choice");
+    $view->content = new View("admin_themes.html");
+    $view->content->admin = module::get_var("gallery", "active_admin_theme");
+    $view->content->site = module::get_var("gallery", "active_site_theme");
+    $view->content->themes = $this->_get_themes();
+
+    site_status::clear("missing_site_theme");
+    site_status::clear("missing_admin_theme");
+    print $view;
+  }
+
+  private function _get_themes() {
+    $themes = array();
+    foreach (scandir(THEMEPATH) as $theme_name) {
+      if ($theme_name[0] == ".") {
+        continue;
+      }
+      $theme_name = preg_replace("/[^a-zA-Z0-9\._-]/", "", $theme_name);
+      if (file_exists(THEMEPATH . "$theme_name/theme.info")) {
+
+        $themes[$theme_name] = theme::get_info($theme_name);
+      }
+    }
+    return $themes;
+  }
+
+  public function preview($type, $theme_name) {
+    $view = new View("admin_themes_preview.html");
+    $view->info = theme::get_info($theme_name);
+    $view->theme_name = t($theme_name);
+    $view->type = $type;
+    if ($type == "admin") {
+      $view->url = url::site("admin?theme=$theme_name");
+    } else {
+      $view->url = item::root()->url("theme=$theme_name");
+    }
+    print $view;
+  }
+
+  public function choose($type, $theme_name) {
+    access::verify_csrf();
+
+    $info = theme::get_info($theme_name);
+
+    if ($type == "admin" && $info->admin) {
+      module::set_var("gallery", "active_admin_theme", $theme_name);
+      message::success(t("Successfully changed your admin theme to <b>%theme_name</b>",
+                         array("theme_name" => $info->name)));
+    } else if ($type == "site" && $info->site) {
+      module::set_var("gallery", "active_site_theme", $theme_name);
+      message::success(t("Successfully changed your Gallery theme to <b>%theme_name</b>",
+                         array("theme_name" => $info->name)));
+    }
+
+    url::redirect("admin/themes");
+  }
+}
+
diff --git a/modules/gallery/controllers/admin_upgrade_checker.php b/modules/gallery/controllers/admin_upgrade_checker.php
new file mode 100644
index 0000000..3f0bdac
--- /dev/null
+++ b/modules/gallery/controllers/admin_upgrade_checker.php
@@ -0,0 +1,57 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Upgrade_Checker_Controller extends Admin_Controller {
+  function check_now() {
+    access::verify_csrf();
+    upgrade_checker::fetch_version_info();
+    $message = upgrade_checker::get_upgrade_message();
+    if ($message) {
+      $message .= t(
+        " <a href=\"%hide-url\"><i>(remind me later)</i></a>",
+        array("hide-url" => url::site("admin/upgrade_checker/remind_me_later?csrf=__CSRF__")));
+      site_status::info($message, "upgrade_checker");
+    } else {
+      site_status::clear("upgrade_checker");
+    }
+    url::redirect("admin/dashboard");
+  }
+
+  function remind_me_later() {
+    access::verify_csrf();
+    site_status::clear("upgrade_checker");
+    if ($referer = Input::instance()->server("HTTP_REFERER")) {
+      url::redirect($referer);
+    } else {
+      url::redirect(item::root()->abs_url());
+    }
+  }
+
+  function set_auto($val) {
+    access::verify_csrf();
+    module::set_var("gallery", "upgrade_checker_auto_enabled", (bool)$val);
+
+    if ((bool)$val) {
+      message::success(t("Automatic upgrade checking is enabled."));
+    } else {
+      message::success(t("Automatic upgrade checking is disabled."));
+    }
+    url::redirect("admin/dashboard");
+  }
+}
diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php
new file mode 100644
index 0000000..0fb033a
--- /dev/null
+++ b/modules/gallery/controllers/albums.php
@@ -0,0 +1,207 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Albums_Controller extends Items_Controller {
+  public function index() {
+    $this->show(ORM::factory("item", 1));
+  }
+
+  public function show($album) {
+    if (!is_object($album)) {
+      // show() must be public because we route to it in url::parse_url(), so make
+      // sure that we're actually receiving an object
+      throw new Kohana_404_Exception();
+    }
+
+    access::required("view", $album);
+
+    $page_size = module::get_var("gallery", "page_size", 9);
+    $input = Input::instance();
+    $show = $input->get("show");
+
+    if ($show) {
+      $child = ORM::factory("item", $show);
+      $index = item::get_position($child);
+      if ($index) {
+        $page = ceil($index / $page_size);
+        if ($page == 1) {
+          url::redirect($album->abs_url());
+        } else {
+          url::redirect($album->abs_url("page=$page"));
+        }
+      }
+    }
+
+    $page = $input->get("page", "1");
+    $children_count = $album->viewable()->children_count();
+    $offset = ($page - 1) * $page_size;
+    $max_pages = max(ceil($children_count / $page_size), 1);
+
+    // Make sure that the page references a valid offset
+    if ($page < 1) {
+      url::redirect($album->abs_url());
+    } else if ($page > $max_pages) {
+      url::redirect($album->abs_url("page=$max_pages"));
+    }
+
+    $template = new Theme_View("page.html", "collection", "album");
+    $template->set_global(
+      array("page" => $page,
+            "page_title" => null,
+            "max_pages" => $max_pages,
+            "page_size" => $page_size,
+            "item" => $album,
+            "children" => $album->viewable()->children($page_size, $offset),
+            "parents" => $album->parents()->as_array(), // view calls empty() on this
+            "breadcrumbs" => Breadcrumb::array_from_item_parents($album),
+            "children_count" => $children_count));
+    $template->content = new View("album.html");
+    $album->increment_view_count();
+
+    print $template;
+    item::set_display_context_callback("Albums_Controller::get_display_context");
+  }
+
+  static function get_display_context($item) {
+    $where = array(array("type", "!=", "album"));
+    $position = item::get_position($item, $where);
+    if ($position > 1) {
+      list ($previous_item, $ignore, $next_item) =
+        $item->parent()->viewable()->children(3, $position - 2, $where);
+    } else {
+      $previous_item = null;
+      list ($next_item) = $item->parent()->viewable()->children(1, $position, $where);
+    }
+
+    return array("position" => $position,
+                 "previous_item" => $previous_item,
+                 "next_item" => $next_item,
+                 "sibling_count" => $item->parent()->viewable()->children_count($where),
+                 "siblings_callback" => array("Albums_Controller::get_siblings", array($item)),
+                 "parents" => $item->parents()->as_array(),
+                 "breadcrumbs" => Breadcrumb::array_from_item_parents($item));
+  }
+
+  static function get_siblings($item, $limit=null, $offset=null) {
+    // @todo consider creating Item_Model::siblings() if we use this more broadly.
+    return $item->parent()->viewable()->children($limit, $offset);
+  }
+
+  public function create($parent_id) {
+    access::verify_csrf();
+    $album = ORM::factory("item", $parent_id);
+    access::required("view", $album);
+    access::required("add", $album);
+
+    $form = album::get_add_form($album);
+    try {
+      $valid = $form->validate();
+      $album = ORM::factory("item");
+      $album->type = "album";
+      $album->parent_id = $parent_id;
+      $album->name = $form->add_album->inputs["name"]->value;
+      $album->title = $form->add_album->title->value ?
+        $form->add_album->title->value : $form->add_album->inputs["name"]->value;
+      $album->description = $form->add_album->description->value;
+      $album->slug = $form->add_album->slug->value;
+      $album->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        $form->add_album->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      $album->save();
+      module::event("album_add_form_completed", $album, $form);
+      log::success("content", "Created an album",
+                   html::anchor("albums/$album->id", "view album"));
+      message::success(t("Created album %album_title",
+                         array("album_title" => html::purify($album->title))));
+
+      json::reply(array("result" => "success", "location" => $album->url()));
+    } else {
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function update($album_id) {
+    access::verify_csrf();
+    $album = ORM::factory("item", $album_id);
+    access::required("view", $album);
+    access::required("edit", $album);
+
+    $form = album::get_edit_form($album);
+    try {
+      $valid = $form->validate();
+      $album->title = $form->edit_item->title->value;
+      $album->description = $form->edit_item->description->value;
+      $album->sort_column = $form->edit_item->sort_order->column->value;
+      $album->sort_order = $form->edit_item->sort_order->direction->value;
+      if (array_key_exists("name", $form->edit_item->inputs)) {
+        $album->name = $form->edit_item->inputs["name"]->value;
+      }
+      $album->slug = $form->edit_item->slug->value;
+      $album->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        $form->edit_item->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      $album->save();
+      module::event("item_edit_form_completed", $album, $form);
+
+      log::success("content", "Updated album", "<a href=\"albums/$album->id\">view</a>");
+      message::success(t("Saved album %album_title",
+                         array("album_title" => html::purify($album->title))));
+
+      if ($form->from_id->value == $album->id) {
+        // Use the new url; it might have changed.
+        json::reply(array("result" => "success", "location" => $album->url()));
+      } else {
+        // Stay on the same page
+        json::reply(array("result" => "success"));
+      }
+    } else {
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function form_add($album_id) {
+    $album = ORM::factory("item", $album_id);
+    access::required("view", $album);
+    access::required("add", $album);
+
+    print album::get_add_form($album);
+  }
+
+  public function form_edit($album_id) {
+    $album = ORM::factory("item", $album_id);
+    access::required("view", $album);
+    access::required("edit", $album);
+
+    print album::get_edit_form($album);
+  }
+}
diff --git a/modules/gallery/controllers/combined.php b/modules/gallery/controllers/combined.php
new file mode 100644
index 0000000..3cf7f87
--- /dev/null
+++ b/modules/gallery/controllers/combined.php
@@ -0,0 +1,96 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Combined_Controller extends Controller {
+  const ALLOW_MAINTENANCE_MODE = true;
+  const ALLOW_PRIVATE_GALLERY = true;
+
+  /**
+   * Return the combined Javascript bundle associated with the given key.
+   */
+  public function javascript($key) {
+    return $this->_emit("javascript", $key);
+  }
+
+  /**
+   * Return the combined CSS bundle associated with the given key.
+   */
+  public function css($key) {
+    return $this->_emit("css", $key);
+  }
+
+  /**
+   * Print out a cached entry.
+   * @param string   the combined entry type (either "javascript" or "css")
+   * @param string   the key (typically an md5 sum)
+   */
+  private function _emit($type, $key) {
+    $input = Input::instance();
+
+    // We don't need to save the session for this request
+    Session::instance()->abort_save();
+
+    // Our data is immutable, so if they already have a copy then it needs no updating.
+    if ($input->server("HTTP_IF_MODIFIED_SINCE")) {
+      header('HTTP/1.0 304 Not Modified');
+      header("Expires: Tue, 19 Jan 2038 00:00:00 GMT");
+      header("Cache-Control: public,max-age=2678400");
+      header('Pragma: public');
+      Kohana::close_buffers(false);
+      return "";
+    }
+
+    if (empty($key)) {
+      throw new Kohana_404_Exception();
+    }
+
+    $cache = Cache::instance();
+    $use_gzip = function_exists("gzencode") &&
+      stripos($input->server("HTTP_ACCEPT_ENCODING"), "gzip") !== false &&
+      (int) ini_get("zlib.output_compression") === 0;
+
+    if ($use_gzip && $content = $cache->get("{$key}_gz")) {
+      header("Content-Encoding: gzip");
+      header("Vary: Accept-Encoding");
+    } else {
+      // Fall back to non-gzipped if we have to
+      $content = $cache->get($key);
+    }
+    if (empty($content)) {
+      throw new Kohana_404_Exception();
+    }
+
+    // $type is either 'javascript' or 'css'
+    if ($type == "javascript") {
+      header("Content-Type: application/javascript; charset=UTF-8");
+    } else {
+      header("Content-Type: text/css; charset=UTF-8");
+    }
+    header("Expires: Tue, 19 Jan 2038 00:00:00 GMT");
+    header("Cache-Control: public,max-age=2678400");
+    header("Pragma: public");
+    header("Last-Modified: " . gmdate("D, d M Y H:i:s T", time()));
+    header("Content-Length: " . strlen($content));
+
+    Kohana::close_buffers(false);
+    print $content;
+  }
+
+}
+
diff --git a/modules/gallery/controllers/file_proxy.php b/modules/gallery/controllers/file_proxy.php
new file mode 100644
index 0000000..34f6b8c
--- /dev/null
+++ b/modules/gallery/controllers/file_proxy.php
@@ -0,0 +1,174 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+/**
+ * Proxy access to files in var/albums and var/resizes, making sure that the session user has
+ * access to view these files.
+ *
+ * Security Philosophy: we do not use the information provided to find if the file exists on
+ * disk.  We use this information only to locate the correct item in the database and then we
+ * *only* use information from the database to find and proxy the correct file.  This way all user
+ * input is sanitized against the database before we perform any file I/O.
+ */
+class File_Proxy_Controller extends Controller {
+  const ALLOW_PRIVATE_GALLERY = true;
+  public function __call($function, $args) {
+
+    // Force zlib compression off.  Image and movie files are already compressed and
+    // recompressing them is CPU intensive.
+    if (ini_get("zlib.output_compression")) {
+      ini_set("zlib.output_compression", "Off");
+    }
+
+    // request_uri: gallery3/var/albums/foo/bar.jpg?m=1234
+    $request_uri = rawurldecode(Input::instance()->server("REQUEST_URI"));
+
+    // get rid of query parameters
+    // request_uri: gallery3/var/albums/foo/bar.jpg
+    $request_uri = preg_replace("/\?.*/", "", $request_uri);
+
+    // var_uri: gallery3/var/
+    $var_uri = url::file("var/");
+
+    // Make sure that the request is for a file inside var
+    $offset = strpos(rawurldecode($request_uri), $var_uri);
+    if ($offset !== 0) {
+      $e = new Kohana_404_Exception();
+      $e->test_fail_code = 1;
+      throw $e;
+    }
+
+    // file_uri: albums/foo/bar.jpg
+    $file_uri = substr($request_uri, strlen($var_uri));
+
+    // type: albums
+    // path: foo/bar.jpg
+    list ($type, $path) = explode("/", $file_uri, 2);
+    if ($type != "resizes" && $type != "albums" && $type != "thumbs") {
+      $e = new Kohana_404_Exception();
+      $e->test_fail_code = 2;
+      throw $e;
+    }
+
+    // If the last element is .album.jpg, pop that off since it's not a real item
+    $path = preg_replace("|/.album.jpg$|", "", $path);
+
+    $item = item::find_by_path($path);
+    if (!$item->loaded()) {
+      // We didn't turn it up. If we're looking for a .jpg then it's it's possible that we're
+      // requesting the thumbnail for a movie.  In that case, the movie file would
+      // have been converted to a .jpg. So try some alternate types:
+      if (preg_match('/.jpg$/', $path)) {
+        foreach (legal_file::get_movie_extensions() as $ext) {
+          $movie_path = preg_replace('/.jpg$/', ".$ext", $path);
+          $item = item::find_by_path($movie_path);
+          if ($item->loaded()) {
+            break;
+          }
+        }
+      }
+    }
+
+    if (!$item->loaded()) {
+      $e = new Kohana_404_Exception();
+      $e->test_fail_code = 3;
+      throw $e;
+    }
+
+    // Make sure we have access to the item
+    if (!access::can("view", $item)) {
+      $e = new Kohana_404_Exception();
+      $e->test_fail_code = 4;
+      throw $e;
+    }
+
+    // Make sure we have view_full access to the original
+    if ($type == "albums" && !access::can("view_full", $item)) {
+      $e = new Kohana_404_Exception();
+      $e->test_fail_code = 5;
+      throw $e;
+    }
+
+    // Don't try to load a directory
+    if ($type == "albums" && $item->is_album()) {
+      $e = new Kohana_404_Exception();
+      $e->test_fail_code = 6;
+      throw $e;
+    }
+
+    // Note: this code is roughly duplicated in data_rest, so if you modify this, please look to
+    // see if you should make the same change there as well.
+
+    if ($type == "albums") {
+      $file = $item->file_path();
+    } else if ($type == "resizes") {
+      $file = $item->resize_path();
+    } else {
+      $file = $item->thumb_path();
+    }
+
+    if (!file_exists($file)) {
+      $e = new Kohana_404_Exception();
+      $e->test_fail_code = 7;
+      throw $e;
+    }
+
+    if (gallery::show_profiler()) {
+      Profiler::enable();
+      $profiler = new Profiler();
+      $profiler->render();
+      exit;
+    }
+
+    header("Content-Length: " . filesize($file));
+
+    header("Pragma:");
+    // Check that the content hasn't expired or it wasn't changed since cached
+    expires::check(2592000, $item->updated);
+
+    // We don't need to save the session for this request
+    Session::instance()->abort_save();
+
+    expires::set(2592000, $item->updated);  // 30 days
+
+    // Dump out the image.  If the item is a movie or album, then its thumbnail will be a JPG.
+    if (($item->is_movie() || $item->is_album()) && $type == "thumbs") {
+      header("Content-Type: image/jpeg");
+    } else {
+      header("Content-Type: $item->mime_type");
+    }
+
+    if (TEST_MODE) {
+      return $file;
+    } else {
+      // Don't use Kohana::close_buffers(false) here because that only closes all the buffers
+      // that Kohana started.  We want to close *all* buffers at this point because otherwise we're
+      // going to buffer up whatever file we're proxying (and it may be very large).  This may
+      // affect embedding or systems with PHP's output_buffering enabled.
+      while (ob_get_level()) {
+        if (!@ob_end_clean()) {
+          // ob_end_clean() can return false if the buffer can't be removed for some reason
+          // (zlib output compression buffers sometimes cause problems).
+          break;
+        }
+      }
+      readfile($file);
+    }
+  }
+}
diff --git a/modules/gallery/controllers/items.php b/modules/gallery/controllers/items.php
new file mode 100644
index 0000000..845df76
--- /dev/null
+++ b/modules/gallery/controllers/items.php
@@ -0,0 +1,43 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Items_Controller extends Controller {
+  public function __call($function, $args) {
+    $item = ORM::factory("item", (int)$function);
+    if (!$item->loaded()) {
+      throw new Kohana_404_Exception();
+    }
+
+    // Redirect to the more specific resource type, since it will render differently.  We can't
+    // delegate here because we may have gotten to this page via /items/<id> which means that we
+    // don't have a type-specific controller.  Also, we want to drive a single canonical resource
+    // mapping where possible.
+    access::required("view", $item);
+    url::redirect($item->abs_url());
+  }
+
+  // Return the width/height dimensions for the given item
+  public function dimensions($id) {
+    $item = ORM::factory("item", $id);
+    access::required("view", $item);
+    json::reply(array("thumb" => array((int)$item->thumb_width, (int)$item->thumb_height),
+                      "resize" => array((int)$item->resize_width, (int)$item->resize_height),
+                      "full" => array((int)$item->width, (int)$item->height)));
+  }
+}
diff --git a/modules/gallery/controllers/l10n_client.php b/modules/gallery/controllers/l10n_client.php
new file mode 100644
index 0000000..993dfb3
--- /dev/null
+++ b/modules/gallery/controllers/l10n_client.php
@@ -0,0 +1,179 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class L10n_Client_Controller extends Controller {
+  public function save() {
+    access::verify_csrf();
+    if (!identity::active_user()->admin) {
+      access::forbidden();
+    }
+
+    $locale = Gallery_I18n::instance()->locale();
+    $input = Input::instance();
+    $key = $input->post("l10n-message-key");
+
+    $root_message = ORM::factory("incoming_translation")
+      ->where("key", "=", $key)
+      ->where("locale", "=", "root")
+      ->find();
+
+    if (!$root_message->loaded()) {
+      throw new Exception("@todo bad request data / illegal state");
+    }
+    $is_plural = Gallery_I18n::is_plural_message(unserialize($root_message->message));
+
+    $is_empty = true;
+    if ($is_plural) {
+      $plural_forms = l10n_client::plural_forms($locale);
+      $translation = array();
+      foreach($plural_forms as $plural_form) {
+        $value = $input->post("l10n-edit-plural-translation-$plural_form");
+        if (null === $value || !is_string($value)) {
+          throw new Exception("@todo bad request data");
+        }
+        $translation[$plural_form] = $value;
+        $is_empty = $is_empty && empty($value);
+      }
+    } else {
+      $translation = $input->post("l10n-edit-translation");
+      $is_empty = empty($translation);
+      if (null === $translation || !is_string($translation)) {
+        throw new Exception("@todo bad request data");
+      }
+    }
+
+    $entry = ORM::factory("outgoing_translation")
+      ->where("key", "=", $key)
+      ->where("locale", "=", $locale)
+      ->find();
+
+    if ($is_empty) {
+      if ($entry->loaded()) {
+        $entry->delete();
+      }
+    } else {
+      if (!$entry->loaded()) {
+        $entry->key = $key;
+        $entry->locale = $locale;
+        $entry->message = $root_message->message;
+        $entry->base_revision = null;
+      }
+
+      $entry->translation = serialize($translation);
+
+      $entry_from_incoming = ORM::factory("incoming_translation")
+        ->where("key", "=", $key)
+        ->where("locale", "=", $locale)
+        ->find();
+
+      if (!$entry_from_incoming->loaded()) {
+        $entry->base_revision = $entry_from_incoming->revision;
+      }
+
+      $entry->save();
+    }
+
+    Gallery_I18n::clear_cache($locale);
+
+    json::reply(new stdClass());
+  }
+
+  public function toggle_l10n_mode() {
+    access::verify_csrf();
+    if (!identity::active_user()->admin) {
+      access::forbidden();
+    }
+
+    $session = Session::instance();
+    $l10n_mode = $session->get("l10n_mode", false);
+    $session->set("l10n_mode", !$l10n_mode);
+
+    $redirect_url = "admin/languages";
+    if (!$l10n_mode) {
+      $redirect_url .= "#l10n-client";
+    }
+
+    url::redirect($redirect_url);
+  }
+
+  private static function _l10n_client_search_form() {
+    $form = new Forge("#", "", "post", array("id" => "g-l10n-search-form"));
+    $group = $form->group("l10n_search");
+    $group->input("l10n-search")->id("g-l10n-search");
+
+    return $form;
+  }
+
+  public static function l10n_form() {
+    if (Input::instance()->get("show_all_l10n_messages")) {
+      $calls = array();
+      foreach (db::build()
+               ->select("key", "message")
+               ->from("incoming_translations")
+               ->where("locale", "=", "root")
+               ->execute() as $row) {
+        $calls[$row->key] = array(unserialize($row->message), array());
+      }
+    } else {
+      $calls = Gallery_I18n::instance()->call_log();
+    }
+    $locale = Gallery_I18n::instance()->locale();
+
+    if ($calls) {
+      $translations = array();
+      foreach (db::build()
+               ->select("key", "translation")
+               ->from("incoming_translations")
+               ->where("locale", "=", $locale)
+               ->execute() as $row) {
+        $translations[$row->key] = unserialize($row->translation);
+      }
+      // Override incoming with outgoing...
+      foreach (db::build()
+               ->select("key", "translation")
+               ->from("outgoing_translations")
+               ->where("locale", "=", $locale)
+               ->execute() as $row) {
+        $translations[$row->key] = unserialize($row->translation);
+      }
+
+      $string_list = array();
+      $cache = array();
+      foreach ($calls as $key => $call) {
+        list ($message, $options) = $call;
+        // Ensure that the message is in the DB
+        l10n_scanner::process_message($message, $cache);
+        // Note: Not interpolating placeholders for the actual translation input field.
+        // TODO: Might show a preview w/ interpolations (using $options)
+        $translation = isset($translations[$key]) ? $translations[$key] : '';
+        $string_list[] = array('source' => $message,
+                               'key' => $key,
+                               'translation' => $translation);
+      }
+
+      $v = new View('l10n_client.html');
+      $v->string_list = $string_list;
+      $v->l10n_search_form = self::_l10n_client_search_form();
+      $v->plural_forms = l10n_client::plural_forms($locale);
+      return $v;
+    }
+
+    return '';
+  }
+}
diff --git a/modules/gallery/controllers/login.php b/modules/gallery/controllers/login.php
new file mode 100644
index 0000000..9da575b
--- /dev/null
+++ b/modules/gallery/controllers/login.php
@@ -0,0 +1,90 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Login_Controller extends Controller {
+  const ALLOW_MAINTENANCE_MODE = true;
+  const ALLOW_PRIVATE_GALLERY = true;
+
+  public function ajax() {
+    $view = new View("login_ajax.html");
+    $view->form = auth::get_login_form("login/auth_ajax");
+    print $view;
+  }
+
+  public function auth_ajax() {
+    access::verify_csrf();
+
+    list ($valid, $form) = $this->_auth("login/auth_ajax");
+    if ($valid) {
+      json::reply(array("result" => "success"));
+    } else {
+      $view = new View("login_ajax.html");
+      $view->form = $form;
+      json::reply(array("result" => "error", "html" => (string)$view));
+    }
+  }
+
+  public function html() {
+    $view = new Theme_View("page.html", "other", "login");
+    $view->page_title = t("Log in to Gallery");
+    $view->content = new View("login_ajax.html");
+    $view->content->form = auth::get_login_form("login/auth_html");
+    print $view;
+  }
+
+  public function auth_html() {
+    access::verify_csrf();
+
+    list ($valid, $form) = $this->_auth("login/auth_html");
+    if ($valid) {
+      $continue_url = $form->continue_url->value;
+      url::redirect($continue_url ? $continue_url : item::root()->abs_url());
+    } else {
+      $view = new Theme_View("page.html", "other", "login");
+      $view->page_title = t("Log in to Gallery");
+      $view->content = new View("login_ajax.html");
+      $view->content->form = $form;
+      print $view;
+    }
+  }
+
+  private function _auth($url) {
+    $form = auth::get_login_form($url);
+    $valid = $form->validate();
+    if ($valid) {
+      $user = identity::lookup_user_by_name($form->login->inputs["name"]->value);
+      if (empty($user) || !identity::is_correct_password($user, $form->login->password->value)) {
+        $form->login->inputs["name"]->add_error("invalid_login", 1);
+        $name = $form->login->inputs["name"]->value;
+        log::warning("user", t("Failed login for %name", array("name" => $name)));
+        module::event("user_auth_failed", $name);
+        $valid = false;
+      }
+    }
+
+    if ($valid) {
+      auth::login($user);
+    }
+
+    // Either way, regenerate the session id to avoid session trapping
+    Session::instance()->regenerate();
+
+    return array($valid, $form);
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/controllers/logout.php b/modules/gallery/controllers/logout.php
new file mode 100644
index 0000000..9a24d1b
--- /dev/null
+++ b/modules/gallery/controllers/logout.php
@@ -0,0 +1,29 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Logout_Controller extends Controller {
+  public function index() {
+    access::verify_csrf();
+    auth::logout();
+    if ($continue_url = Input::instance()->get("continue_url")) {
+      url::redirect($continue_url);
+    }
+    url::redirect(item::root()->abs_url());
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/controllers/movies.php b/modules/gallery/controllers/movies.php
new file mode 100644
index 0000000..5607571
--- /dev/null
+++ b/modules/gallery/controllers/movies.php
@@ -0,0 +1,91 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Movies_Controller extends Items_Controller {
+  public function show($movie) {
+    if (!is_object($movie)) {
+      // show() must be public because we route to it in url::parse_url(), so make
+      // sure that we're actually receiving an object
+      throw new Kohana_404_Exception();
+    }
+
+    access::required("view", $movie);
+
+    $template = new Theme_View("page.html", "item", "movie");
+    $template->set_global(array("item" => $movie,
+                                "children" => array(),
+                                "children_count" => 0));
+    $template->set_global(item::get_display_context($movie));
+    $template->content = new View("movie.html");
+
+    $movie->increment_view_count();
+
+    print $template;
+  }
+
+  public function update($movie_id) {
+    access::verify_csrf();
+    $movie = ORM::factory("item", $movie_id);
+    access::required("view", $movie);
+    access::required("edit", $movie);
+
+    $form = movie::get_edit_form($movie);
+    try {
+      $valid = $form->validate();
+      $movie->title = $form->edit_item->title->value;
+      $movie->description = $form->edit_item->description->value;
+      $movie->slug = $form->edit_item->slug->value;
+      $movie->name = $form->edit_item->inputs["name"]->value;
+      $movie->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        $form->edit_item->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      $movie->save();
+      module::event("item_edit_form_completed", $movie, $form);
+
+      log::success("content", "Updated movie", "<a href=\"{$movie->url()}\">view</a>");
+      message::success(
+        t("Saved movie %movie_title", array("movie_title" => html::purify($movie->title))));
+
+      if ($form->from_id->value == $movie->id) {
+        // Use the new url; it might have changed.
+        json::reply(array("result" => "success", "location" => $movie->url()));
+      } else {
+        // Stay on the same page
+        json::reply(array("result" => "success"));
+      }
+    } else {
+      json::reply(array("result" => "error", "html" => (string) $form));
+    }
+  }
+
+  public function form_edit($movie_id) {
+    $movie = ORM::factory("item", $movie_id);
+    access::required("view", $movie);
+    access::required("edit", $movie);
+
+    print movie::get_edit_form($movie);
+  }
+}
diff --git a/modules/gallery/controllers/packager.php b/modules/gallery/controllers/packager.php
new file mode 100644
index 0000000..d7e3cf4
--- /dev/null
+++ b/modules/gallery/controllers/packager.php
@@ -0,0 +1,191 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Packager_Controller extends Controller {
+  function package() {
+    if (PHP_SAPI != "cli") {
+      access::forbidden();
+    }
+
+    $_SERVER["HTTP_HOST"] = "example.com";
+
+    try {
+      $this->_reset();                // empty and reinstall the standard modules
+      $this->_dump_database();        // Dump the database
+      $this->_dump_var();             // Dump the var directory
+    } catch (Exception $e) {
+      print $e->getMessage() . "\n" . $e->getTraceAsString();
+      return;
+    }
+
+    print "Successfully wrote install.sql and init_var.php\n";
+  }
+
+  private function _reset() {
+    // Drop all tables
+    foreach (Database::instance()->list_tables() as $table) {
+      Database::instance()->query("DROP TABLE IF EXISTS {{$table}}");
+    }
+
+    // Clean out data
+    dir::unlink(VARPATH . "uploads");
+    dir::unlink(VARPATH . "albums");
+    dir::unlink(VARPATH . "resizes");
+    dir::unlink(VARPATH . "thumbs");
+    dir::unlink(VARPATH . "modules");
+    dir::unlink(VARPATH . "tmp");
+
+    Database::instance()->clear_cache();
+    module::$modules = array();
+    module::$active = array();
+
+    // Use a known random seed so that subsequent packaging runs will reuse the same random
+    // numbers, keeping our install.sql file more stable.
+    srand(0);
+
+    foreach (array("gallery", "user", "comment", "organize", "info",
+                   "rss", "search", "slideshow", "tag") as $module_name) {
+      module::install($module_name);
+      module::activate($module_name);
+    }
+  }
+
+  private function _dump_database() {
+    // We now have a clean install with just the packages that we want.  Make sure that the
+    // database is clean too.
+    $i = 1;
+    foreach (array("dashboard_sidebar", "dashboard_center", "site_sidebar") as $key) {
+      $blocks = array();
+      foreach (unserialize(module::get_var("gallery", "blocks_{$key}")) as $rnd => $value) {
+        $blocks[++$i] = $value;
+      }
+      module::set_var("gallery", "blocks_{$key}", serialize($blocks));
+    }
+
+    Database::instance()->query("TRUNCATE {caches}");
+    Database::instance()->query("TRUNCATE {sessions}");
+    Database::instance()->query("TRUNCATE {logs}");
+    db::build()->update("users")
+      ->set(array("password" => ""))
+      ->where("id", "in", array(1, 2))
+      ->execute();
+
+    $dbconfig = Kohana::config('database.default');
+    $conn = $dbconfig["connection"];
+    $sql_file = DOCROOT . "installer/install.sql";
+    if (!is_writable($sql_file)) {
+      print "$sql_file is not writeable";
+      return;
+    }
+    $command = sprintf(
+      "mysqldump --compact --skip-extended-insert --add-drop-table %s %s %s %s > $sql_file",
+      escapeshellarg("-h{$conn['host']}"),
+      escapeshellarg("-u{$conn['user']}"),
+      $conn['pass'] ? escapeshellarg("-p{$conn['pass']}") : "",
+      escapeshellarg($conn['database']));
+    exec($command, $output, $status);
+    if ($status) {
+      print "<pre>";
+      print "$command\n";
+      print "Failed to dump database\n";
+      print implode("\n", $output);
+      return;
+    }
+
+    // Post-process the sql file
+    $buf = "";
+    $root = ORM::factory("item", 1);
+    $root_created_timestamp = $root->created;
+    $root_updated_timestamp = $root->updated;
+    $table_name = "";
+    foreach (file($sql_file) as $line) {
+      // Prefix tables
+      $line = preg_replace(
+        "/(CREATE TABLE|IF EXISTS|INSERT INTO) `{$dbconfig['table_prefix']}(\w+)`/", "\\1 {\\2}",
+        $line);
+
+      if (preg_match("/CREATE TABLE {(\w+)}/", $line, $matches)) {
+        $table_name = $matches[1];
+      }
+      // Normalize dates
+      $line = preg_replace("/,$root_created_timestamp,/", ",UNIX_TIMESTAMP(),", $line);
+      $line = preg_replace("/,$root_updated_timestamp,/", ",UNIX_TIMESTAMP(),", $line);
+
+      // Remove ENGINE= specifications execpt for search records, it always needs to be MyISAM
+      if ($table_name != "search_records") {
+        $line = preg_replace("/ENGINE=\S+ /", "", $line);
+      }
+
+      // Null out ids in the vars table since it's an auto_increment table and this will result in
+      // more stable values so we'll have less churn in install.sql.
+      $line = preg_replace(
+        "/^INSERT INTO {vars} VALUES \(\d+/", "INSERT INTO {vars} VALUES (NULL", $line);
+
+      $buf .= $line;
+    }
+    $fd = fopen($sql_file, "wb");
+    fwrite($fd, $buf);
+    fclose($fd);
+  }
+
+  private function _dump_var() {
+    $objects = new RecursiveIteratorIterator(
+      new RecursiveDirectoryIterator(VARPATH),
+      RecursiveIteratorIterator::SELF_FIRST);
+
+    $var_file = DOCROOT . "installer/init_var.php";
+    if (!is_writable($var_file)) {
+      print "$var_file is not writeable";
+      return;
+    }
+
+    $paths = array();
+    foreach($objects as $name => $file){
+      $path = $file->getPath();
+      $basename = $file->getBasename();
+      if ($basename == "database.php" || $basename == "." || $basename == "..") {
+        continue;
+      } else if (basename($path) == "logs" && $basename != ".htaccess") {
+        continue;
+      }
+
+      if ($file->isDir()) {
+        $paths[] = "VARPATH . \"" . substr($name, strlen(VARPATH)) . "\"";
+      } else {
+        // @todo: serialize non-directories
+        $files["VARPATH . \"" . substr($name, strlen(VARPATH)) . "\""] =
+          base64_encode(file_get_contents($name));
+      }
+    }
+    // Sort the paths so that the var file is stable
+    sort($paths);
+
+    $fd = fopen($var_file, "w");
+    fwrite($fd, "<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n");
+    fwrite($fd, "<?php\n");
+    foreach ($paths as $path) {
+      fwrite($fd, "!file_exists($path) && mkdir($path);\n");
+    }
+    ksort($files);
+    foreach ($files as $file => $contents) {
+      fwrite($fd, "file_put_contents($file, base64_decode(\"$contents\"));\n");
+    }
+    fclose($fd);
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/controllers/permissions.php b/modules/gallery/controllers/permissions.php
new file mode 100644
index 0000000..2513f86
--- /dev/null
+++ b/modules/gallery/controllers/permissions.php
@@ -0,0 +1,91 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Permissions_Controller extends Controller {
+  function browse($id) {
+    $item = ORM::factory("item", $id);
+    access::required("view", $item);
+    access::required("edit", $item);
+
+    if (!$item->is_album()) {
+      access::forbidden();
+    }
+
+    $view = new View("permissions_browse.html");
+    $view->htaccess_works = access::htaccess_works();
+    $view->item = $item;
+    $view->parents = $item->parents();
+    $view->form = $this->_get_form($item);
+
+    print $view;
+  }
+
+  function form($id) {
+    $item = ORM::factory("item", $id);
+    access::required("view", $item);
+    access::required("edit", $item);
+
+    if (!$item->is_album()) {
+      access::forbidden();
+    }
+
+    print $this->_get_form($item);
+  }
+
+  function change($command, $group_id, $perm_id, $item_id) {
+    access::verify_csrf();
+
+    $group = identity::lookup_group($group_id);
+    $perm = ORM::factory("permission", $perm_id);
+    $item = ORM::factory("item", $item_id);
+    access::required("view", $item);
+    access::required("edit", $item);
+
+    if (!empty($group) && $perm->loaded() && $item->loaded()) {
+      switch($command) {
+      case "allow":
+        access::allow($group, $perm->name, $item);
+        break;
+
+      case "deny":
+        access::deny($group, $perm->name, $item);
+        break;
+
+      case "reset":
+        access::reset($group, $perm->name, $item);
+        break;
+      }
+
+      // If the active user just took away their own edit permissions, give it back.
+      if ($perm->name == "edit") {
+        if (!access::user_can(identity::active_user(), "edit", $item)) {
+          access::allow($group, $perm->name, $item);
+        }
+      }
+    }
+  }
+
+  private function _get_form($item) {
+    $view = new View("permissions_form.html");
+    $view->item = $item;
+    $view->groups = identity::groups();
+    $view->permissions = ORM::factory("permission")->find_all();
+    return $view;
+  }
+}
diff --git a/modules/gallery/controllers/photos.php b/modules/gallery/controllers/photos.php
new file mode 100644
index 0000000..96a22c5
--- /dev/null
+++ b/modules/gallery/controllers/photos.php
@@ -0,0 +1,91 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Photos_Controller extends Items_Controller {
+  public function show($photo) {
+    if (!is_object($photo)) {
+      // show() must be public because we route to it in url::parse_url(), so make
+      // sure that we're actually receiving an object
+      throw new Kohana_404_Exception();
+    }
+
+    access::required("view", $photo);
+
+    $template = new Theme_View("page.html", "item", "photo");
+    $template->set_global(array("item" => $photo,
+                                "children" => array(),
+                                "children_count" => 0));
+    $template->set_global(item::get_display_context($photo));
+    $template->content = new View("photo.html");
+
+    $photo->increment_view_count();
+
+    print $template;
+  }
+
+  public function update($photo_id) {
+    access::verify_csrf();
+    $photo = ORM::factory("item", $photo_id);
+    access::required("view", $photo);
+    access::required("edit", $photo);
+
+    $form = photo::get_edit_form($photo);
+    try {
+      $valid = $form->validate();
+      $photo->title = $form->edit_item->title->value;
+      $photo->description = $form->edit_item->description->value;
+      $photo->slug = $form->edit_item->slug->value;
+      $photo->name = $form->edit_item->inputs["name"]->value;
+      $photo->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        $form->edit_item->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      $photo->save();
+      module::event("item_edit_form_completed", $photo, $form);
+
+      log::success("content", "Updated photo", "<a href=\"{$photo->url()}\">view</a>");
+      message::success(
+        t("Saved photo %photo_title", array("photo_title" => html::purify($photo->title))));
+
+      if ($form->from_id->value == $photo->id) {
+        // Use the new url; it might have changed.
+        json::reply(array("result" => "success", "location" => $photo->url()));
+      } else {
+        // Stay on the same page
+        json::reply(array("result" => "success"));
+      }
+    } else {
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function form_edit($photo_id) {
+    $photo = ORM::factory("item", $photo_id);
+    access::required("view", $photo);
+    access::required("edit", $photo);
+
+    print photo::get_edit_form($photo);
+  }
+}
diff --git a/modules/gallery/controllers/quick.php b/modules/gallery/controllers/quick.php
new file mode 100644
index 0000000..4b21d9e
--- /dev/null
+++ b/modules/gallery/controllers/quick.php
@@ -0,0 +1,144 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Quick_Controller extends Controller {
+  public function rotate($id, $dir) {
+    access::verify_csrf();
+    $item = model_cache::get("item", $id);
+    access::required("view", $item);
+    access::required("edit", $item);
+
+    $degrees = 0;
+    switch($dir) {
+    case "ccw":
+      $degrees = -90;
+      break;
+
+    case "cw":
+      $degrees = 90;
+      break;
+    }
+
+    if ($degrees) {
+      $tmpfile = system::temp_filename("rotate",
+        pathinfo($item->file_path(), PATHINFO_EXTENSION));
+      gallery_graphics::rotate($item->file_path(), $tmpfile, array("degrees" => $degrees), $item);
+      $item->set_data_file($tmpfile);
+      $item->save();
+    }
+
+    if (Input::instance()->get("page_type") == "collection") {
+      json::reply(
+        array("src" => $item->thumb_url(),
+              "width" => $item->thumb_width,
+              "height" => $item->thumb_height));
+    } else {
+      json::reply(
+        array("src" => $item->resize_url(),
+              "width" => $item->resize_width,
+              "height" => $item->resize_height));
+    }
+  }
+
+  public function make_album_cover($id) {
+    access::verify_csrf();
+
+    $item = model_cache::get("item", $id);
+    access::required("view", $item);
+    access::required("view", $item->parent());
+    access::required("edit", $item->parent());
+
+    $msg = t("Made <b>%title</b> this album's cover", array("title" => html::purify($item->title)));
+
+    item::make_album_cover($item);
+    message::success($msg);
+
+    json::reply(array("result" => "success", "reload" => 1));
+  }
+
+  public function form_delete($id) {
+    $item = model_cache::get("item", $id);
+    access::required("view", $item);
+    access::required("edit", $item);
+
+    $v = new View("quick_delete_confirm.html");
+    $v->item = $item;
+    $v->form = item::get_delete_form($item);
+    print $v;
+  }
+
+  public function delete($id) {
+    access::verify_csrf();
+    $item = model_cache::get("item", $id);
+    access::required("view", $item);
+    access::required("edit", $item);
+
+    if ($item->is_album()) {
+      $msg = t("Deleted album <b>%title</b>", array("title" => html::purify($item->title)));
+    } else {
+      $msg = t("Deleted photo <b>%title</b>", array("title" => html::purify($item->title)));
+    }
+
+    $parent = $item->parent();
+
+    if ($item->is_album()) {
+      // Album delete will trigger deletes for all children.  Do this in a batch so that we can be
+      // smart about notifications, album cover updates, etc.
+      batch::start();
+      $item->delete();
+      batch::stop();
+    } else {
+      $item->delete();
+    }
+    message::success($msg);
+
+    $from_id = Input::instance()->get("from_id");
+    if (Input::instance()->get("page_type") == "collection" &&
+        $from_id != $id /* deleted the item we were viewing */) {
+      json::reply(array("result" => "success", "reload" => 1));
+    } else {
+      json::reply(array("result" => "success", "location" => $parent->url()));
+    }
+  }
+
+  public function form_edit($id) {
+    $item = model_cache::get("item", $id);
+    access::required("view", $item);
+    access::required("edit", $item);
+
+    switch ($item->type) {
+    case "album":
+      $form = album::get_edit_form($item);
+      break;
+
+    case "photo":
+      $form = photo::get_edit_form($item);
+      break;
+
+    case "movie":
+      $form = movie::get_edit_form($item);
+      break;
+    }
+
+    // Pass on the source item where this form was generated, so we have an idea where to return to.
+    $form->hidden("from_id")->value((int)Input::instance()->get("from_id", 0));
+
+    print $form;
+  }
+}
diff --git a/modules/gallery/controllers/reauthenticate.php b/modules/gallery/controllers/reauthenticate.php
new file mode 100644
index 0000000..c79b76e
--- /dev/null
+++ b/modules/gallery/controllers/reauthenticate.php
@@ -0,0 +1,105 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Reauthenticate_Controller extends Controller {
+  public function index() {
+    $is_ajax = Session::instance()->get_once("is_ajax_request", request::is_ajax());
+    if (!identity::active_user()->admin) {
+      if ($is_ajax) {
+        // We should never be able to get here since Admin_Controller::_reauth_check() won't work
+        // for non-admins.
+        access::forbidden();
+      } else {
+        url::redirect(item::root()->abs_url());
+      }
+    }
+
+    // On redirects from the admin controller, the ajax request indicator is lost,
+    // so we store it in the session.
+    if ($is_ajax) {
+      $v = new View("reauthenticate.html");
+      $v->form = self::_form();
+      $v->user_name = identity::active_user()->name;
+      print $v;
+    } else {
+      self::_show_form(self::_form());
+    }
+  }
+
+  public function auth() {
+    if (!identity::active_user()->admin) {
+      access::forbidden();
+    }
+    access::verify_csrf();
+
+    $form = self::_form();
+    $valid = $form->validate();
+    $user = identity::active_user();
+    if ($valid) {
+      module::event("user_auth", $user);
+      if (!request::is_ajax()) {
+        message::success(t("Successfully re-authenticated!"));
+      }
+      url::redirect(Session::instance()->get_once("continue_url"));
+    } else {
+      $name = $user->name;
+      log::warning("user", t("Failed re-authentication for %name", array("name" => $name)));
+      module::event("user_auth_failed", $name);
+      if (request::is_ajax()) {
+        $v = new View("reauthenticate.html");
+        $v->form = $form;
+        $v->user_name = identity::active_user()->name;
+        json::reply(array("html" => (string)$v));
+      } else {
+        self::_show_form($form);
+      }
+    }
+  }
+
+  private static function _show_form($form) {
+    $view = new Theme_View("page.html", "other", "reauthenticate");
+    $view->page_title = t("Re-authenticate");
+    $view->content = new View("reauthenticate.html");
+    $view->content->form = $form;
+    $view->content->user_name = identity::active_user()->name;
+
+    print $view;
+  }
+
+  private static function _form() {
+    $form = new Forge("reauthenticate/auth", "", "post", array("id" => "g-reauthenticate-form"));
+    $form->set_attr("class", "g-narrow");
+    $group = $form->group("reauthenticate")->label(t("Re-authenticate"));
+    $group->password("password")->label(t("Password"))->id("g-password")->class(null)
+      ->callback("auth::validate_too_many_failed_auth_attempts")
+      ->callback("Reauthenticate_Controller::valid_password")
+      ->error_messages("invalid_password", t("Incorrect password"))
+      ->error_messages(
+        "too_many_failed_auth_attempts",
+        t("Too many incorrect passwords.  Try again later"));
+    $group->submit("")->value(t("Submit"));
+    return $form;
+  }
+
+  static function valid_password($password_input) {
+    if (!identity::is_correct_password(identity::active_user(), $password_input->value)) {
+      $password_input->add_error("invalid_password", 1);
+    }
+  }
+}
diff --git a/modules/gallery/controllers/upgrader.php b/modules/gallery/controllers/upgrader.php
new file mode 100644
index 0000000..6b3a9ef
--- /dev/null
+++ b/modules/gallery/controllers/upgrader.php
@@ -0,0 +1,118 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Upgrader_Controller extends Controller {
+  public function index() {
+    $session = Session::instance();
+
+    // Make sure we have an upgrade token
+    if (!($upgrade_token = $session->get("upgrade_token", null))) {
+      $session->set("upgrade_token", $upgrade_token = random::hash());
+    }
+
+    // If the upgrade token exists, then bless this session
+    if (file_exists(TMPPATH . $upgrade_token)) {
+      $session->set("can_upgrade", true);
+      @unlink(TMPPATH . $upgrade_token);
+    }
+
+    $available_upgrades = 0;
+    foreach (module::available() as $module) {
+      if ($module->version && $module->version != $module->code_version) {
+        $available_upgrades++;
+      }
+    }
+
+    $failed = Input::instance()->get("failed");
+    $view = new View("upgrader.html");
+    $view->can_upgrade = identity::active_user()->admin || $session->get("can_upgrade");
+    $view->upgrade_token = $upgrade_token;
+    $view->available = module::available();
+    $view->failed = $failed ? explode(",", $failed) : array();
+    $view->done = $available_upgrades == 0;
+    $view->obsolete_modules_message = module::get_obsolete_modules_message();
+    print $view;
+  }
+
+  public function upgrade() {
+    if (php_sapi_name() == "cli") {
+      // @todo this may screw up some module installers, but we don't have a better answer at
+      // this time.
+      $_SERVER["HTTP_HOST"] = "example.com";
+    } else {
+      if (!identity::active_user()->admin && !Session::instance()->get("can_upgrade", false)) {
+        access::forbidden();
+      }
+
+      try {
+        access::verify_csrf();
+      } catch (Exception $e) {
+        url::redirect("upgrader");
+      }
+    }
+
+    $available = module::available();
+    // Upgrade gallery first
+    $gallery = $available["gallery"];
+    if ($gallery->code_version != $gallery->version) {
+      module::upgrade("gallery");
+      module::activate("gallery");
+    }
+
+    // Then upgrade the rest
+    $failed = array();
+    foreach (module::available() as $id => $module) {
+      if ($id == "gallery") {
+        continue;
+      }
+
+      if ($module->active && $module->code_version != $module->version) {
+        try {
+          module::upgrade($id);
+        } catch (Exception $e) {
+          // @todo assume it's MODULE_FAILED_TO_UPGRADE for now
+          $failed[] = $id;
+        }
+      }
+    }
+
+    // If the upgrade failed, this will get recreated
+    site_status::clear("upgrade_now");
+
+    // Clear any upgrade check strings, we are probably up to date.
+    site_status::clear("upgrade_checker");
+
+    if (php_sapi_name() == "cli") {
+      if ($failed) {
+        print "Upgrade completed ** WITH FAILURES **\n";
+        print "The following modules were not successfully upgraded:\n";
+        print "  " . implode($failed, "\n  ") . "\n";
+        print "Try getting newer versions or deactivating those modules\n";
+      } else {
+        print "Upgrade complete\n";
+      }
+    } else {
+      if ($failed) {
+        url::redirect("upgrader?failed=" . join(",", $failed));
+      } else {
+        url::redirect("upgrader");
+      }
+    }
+  }
+}
diff --git a/modules/gallery/controllers/uploader.php b/modules/gallery/controllers/uploader.php
new file mode 100644
index 0000000..8e09dbe
--- /dev/null
+++ b/modules/gallery/controllers/uploader.php
@@ -0,0 +1,133 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Uploader_Controller extends Controller {
+  public function index($id) {
+    $item = ORM::factory("item", $id);
+    access::required("view", $item);
+    access::required("add", $item);
+    if (!$item->is_album()) {
+      $item = $item->parent();
+    }
+
+    print $this->_get_add_form($item);
+  }
+
+  public function start() {
+    access::verify_csrf();
+    batch::start();
+  }
+
+  public function add_photo($id) {
+    $album = ORM::factory("item", $id);
+    access::required("view", $album);
+    access::required("add", $album);
+    access::verify_csrf();
+
+    // The Flash uploader not call /start directly, so simulate it here for now.
+    if (!batch::in_progress()) {
+      batch::start();
+    }
+
+    $form = $this->_get_add_form($album);
+
+    // Uploadify adds its own field to the form, so validate that separately.
+    $file_validation = new Validation($_FILES);
+    $file_validation->add_rules(
+      "Filedata", "upload::valid",  "upload::required",
+      "upload::type[" . implode(",", legal_file::get_extensions()) . "]");
+
+    if ($form->validate() && $file_validation->validate()) {
+      $temp_filename = upload::save("Filedata");
+      system::delete_later($temp_filename);
+      try {
+        $item = ORM::factory("item");
+        $item->name = substr(basename($temp_filename), 10);  // Skip unique identifier Kohana adds
+        $item->title = item::convert_filename_to_title($item->name);
+        $item->parent_id = $album->id;
+        $item->set_data_file($temp_filename);
+
+        $path_info = @pathinfo($temp_filename);
+        if (array_key_exists("extension", $path_info) &&
+            legal_file::get_movie_extensions($path_info["extension"])) {
+          $item->type = "movie";
+          $item->save();
+          log::success("content", t("Added a movie"),
+                       html::anchor("movies/$item->id", t("view movie")));
+        } else {
+          $item->type = "photo";
+          $item->save();
+          log::success("content", t("Added a photo"),
+                       html::anchor("photos/$item->id", t("view photo")));
+        }
+
+        module::event("add_photos_form_completed", $item, $form);
+      } catch (Exception $e) {
+        // The Flash uploader has no good way of reporting complex errors, so just keep it simple.
+        Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+
+        // Ugh.  I hate to use instanceof, But this beats catching the exception separately since
+        // we mostly want to treat it the same way as all other exceptions
+        if ($e instanceof ORM_Validation_Exception) {
+          Kohana_Log::add("error", "Validation errors: " . print_r($e->validation->errors(), 1));
+        }
+
+        header("HTTP/1.1 500 Internal Server Error");
+        print "ERROR: " . $e->getMessage();
+        return;
+      }
+      print "FILEID: $item->id";
+    } else {
+      header("HTTP/1.1 400 Bad Request");
+      print "ERROR: " . t("Invalid upload");
+    }
+  }
+
+  public function status($success_count, $error_count) {
+    if ($error_count) {
+      // The "errors" won't be properly pluralized :-/
+      print t2("Uploaded %count photo (%error errors)",
+               "Uploaded %count photos (%error errors)",
+               (int)$success_count,
+               array("error" => (int)$error_count));
+    } else {
+      print t2("Uploaded %count photo", "Uploaded %count photos", $success_count);}
+  }
+
+  public function finish() {
+    access::verify_csrf();
+
+    batch::stop();
+    json::reply(array("result" => "success"));
+  }
+
+  private function _get_add_form($album)  {
+    $form = new Forge("uploader/finish", "", "post", array("id" => "g-add-photos-form"));
+    $group = $form->group("add_photos")
+      ->label(t("Add photos to %album_title", array("album_title" => html::purify($album->title))));
+    $group->uploadify("uploadify")->album($album);
+
+    $group = $form->group("actions");
+    $group->uploadify_buttons("");
+
+    module::event("add_photos_form", $album, $form);
+
+    return $form;
+  }
+}
diff --git a/modules/gallery/controllers/user_profile.php b/modules/gallery/controllers/user_profile.php
new file mode 100644
index 0000000..cf589da
--- /dev/null
+++ b/modules/gallery/controllers/user_profile.php
@@ -0,0 +1,108 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class User_Profile_Controller extends Controller {
+
+  public function show($id) {
+    // If we get here, then we should have a user id other than guest.
+    $user = identity::lookup_user($id);
+    if (!$user) {
+      throw new Kohana_404_Exception();
+    }
+
+    if (!$this->_can_view_profile_pages($user)) {
+      throw new Kohana_404_Exception();
+    }
+
+    $v = new Theme_View("page.html", "other", "profile");
+    $v->page_title = t("%name Profile", array("name" => $user->display_name()));
+    $v->content = new View("user_profile.html");
+
+    $v->content->user = $user;
+    $v->content->contactable =
+      !$user->guest && $user->id != identity::active_user()->id && $user->email;
+    $v->content->editable =
+      identity::is_writable() && !$user->guest && $user->id == identity::active_user()->id;
+
+    $event_data = (object)array("user" => $user, "content" => array());
+    module::event("show_user_profile", $event_data);
+    $v->content->info_parts = $event_data->content;
+
+    print $v;
+  }
+
+  public function contact($id) {
+    $user = identity::lookup_user($id);
+    if (!$this->_can_view_profile_pages($user)) {
+      throw new Kohana_404_Exception();
+    }
+
+    print user_profile::get_contact_form($user);
+  }
+
+  public function send($id) {
+    access::verify_csrf();
+    $user = identity::lookup_user($id);
+    if (!$this->_can_view_profile_pages($user)) {
+      throw new Kohana_404_Exception();
+    }
+
+    $form = user_profile::get_contact_form($user);
+    if ($form->validate()) {
+      Sendmail::factory()
+        ->to($user->email)
+        ->subject(html::clean($form->message->subject->value))
+        ->header("Mime-Version", "1.0")
+        ->header("Content-type", "text/html; charset=UTF-8")
+        ->reply_to($form->message->reply_to->value)
+        ->message(html::purify($form->message->message->value))
+        ->send();
+      message::success(t("Sent message to %user_name", array("user_name" => $user->display_name())));
+      json::reply(array("result" => "success"));
+    } else {
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  private function _can_view_profile_pages($user) {
+    if (!$user->loaded()) {
+      return false;
+    }
+
+    if ($user->id == identity::active_user()->id) {
+      // You can always view your own profile
+      return true;
+    }
+
+    switch (module::get_var("gallery", "show_user_profiles_to")) {
+    case "admin_users":
+      return identity::active_user()->admin;
+
+    case "registered_users":
+      return !identity::active_user()->guest;
+
+    case "everybody":
+      return true;
+
+    default:
+      // Fail in private mode on an invalid setting
+      return false;
+    }
+  }
+}
diff --git a/modules/gallery/controllers/welcome_message.php b/modules/gallery/controllers/welcome_message.php
new file mode 100644
index 0000000..bde5e94
--- /dev/null
+++ b/modules/gallery/controllers/welcome_message.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Welcome_Message_Controller extends Controller {
+  public function index() {
+    if (!identity::active_user()->admin) {
+      url::redirect(item::root()->abs_url());
+    }
+
+    $v = new View("welcome_message.html");
+    $v->user = identity::active_user();
+    print $v;
+  }
+}
diff --git a/modules/gallery/css/debug.css b/modules/gallery/css/debug.css
new file mode 100644
index 0000000..6808da0
--- /dev/null
+++ b/modules/gallery/css/debug.css
@@ -0,0 +1,28 @@
+.g-annotated-theme-block {
+  border: 1px solid #C00;
+  clear: both;
+  margin: 1em;
+  padding: 1em;
+  position: relative;
+}
+
+.g-annotated-theme-block_album_top {
+  float: right;
+}
+
+.g-annotated-theme-block_header_bottom {
+  float: right;
+}
+
+.g-annotated-theme-block div.title {
+  background: #C00;
+  border: 1px solid black;
+  color: white;
+  font-size: 110%;
+  padding: 4px;
+  position: absolute;
+  right: -1em;
+  top: -1em;
+  text-align: left;
+  -moz-border-radius: 5%;
+}
diff --git a/modules/gallery/css/gallery.css b/modules/gallery/css/gallery.css
new file mode 100644
index 0000000..7e71115
--- /dev/null
+++ b/modules/gallery/css/gallery.css
@@ -0,0 +1,213 @@
+/**
+ * Gallery 3 core module styles
+ *
+ * Sheet organization:
+ *  1)  End-user
+ *  2)  Admin
+ *  3)  Right to left language styles
+ */
+
+/** *******************************************************************
+ * 1) End-user
+ **********************************************************************/
+
+/* Uploader ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-add-photos-canvas,
+#g-add-photos-status {
+  width: 469px;
+}
+
+#g-add-photos-canvas {
+  border: 1px solid  #ccc;
+  height: 200px;
+  margin: .5em 0;
+  padding: 2.8em 0 0 0;
+  overflow: auto;
+  position: relative;
+}
+
+#g-add-photos-canvas object,
+#g-add-photos-button {
+  left: 90px;
+  margin: .5em 0;
+  padding: .4em 1em;
+  position: absolute;
+  top: 0;
+  width: 300px;
+}
+
+#g-add-photos-canvas object {
+  z-index: 100;
+  padding: 0em;
+}
+
+#g-add-photos-canvas .uploadifyQueue {
+  margin-top: .5em;
+}
+
+#g-add-photos-canvas .uploadifyQueueItem {
+  margin: 0;
+}
+
+#g-add-photos-button {
+  z-index: 1;
+}
+
+#g-add-photos-status {
+  border: 1px solid #ccc;
+  height: 125px;
+  margin: .4em 0;
+  overflow: auto;
+}
+
+#g-add-photos-status .g-message-block {
+  border: none;
+}
+
+#g-add-photos-status #g-action-status li {
+  margin: 0 0 1px 0;
+  padding-top: .7em;
+  width: 433px;
+}
+
+#g-add-photos-form .g-breadcrumbs {
+  margin: 0;
+}
+
+#g-add-photos-form p {
+  margin-bottom: 0
+}
+
+#g-add-photos-status-message {
+  float: right;
+}
+
+/* Permissions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-edit-permissions-form {
+  clear: both;
+}
+
+#g-edit-permissions-form th {
+  text-align: center;
+}
+
+#g-permissions .g-denied,
+#g-permissions .g-allowed {
+  text-align: center;
+  vertical-align: middle;
+}
+
+/* Move items ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-move ul {
+  padding-left: 1em;
+}
+
+#g-move .selected {
+  background: #999;
+}
+
+/* In-place edit ~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-in-place-edit-form ul {
+  margin: 0;
+}
+
+/* User profile ~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-user-profile h1 {
+  margin: 1em 0;
+}
+
+#g-user-profile .g-avatar {
+  margin-right: .6em;
+}
+
+#g-user-profile .g-block {
+  margin-top: 0;
+}
+
+#g-user-profile .g-block-content {
+  margin-top: 0;
+}
+
+#g-user-profile th,
+#g-user-profile td {
+  border: none;
+}
+
+#g-user-profile th {
+  white-space: nowrap;
+  width: 1%;
+}
+
+/* Unsupported movie download link ~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-movie-download-link {
+  text-align: center;
+}
+
+/** *******************************************************************
+ * 2) Admin
+ **********************************************************************/
+
+.g-task-log {
+  border: 1px solid #000;
+  height: 400px;
+  margin: .6em 0;
+  overflow: auto;
+  padding: .4em
+}
+
+#g-languages-form table {
+  width: 40%;
+  margin: 0 3em 1em 0;
+}
+
+#g-languages-form input {
+  clear: both;
+}
+
+#g-translations ol {
+  margin: 0 0 1em 2em;
+}
+#g-translations ol li {
+  list-style-type: decimal;
+  line-height: 150%;
+}
+
+#g-translations .g-button {
+  padding: .5em;
+  margin-bottom: 1em;
+}
+
+/** *******************************************************************
+ * 3) Right to left language styles
+ **********************************************************************/
+
+.rtl #g-add-photos-status #g-action-status li {
+  width: 407px;
+}
+
+.rtl #g-block-admin .g-left {
+  margin-left: 1em;
+  margin-right: 0;
+}
+
+.rtl #g-user-profile .g-avatar {
+  margin-left: .6em;
+}
+
+.rtl #g-languages-form table {
+  margin: 0 0 1em 3em;
+}
+
+.rtl #g-translations ol {
+  margin: 0 2em 1em 0;
+}
+
+.rtl #g-add-photos-status-message {
+  float: left;
+}
diff --git a/modules/gallery/css/l10n_client.css b/modules/gallery/css/l10n_client.css
new file mode 100644
index 0000000..90034d0
--- /dev/null
+++ b/modules/gallery/css/l10n_client.css
@@ -0,0 +1,206 @@
+/**
+ * TODO(andy_st): Add original copyright notice from Drupal l10_client.
+ * TODO(andy_st): Add G3 copyright notice.
+ * TODO(andy_st): clean up formatting to match our other CSS files.
+ */
+
+/* $Id: l10n_client.css,v 1.6 2008/09/09 10:48:20 goba Exp $ */
+
+/* width percentages add to 99% rather than 100% to prevent float
+   overflows from occurring in an unnamed browser that can't decide
+   how it wants to round. */
+
+/* l10n_client container */
+#l10n-client {
+  text-align:left;
+  z-index:99;
+  line-height:1em;
+  color:#000; background:#fff;
+  position:fixed;
+  width:100%; height: 2em;
+  bottom:0px; left:0px;
+  overflow:hidden;}
+
+* html #l10n-client {
+  position:static;}
+
+#l10n-client-string-select .string-list,
+#l10n-client-string-editor .source,
+#l10n-client-string-editor .editor {
+  height:20em;}
+
+#l10n-client .labels {
+  overflow:hidden;
+  position:relative;
+  height:2em;
+  color:#fff;
+  background:#37a;}
+
+#l10n-client .labels .label {
+  display:none;}
+
+/* Panel toggle button (span) */
+#l10n-client-toggler {
+  cursor:pointer;
+  display:block;
+  position:absolute; right:0em;
+  height:2em; line-height:2em;
+  text-align:center; background:#000;
+}
+#l10n-client-toggler a {
+	font-size: 1em;
+	padding: .5em;
+}
+#l10n-client-toggler #g-minimize-l10n {
+  border-right: 1px solid #ffffff;
+}
+
+/* Panel labels */
+#l10n-client h2 {
+  border-left:1px solid #fff;
+  height:1em; line-height:1em;
+  padding: .5em; margin:0px;
+  font-size:1em;
+}
+
+#l10n-client .strings h2 {
+  border:0px;}
+
+/* 25 + 37 + 37 = 99 */
+#l10n-client .strings {
+  width:25%; float:left;}
+
+#l10n-client .source {
+  width:37%; float:left;}
+
+#l10n-client .translation {
+  width:37%; float:left;}
+
+/* Translatable string list */
+#l10n-client-string-select {
+  display:none;
+  float:left;
+  width:25%;
+  direction: ltr;
+}
+
+#l10n-client .string-list {
+  height: 16em;
+  overflow:auto;
+  list-style:none; list-style-image:none;
+  margin:0em; padding:0em;}
+
+#l10n-client .string-list li {
+  font-size:.9em;
+  line-height:1.5em;
+  cursor:default;
+  background:transparent;
+  list-style:none; list-style-image:none;
+  border-bottom:1px solid #ddd;
+  padding:.25em .5em;
+  margin:0em;}
+
+/* Green for translated */
+#l10n-client .string-list li.translated {
+  border-bottom-color:#9c3;
+  background:#cf6; color:#360;}
+
+#l10n-client .string-list li.translated:hover {
+  background: #df8;}
+
+#l10n-client .string-list li.translated:active {
+  background: #9c3;}
+
+#l10n-client .string-list li.hidden {
+  display:none;}
+
+/* Gray + Blue hover for untranslated */
+#l10n-client .string-list li.untranslated {}
+
+#l10n-client .string-list li.untranslated:hover {
+  background: #ace;}
+
+#l10n-client .string-list li.untranslated:active {
+  background: #8ac;}
+
+/* Selected string is indicated by bold text */
+#l10n-client .string-list li.active {
+  font-weight:bold;}
+
+#l10n-client #g-l10n-search-form {
+  background: #eee;
+  margin: 0em;
+  padding: .25em .25em;
+}
+
+#l10n-client #g-l10n-search-form .form-item,
+#l10n-client #g-l10n-search-form input.form-text,
+#l10n-client #g-l10n-search-form #search-filter-go,
+#l10n-client #g-l10n-search-form #search-filter-clear {
+  display:inline;
+  vertical-align:middle;
+}
+
+#l10n-client #g-l10n-search-form .form-item {
+  margin:0em;
+  padding:0em;
+}
+
+#l10n-client #g-l10n-search-form fieldset {
+  margin-bottom: 0;
+  padding: .25em .25em;
+}
+
+
+#l10n-client #g-l10n-search-form input {
+  width: 96.75%;
+}
+
+#l10n-client #g-l10n-search-form #search-filter-clear {
+  width:10%;
+  margin:0em;
+}
+
+#l10n-client-string-editor {
+  display:none;
+  float:left;
+  width:74%;}
+
+#l10n-client-string-editor .source {
+  overflow:hidden;
+  width:50%;
+  float:left;
+}
+
+#l10n-client-string-editor .source .source-text {
+  line-height:1.5em;
+  background:#eee;
+  font-family: monospace;
+  text-align: left;
+  height:16em; margin:1em; padding:1em;
+  overflow:auto;
+  direction: ltr;
+}
+
+#l10n-client-string-editor .translation {
+  overflow-y:auto;
+  overflow-x: hidden;
+  height: 20em;
+  width:49%;
+  float: right;
+}
+
+#g-l10n-client-save-form {
+  padding: 0em;
+}
+
+#l10n-client form ul,
+#l10n-client form li,
+#l10n-client form input[type=submit],
+#l10n-client form input[type=text] {
+  display: inline ! important ;
+}
+
+#l10n-client form .hidden {
+  display: none;
+}
diff --git a/modules/gallery/css/upgrader.css b/modules/gallery/css/upgrader.css
new file mode 100644
index 0000000..8610016
--- /dev/null
+++ b/modules/gallery/css/upgrader.css
@@ -0,0 +1,183 @@
+body {
+  background: #eee;
+  font-family: 'Trebuchet MS';
+  font-size: 1.1em;
+}
+
+h1 {
+  font-size: 1.4em;
+}
+
+div#outer {
+  background: #fff;
+  border: 1px solid #999;
+  margin: 0 auto;
+  width: 650px;
+}
+
+div#inner {
+  margin: 0;
+  padding: 0 1em;
+}
+
+div#footer {
+  border-top: 1px solid #ccc;
+  margin: 1em;
+}
+
+table {
+  width: 600px;
+  margin-bottom: 10px;
+}
+
+th.name,
+td.name {
+  text-align: left;
+  padding-left: 30px;
+}
+
+td {
+  text-align: center;
+  border-bottom: 1px solid #eee;
+}
+
+tr.current td {
+  opacity: 0.5;
+  font-style: italic;
+}
+
+tr.current td.gallery {
+  color: #00d;
+}
+
+tr.upgradeable td {
+  font-weight: bold;
+}
+
+tr.upgradeable td.gallery {
+  color: #00d;
+}
+
+tr.failed td {
+  color: red;
+}
+
+p {
+  font-size: .9em;
+}
+
+ul {
+  font-size: .9em;
+  list-style: none;
+}
+
+li {
+  display: inline;
+}
+
+li:before {
+  content: "\00BB \0020";
+}
+
+div.button {
+  margin: 0 auto;
+  width: 120px;
+  text-align: center;
+  border: 1px solid #999;
+  background: #eee;
+}
+
+div.button a {
+  text-decoration: none;
+}
+
+div.button-active:hover {
+  background: #ccc;
+}
+
+div#dialog {
+  width: 340px;
+  height: 200px;
+  position: absolute;
+  background: blue;
+  z-index: 1000;
+  margin: 10px;
+  text-align: center;
+}
+
+div#dialog a.close {
+  float: right;
+  padding: 10px;
+  text-decoration: none;
+}
+
+div#dialog div {
+  width: 292px;
+  height: 152px;
+  margin: 2px;
+  padding: 20px;
+  border: 2px solid #999;
+  background: #eee;
+}
+
+.muted {
+  opacity: 0.5;
+}
+
+.failed {
+  color: red;
+}
+
+pre {
+  display: inline;
+  margin: 0px;
+  padding: 0px;
+}
+
+div#upgrade_button {
+  margin-bottom: 20px;
+}
+
+div#welcome_message {
+  margin-left: 30px;
+}
+
+#logo {
+  margin-left: 14px;
+}
+
+.rtl {
+  direction: rtl;
+}
+
+.rtl th.name,
+.rtl td.name {
+  text-align: right;
+  padding-right: 30px;
+}
+
+
+.rtl li:before {
+  content: "";
+}
+
+.rtl li:after {
+  content: "\00BB \0020";
+}
+
+.rtl ul {
+  margin-right: 0;
+  padding-right: 0;
+}
+
+.rtl div#dialog a.close {
+  float: left;
+}
+
+.rtl div#welcome_message {
+  padding-right: 30px;
+}
+
+.rtl #logo {
+  padding-right: 12px;
+}
diff --git a/modules/gallery/helpers/MY_html.php b/modules/gallery/helpers/MY_html.php
new file mode 100644
index 0000000..767fe3f
--- /dev/null
+++ b/modules/gallery/helpers/MY_html.php
@@ -0,0 +1,91 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class html extends html_Core {
+  /**
+   * Returns a string that is safe to be used in HTML (XSS protection).
+   *
+   * If $html is a string, the returned string will be HTML escaped.
+   * If $html is a SafeString instance, the returned string may contain
+   * unescaped HTML which is assumed to be safe.
+   *
+   * Example:<pre>
+   *   <div><?= html::clean($php_var) ?>
+   * </pre>
+   */
+  static function clean($html) {
+    return new SafeString($html);
+  }
+
+  /**
+   * Returns a string that is safe to be used in HTML (XSS protection),
+   * purifying (filtering) the given HTML to ensure that the result contains
+   * only non-malicious HTML.
+   *
+   * Example:<pre>
+   *   <div><?= html::purify($item->title) ?>
+   * </pre>
+   */
+  static function purify($html) {
+    return SafeString::purify($html);
+  }
+
+  /**
+   * Flags the given string as safe to be used in HTML (free of malicious HTML/JS).
+   *
+   * Example:<pre>
+   *   // Parameters to t() are automatically escaped by default.
+   *   // If the parameter is marked as clean, it won't get escaped.
+   *   t('Go <a href="%url">there</a>',
+   *     array("url" => html::mark_clean(url::current())))
+   * </pre>
+   */
+  static function mark_clean($html) {
+    return SafeString::of_safe_html($html);
+  }
+
+  /**
+   * Escapes the given string for use in JavaScript.
+   *
+   * Example:<pre>
+   *   <script type="text/javascript>"
+   *     var some_js_string = <?= html::js_string($php_string) ?>;
+   *   </script>
+   * </pre>
+   */
+  static function js_string($string) {
+    return SafeString::of($string)->for_js();
+  }
+
+  /**
+   * Returns a string safe for use in HTML element attributes.
+   *
+   * Assumes that the HTML element attribute is already
+   * delimited by single or double quotes
+   *
+   * Example:<pre>
+   *     <a title="<?= html::clean_for_attribute($php_var) ?>">;
+   *   </script>
+   * </pre>
+   * @return the string escaped for use in HTML attributes.
+   */
+  static function clean_attribute($string) {
+    return html::clean($string)->for_html_attr();
+  }
+}
diff --git a/modules/gallery/helpers/MY_num.php b/modules/gallery/helpers/MY_num.php
new file mode 100644
index 0000000..a550a1a
--- /dev/null
+++ b/modules/gallery/helpers/MY_num.php
@@ -0,0 +1,54 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class num extends num_Core {
+  /**
+   * Convert a size value as accepted by PHP's shorthand to bytes.
+   * ref: http://us2.php.net/manual/en/function.ini-get.php
+   * ref: http://us2.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
+   */
+  static function convert_to_bytes($val) {
+    $val = trim($val);
+    $last = strtolower($val[strlen($val)-1]);
+    switch($last) {
+    case 'g':
+      $val *= 1024;
+    case 'm':
+      $val *= 1024;
+    case 'k':
+      $val *= 1024;
+    }
+
+    return $val;
+  }
+
+  /**
+   * Convert a size value as accepted by PHP's shorthand to bytes.
+   * ref: http://us2.php.net/manual/en/function.ini-get.php
+   * ref: http://us2.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
+   */
+  static function convert_to_human_readable($num) {
+    foreach (array("G" => 1e9, "M" => 1e6, "K" => 1e3) as $k => $v) {
+      if ($num > $v) {
+        $num = round($num / $v) . $k;
+      }
+    }
+    return $num;
+  }
+}
diff --git a/modules/gallery/helpers/MY_remote.php b/modules/gallery/helpers/MY_remote.php
new file mode 100644
index 0000000..59804b9
--- /dev/null
+++ b/modules/gallery/helpers/MY_remote.php
@@ -0,0 +1,167 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class remote extends remote_Core {
+
+  static function post($url, $post_data_array, $extra_headers=array()) {
+    $post_data_raw = self::_encode_post_data($post_data_array, $extra_headers);
+
+    /* Read the web page into a buffer */
+    list ($response_status, $response_headers, $response_body) =
+      remote::do_request($url, 'POST', $extra_headers, $post_data_raw);
+
+    return array($response_body, $response_status, $response_headers);
+  }
+
+  static function success($response_status) {
+    return preg_match("/^HTTP\/\d+\.\d+\s2\d{2}(\s|$)/", trim($response_status));
+  }
+
+  /**
+   * Encode the post data.  For each key/value pair, urlencode both the key and the value and then
+   * concatenate together.  As per the specification, each key/value pair is separated with an
+   * ampersand (&)
+   * @param array $post_data_array the key/value post data
+   * @param array $extra_headers extra headers to pass to the server
+   * @return string the encoded post data
+   */
+  private static function _encode_post_data($post_data_array, &$extra_headers) {
+    $post_data_raw = '';
+    foreach ($post_data_array as $key => $value) {
+      if (!empty($post_data_raw)) {
+        $post_data_raw .= '&';
+      }
+      $post_data_raw .= urlencode($key) . '=' . urlencode($value);
+    }
+
+    $extra_headers['Content-Type'] = 'application/x-www-form-urlencoded';
+    $extra_headers['Content-Length'] = strlen($post_data_raw);
+
+    return $post_data_raw;
+  }
+
+  /**
+   * A single request, without following redirects
+   *
+   * @todo: Handle redirects? If so, only for GET (i.e. not for POST), and use G2's
+   * WebHelper_simple::_parseLocation logic.
+   */
+  static function do_request($url, $method='GET', $headers=array(), $body='') {
+    if (!array_key_exists("User-Agent", $headers)) {
+      $headers["User-Agent"] = "Gallery3";
+    }
+    /* Convert illegal characters */
+    $url = str_replace(' ', '%20', $url);
+
+    $url_components = self::_parse_url_for_fsockopen($url);
+    $handle = fsockopen(
+      $url_components['fsockhost'], $url_components['port'], $errno, $errstr, 5);
+    if (empty($handle)) {
+      // log "Error $errno: '$errstr' requesting $url";
+      return array(null, null, null);
+    }
+
+    $header_lines = array('Host: ' . $url_components['host']);
+    foreach ($headers as $key => $value) {
+      $header_lines[] = $key . ': ' . $value;
+    }
+
+    $success = fwrite($handle, sprintf("%s %s HTTP/1.0\r\n%s\r\n\r\n%s",
+                                       $method,
+                                       $url_components['uri'],
+                                       implode("\r\n", $header_lines),
+                                       $body));
+    if (!$success) {
+      // Zero bytes written or false was returned
+      // log "fwrite failed in requestWebPage($url)" . ($success === false ? ' - false' : ''
+      return array(null, null, null);
+    }
+    fflush($handle);
+
+    /*
+     * Read the status line.  fgets stops after newlines.  The first line is the protocol
+     * version followed by a numeric status code and its associated textual phrase.
+     */
+    $response_status = trim(fgets($handle, 4096));
+    if (empty($response_status)) {
+      // 'Empty http response code, maybe timeout'
+      return array(null, null, null);
+    }
+
+    /* Read the headers */
+    $response_headers = array();
+    while (!feof($handle)) {
+      $line = trim(fgets($handle, 4096));
+      if (empty($line)) {
+        break;
+      }
+
+      /* Normalize the line endings */
+      $line = str_replace("\r", '', $line);
+
+      list ($key, $value) = explode(':', $line, 2);
+      if (isset($response_headers[$key])) {
+        if (!is_array($response_headers[$key])) {
+          $response_headers[$key] = array($response_headers[$key]);
+        }
+        $response_headers[$key][] = trim($value);
+      } else {
+        $response_headers[$key] = trim($value);
+      }
+    }
+
+    /* Read the body */
+    $response_body = '';
+    while (!feof($handle)) {
+      $response_body .= fread($handle, 4096);
+    }
+    fclose($handle);
+
+    return array($response_status, $response_headers, $response_body);
+  }
+
+  /**
+   * Prepare for fsockopen call.
+   * @param string $url
+   * @return array url components
+   * @access private
+   */
+  private static function _parse_url_for_fsockopen($url) {
+    $url_components = parse_url($url);
+    if (strtolower($url_components['scheme']) == 'https') {
+      $url_components['fsockhost'] = 'ssl://' . $url_components['host'];
+      $default_port = 443;
+    } else {
+      $url_components['fsockhost'] = $url_components['host'];
+      $default_port = 80;
+    }
+    if (empty($url_components['port'])) {
+      $url_components['port'] = $default_port;
+    }
+    if (empty($url_components['path'])) {
+      $url_components['path'] = '/';
+    }
+    $uri = $url_components['path']
+      . (empty($url_components['query']) ? '' : '?' . $url_components['query']);
+    /* Unescape ampersands, since if the url comes from form input it will be escaped */
+    $url_components['uri'] = str_replace('&amp;', '&', $uri);
+    return $url_components;
+  }
+}
+
diff --git a/modules/gallery/helpers/MY_url.php b/modules/gallery/helpers/MY_url.php
new file mode 100644
index 0000000..eba08b2
--- /dev/null
+++ b/modules/gallery/helpers/MY_url.php
@@ -0,0 +1,92 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class url extends url_Core {
+  static function parse_url() {
+    if (Router::$controller) {
+      return;
+    }
+
+    // Work around problems with the CGI sapi by enforcing our default path
+    if ($_SERVER["SCRIPT_NAME"] && "/" . Router::$current_uri == $_SERVER["SCRIPT_NAME"]) {
+      Router::$controller_path = MODPATH . "gallery/controllers/albums.php";
+      Router::$controller = "albums";
+      Router::$method = 1;
+      return;
+    }
+
+    $item = item::find_by_relative_url(html_entity_decode(Router::$current_uri, ENT_QUOTES));
+    if ($item && $item->loaded()) {
+      Router::$controller = "{$item->type}s";
+      Router::$controller_path = MODPATH . "gallery/controllers/{$item->type}s.php";
+      Router::$method = "show";
+      Router::$arguments = array($item);
+    }
+  }
+
+  /**
+   * Just like url::file() except that it returns an absolute URI
+   */
+  static function abs_file($path) {
+    return url::base(false, request::protocol()) . $path;
+  }
+
+  /**
+   * Just like url::site() except that it returns an absolute URI and
+   * doesn't take a protocol parameter.
+   */
+  static function abs_site($path) {
+    return url::site($path, request::protocol());
+  }
+
+  /**
+   * Just like url::current except that it returns an absolute URI
+   */
+  static function abs_current($qs=false) {
+    return self::abs_site(url::current($qs));
+  }
+
+  /**
+   * Just like url::merge except that it escapes any XSS in the path.
+   */
+  static function merge(array $arguments) {
+    return htmlspecialchars(parent::merge($arguments));
+  }
+
+  /**
+   * Just like url::current except that it escapes any XSS in the path.
+   */
+  static function current($qs=false, $suffix=false) {
+    return htmlspecialchars(parent::current($qs, $suffix));
+  }
+
+  /**
+   * Merge extra an query string onto a given url safely.
+   * @param string the original url
+   * @param array the query string data in key=value form
+   */
+  static function merge_querystring($url, $query_params) {
+    $qs = implode("&", $query_params);
+    if (strpos($url, "?") === false) {
+      return $url . "?$qs";
+    } else {
+      return $url . "&$qs";
+    }
+  }
+}
diff --git a/modules/gallery/helpers/MY_valid.php b/modules/gallery/helpers/MY_valid.php
new file mode 100644
index 0000000..f1dd9c3
--- /dev/null
+++ b/modules/gallery/helpers/MY_valid.php
@@ -0,0 +1,26 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class valid extends valid_Core {
+  static function url($url) {
+    return valid_Core::url($url) &&
+      (!strncasecmp($url, "http://", strlen("http://")) ||
+       !strncasecmp($url, "https://", strlen("https://")));
+  }
+}
diff --git a/modules/gallery/helpers/access.php b/modules/gallery/helpers/access.php
new file mode 100644
index 0000000..a7dca57
--- /dev/null
+++ b/modules/gallery/helpers/access.php
@@ -0,0 +1,758 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+/**
+ * API for Gallery Access control.
+ *
+ * Permissions are hierarchical, and apply only to groups and albums.  They cascade down from the
+ * top of the Gallery to the bottom, so if you set a permission in the root album, that permission
+ * applies for any sub-album unless the sub-album overrides it.  Likewise, any permission applied
+ * to an album applies to any photos inside the album.  Overrides can be applied at any level of
+ * the hierarchy for any permission other than View permissions.
+ *
+ * View permissions are an exceptional case.  In the case of viewability, we want to ensure that
+ * if an album's parent is inaccessible, then this album must be inaccessible also.  So while view
+ * permissions cascade downwards and you're free to set the ALLOW permission on any album, that
+ * ALLOW permission will be ignored unless all that album's parents are marked ALLOW also.
+ *
+ * Implementatation Notes:
+ *
+ * Notes refer to this example album hierarchy:
+ *      A1
+ *     /  \
+ *   A2   A3
+ *       /  \
+ *      A4  A5
+ *
+ * o We have the concept of "intents".  A user can specify that he intends for A3 to be
+ *   inaccessible (ie: a DENY on the "view" permission to the EVERYBODY group).  Once A3 is
+ *   inaccessible, A5 can never be displayed to that group.  If A1 is made inaccessible, then the
+ *   entire tree is hidden.  If subsequently A1 is made accessible, then the whole tree is
+ *   available again *except* A3 and below since the user's "intent" for A3 is maintained.
+ *
+ * o Intents are specified as <group_id, perm, item_id> tuples.  It would be inefficient to check
+ *   these tuples every time we want to do a lookup, so we use these intents to create an entire
+ *   table of permissions for easy lookup in the Access_Cache_Model.  There's a 1:1 mapping
+ *   between Item_Model and Access_Cache_Model entries.
+ *
+ * o For efficiency, we create columns in Access_Intent_Model and Access_Cache_Model for each of
+ *   the possible Group_Model and Permission_Model combinations.  This may lead to performance
+ *   issues for very large Gallery installs, but for small to medium sized ones (5-10 groups, 5-10
+ *   permissions) it's especially efficient because there's a single field value for each
+ *   group/permission/item combination.
+ *
+ * o For efficiency, we store the cache columns for view permissions directly in the Item_Model.
+ *   This means that we can filter items by group/permission combination without doing any table
+ *   joins making for an especially efficient permission check at the expense of having to
+ *   maintain extra columns for each item.
+ *
+ * o If at any time the Access_Cache_Model becomes invalid, we can rebuild the entire table from
+ *   the Access_Intent_Model
+ */
+class access_Core {
+  const DENY      = "0";
+  const ALLOW     = "1";
+  const INHERIT   = null; // access_intent
+  const UNKNOWN   = null; // cache (access_cache, items)
+
+  /**
+   * Does the active user have this permission on this item?
+   *
+   * @param  string     $perm_name
+   * @param  Item_Model $item
+   * @return boolean
+   */
+  static function can($perm_name, $item) {
+    return access::user_can(identity::active_user(), $perm_name, $item);
+  }
+
+  /**
+   * Does the user have this permission on this item?
+   *
+   * @param  User_Model $user
+   * @param  string     $perm_name
+   * @param  Item_Model $item
+   * @return boolean
+   */
+  static function user_can($user, $perm_name, $item) {
+    if (!$item->loaded()) {
+      return false;
+    }
+
+    if ($user->admin) {
+      return true;
+    }
+
+    // Use the nearest parent album (including the current item) so that we take advantage
+    // of the cache when checking many items in a single album.
+    $id = ($item->type == "album") ? $item->id : $item->parent_id;
+    $resource = $perm_name == "view" ?
+      $item : model_cache::get("access_cache", $id, "item_id");
+
+    foreach ($user->groups() as $group) {
+      if ($resource->__get("{$perm_name}_{$group->id}") === access::ALLOW) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * If the active user does not have this permission, failed with an access::forbidden().
+   *
+   * @param  string     $perm_name
+   * @param  Item_Model $item
+   * @return boolean
+   */
+  static function required($perm_name, $item) {
+    if (!access::can($perm_name, $item)) {
+      if ($perm_name == "view") {
+        // Treat as if the item didn't exist, don't leak any information.
+        throw new Kohana_404_Exception();
+      } else {
+        access::forbidden();
+      }
+    }
+  }
+
+  /**
+   * Does this group have this permission on this item?
+   *
+   * @param  Group_Model $group
+   * @param  string      $perm_name
+   * @param  Item_Model  $item
+   * @return boolean
+   */
+  static function group_can($group, $perm_name, $item) {
+    // Use the nearest parent album (including the current item) so that we take advantage
+    // of the cache when checking many items in a single album.
+    $id = ($item->type == "album") ? $item->id : $item->parent_id;
+    $resource = $perm_name == "view" ?
+      $item : model_cache::get("access_cache", $id, "item_id");
+
+    return $resource->__get("{$perm_name}_{$group->id}") === access::ALLOW;
+  }
+
+  /**
+   * Return this group's intent for this permission on this item.
+   *
+   * @param  Group_Model $group
+   * @param  string      $perm_name
+   * @param  Item_Model  $item
+   * @return boolean     access::ALLOW, access::DENY or access::INHERIT (null) for no intent
+   */
+  static function group_intent($group, $perm_name, $item) {
+    $intent = model_cache::get("access_intent", $item->id, "item_id");
+    return $intent->__get("{$perm_name}_{$group->id}");
+  }
+
+  /**
+   * Is the permission on this item locked by a parent?  If so return the nearest parent that
+   * locks it.
+   *
+   * @param  Group_Model $group
+   * @param  string      $perm_name
+   * @param  Item_Model  $item
+   * @return ORM_Model   item that locks this one
+   */
+  static function locked_by($group, $perm_name, $item) {
+    if ($perm_name != "view") {
+      return null;
+    }
+
+    // For view permissions, if any parent is access::DENY, then those parents lock this one.
+    // Return
+    $lock = ORM::factory("item")
+      ->where("left_ptr", "<=", $item->left_ptr)
+      ->where("right_ptr", ">=", $item->right_ptr)
+      ->where("items.id", "<>", $item->id)
+      ->join("access_intents", "items.id", "access_intents.item_id")
+      ->where("access_intents.view_$group->id", "=", access::DENY)
+      ->order_by("level", "DESC")
+      ->limit(1)
+      ->find();
+
+    if ($lock->loaded()) {
+      return $lock;
+    } else {
+      return null;
+    }
+  }
+
+  /**
+   * Terminate immediately with an HTTP 403 Forbidden response.
+   */
+  static function forbidden() {
+    throw new Kohana_Exception("@todo FORBIDDEN", null, 403);
+  }
+
+  /**
+   * Internal method to set a permission
+   *
+   * @param  Group_Model $group
+   * @param  string      $perm_name
+   * @param  Item_Model  $item
+   * @param  boolean     $value
+   */
+  private static function _set(Group_Definition $group, $perm_name, $album, $value) {
+    if (!($group instanceof Group_Definition)) {
+      throw new Exception("@todo PERMISSIONS_ONLY_WORK_ON_GROUPS");
+    }
+    if (!$album->loaded()) {
+      throw new Exception("@todo INVALID_ALBUM $album->id");
+    }
+    if (!$album->is_album()) {
+      throw new Exception("@todo INVALID_ALBUM_TYPE not an album");
+    }
+    $access = model_cache::get("access_intent", $album->id, "item_id");
+    $access->__set("{$perm_name}_{$group->id}", $value);
+    $access->save();
+
+    if ($perm_name == "view") {
+      self::_update_access_view_cache($group, $album);
+    } else {
+      self::_update_access_non_view_cache($group, $perm_name, $album);
+    }
+
+    access::update_htaccess_files($album, $group, $perm_name, $value);
+    model_cache::clear();
+  }
+
+  /**
+   * Allow a group to have a permission on an item.
+   *
+   * @param  Group_Model $group
+   * @param  string  $perm_name
+   * @param  Item_Model $item
+   */
+  static function allow($group, $perm_name, $item) {
+    self::_set($group, $perm_name, $item, self::ALLOW);
+  }
+
+  /**
+   * Deny a group the given permission on an item.
+   *
+   * @param  Group_Model $group
+   * @param  string  $perm_name
+   * @param  Item_Model $item
+   */
+  static function deny($group, $perm_name, $item) {
+    self::_set($group, $perm_name, $item, self::DENY);
+  }
+
+  /**
+   * Unset the given permission for this item and use inherited values
+   *
+   * @param  Group_Model $group
+   * @param  string  $perm_name
+   * @param  Item_Model $item
+   */
+  static function reset($group, $perm_name, $item) {
+    if ($item->id == 1) {
+      throw new Exception("@todo CANT_RESET_ROOT_PERMISSION");
+    }
+    self::_set($group, $perm_name, $item, self::INHERIT);
+  }
+
+  /**
+   * Recalculate the permissions for an album's hierarchy.
+   */
+  static function recalculate_album_permissions($album) {
+    foreach (self::_get_all_groups() as $group) {
+      foreach (ORM::factory("permission")->find_all() as $perm) {
+        if ($perm->name == "view") {
+          self::_update_access_view_cache($group, $album);
+        } else {
+          self::_update_access_non_view_cache($group, $perm->name, $album);
+        }
+      }
+    }
+    model_cache::clear();
+  }
+
+  /**
+   * Recalculate the permissions for a single photo.
+   */
+  static function recalculate_photo_permissions($photo) {
+    $parent = $photo->parent();
+    $parent_access_cache = ORM::factory("access_cache")->where("item_id", "=", $parent->id)->find();
+    $photo_access_cache = ORM::factory("access_cache")->where("item_id", "=", $photo->id)->find();
+    foreach (self::_get_all_groups() as $group) {
+      foreach (ORM::factory("permission")->find_all() as $perm) {
+        $field = "{$perm->name}_{$group->id}";
+        if ($perm->name == "view") {
+          $photo->$field = $parent->$field;
+        } else {
+          $photo_access_cache->$field = $parent_access_cache->$field;
+        }
+      }
+    }
+    $photo_access_cache->save();
+    $photo->save();
+    model_cache::clear();
+  }
+
+  /**
+   * Register a permission so that modules can use it.
+   *
+   * @param  string $name           The internal name for for this permission
+   * @param  string $display_name   The internationalized version of the displayable name
+   * @return void
+  */
+  static function register_permission($name, $display_name) {
+    $permission = ORM::factory("permission", $name);
+    if ($permission->loaded()) {
+      throw new Exception("@todo PERMISSION_ALREADY_EXISTS $name");
+    }
+    $permission->name = $name;
+    $permission->display_name = $display_name;
+    $permission->save();
+
+    foreach (self::_get_all_groups() as $group) {
+      self::_add_columns($name, $group);
+    }
+  }
+
+  /**
+   * Delete a permission.
+   *
+   * @param  string $perm_name
+   * @return void
+   */
+  static function delete_permission($name) {
+    foreach (self::_get_all_groups() as $group) {
+      self::_drop_columns($name, $group);
+    }
+    $permission = ORM::factory("permission")->where("name", "=", $name)->find();
+    if ($permission->loaded()) {
+      $permission->delete();
+    }
+  }
+
+  /**
+   * Add the appropriate columns for a new group
+   *
+   * @param Group_Model $group
+   * @return void
+   */
+  static function add_group($group) {
+    foreach (ORM::factory("permission")->find_all() as $perm) {
+      self::_add_columns($perm->name, $group);
+    }
+  }
+
+  /**
+   * Remove a group's permission columns (usually when it's deleted)
+   *
+   * @param Group_Model $group
+   * @return void
+   */
+  static function delete_group($group) {
+    foreach (ORM::factory("permission")->find_all() as $perm) {
+      self::_drop_columns($perm->name, $group);
+    }
+  }
+
+  /**
+   * Add new access rows when a new item is added.
+   *
+   * @param Item_Model $item
+   * @return void
+   */
+  static function add_item($item) {
+    $access_intent = ORM::factory("access_intent", $item->id);
+    if ($access_intent->loaded()) {
+      throw new Exception("@todo ITEM_ALREADY_ADDED $item->id");
+    }
+    $access_intent = ORM::factory("access_intent");
+    $access_intent->item_id = $item->id;
+    $access_intent->save();
+
+    // Create a new access cache entry and copy the parents values.
+    $access_cache = ORM::factory("access_cache");
+    $access_cache->item_id = $item->id;
+    if ($item->id != 1) {
+      $parent_access_cache =
+        ORM::factory("access_cache")->where("item_id", "=", $item->parent()->id)->find();
+      foreach (self::_get_all_groups() as $group) {
+        foreach (ORM::factory("permission")->find_all() as $perm) {
+          $field = "{$perm->name}_{$group->id}";
+          if ($perm->name == "view") {
+            $item->$field = $item->parent()->$field;
+          } else {
+            $access_cache->$field = $parent_access_cache->$field;
+          }
+        }
+      }
+    }
+    $item->save();
+    $access_cache->save();
+  }
+
+  /**
+   * Delete appropriate access rows when an item is deleted.
+   *
+   * @param Item_Model $item
+   * @return void
+   */
+  static function delete_item($item) {
+    ORM::factory("access_intent")->where("item_id", "=", $item->id)->find()->delete();
+    ORM::factory("access_cache")->where("item_id", "=", $item->id)->find()->delete();
+  }
+
+  /**
+   * Verify our Cross Site Request Forgery token is valid, else throw an exception.
+   */
+  static function verify_csrf() {
+    $input = Input::instance();
+    if ($input->post("csrf", $input->get("csrf", null)) !== Session::instance()->get("csrf")) {
+      access::forbidden();
+    }
+  }
+
+  /**
+   * Get the Cross Site Request Forgery token for this session.
+   * @return string
+   */
+  static function csrf_token() {
+    $session = Session::instance();
+    $csrf = $session->get("csrf");
+    if (empty($csrf)) {
+      $csrf = random::hash();
+      $session->set("csrf", $csrf);
+    }
+    return $csrf;
+  }
+
+  /**
+   * Generate an <input> element containing the Cross Site Request Forgery token for this session.
+   * @return string
+   */
+  static function csrf_form_field() {
+    return "<input type=\"hidden\" name=\"csrf\" value=\"" . access::csrf_token() . "\"/>";
+  }
+
+  /**
+   * Internal method to get all available groups.
+   *
+   * @return ORM_Iterator
+   */
+  private static function _get_all_groups() {
+    // When we build the gallery package, it's possible that there is no identity provider
+    // installed yet.  This is ok at packaging time, so work around it.
+   if (module::is_active(module::get_var("gallery", "identity_provider", "user"))) {
+      return identity::groups();
+    } else {
+      return array();
+    }
+  }
+
+  /**
+   * Internal method to  remove Permission/Group columns
+   *
+   * @param  Group_Model $group
+   * @param  string      $perm_name
+   * @return void
+   */
+  private static function _drop_columns($perm_name, $group) {
+    $field = "{$perm_name}_{$group->id}";
+    $cache_table = $perm_name == "view" ? "items" : "access_caches";
+    Database::instance()->query("ALTER TABLE {{$cache_table}} DROP `$field`");
+    Database::instance()->query("ALTER TABLE {access_intents} DROP `$field`");
+    model_cache::clear();
+    ORM::factory("access_intent")->clear_cache();
+  }
+
+  /**
+   * Internal method to add Permission/Group columns
+   *
+   * @param  Group_Model $group
+   * @param  string  $perm_name
+   * @return void
+   */
+  private static function _add_columns($perm_name, $group) {
+    $field = "{$perm_name}_{$group->id}";
+    $cache_table = $perm_name == "view" ? "items" : "access_caches";
+    $not_null = $cache_table == "items" ? "" : "NOT NULL";
+    Database::instance()->query(
+      "ALTER TABLE {{$cache_table}} ADD `$field` BINARY $not_null DEFAULT FALSE");
+    Database::instance()->query(
+      "ALTER TABLE {access_intents} ADD `$field` BINARY DEFAULT NULL");
+    db::build()
+      ->update("access_intents")
+      ->set($field, access::DENY)
+      ->where("item_id", "=", 1)
+      ->execute();
+    model_cache::clear();
+    ORM::factory("access_intent")->clear_cache();
+  }
+
+  /**
+   * Update the Access_Cache model based on information from the Access_Intent model for view
+   * permissions only.
+   *
+   * @todo: use database locking
+   *
+   * @param  Group_Model $group
+   * @param  Item_Model $item
+   * @return void
+   */
+  private static function _update_access_view_cache($group, $item) {
+    $access = ORM::factory("access_intent")->where("item_id", "=", $item->id)->find();
+    $field = "view_{$group->id}";
+
+    // With view permissions, deny values in the parent can override allow values in the child,
+    // so start from the bottom of the tree and work upwards overlaying negative on top of
+    // positive.
+    //
+    // If the item's intent is ALLOW or DEFAULT, it's possible that some ancestor has specified
+    // DENY and this ALLOW cannot be obeyed.  So in that case, back up the tree and find any
+    // non-DEFAULT and non-ALLOW parent and propagate from there.  If we can't find a matching
+    // item, then its safe to propagate from here.
+    if ($access->$field !== access::DENY) {
+      $tmp_item = ORM::factory("item")
+        ->where("left_ptr", "<", $item->left_ptr)
+        ->where("right_ptr", ">", $item->right_ptr)
+        ->join("access_intents", "access_intents.item_id", "items.id")
+        ->where("access_intents.$field", "=", access::DENY)
+        ->order_by("left_ptr", "DESC")
+        ->limit(1)
+        ->find();
+      if ($tmp_item->loaded()) {
+        $item = $tmp_item;
+      }
+    }
+
+    // We will have a problem if we're trying to change a DENY to an ALLOW because the
+    // access_caches table will already contain DENY values and we won't be able to overwrite
+    // them according the rule above.  So mark every permission below this level as UNKNOWN so
+    // that we can tell which permissions have been changed, and which ones need to be updated.
+    db::build()
+      ->update("items")
+      ->set($field, access::UNKNOWN)
+      ->where("left_ptr", ">=", $item->left_ptr)
+      ->where("right_ptr", "<=", $item->right_ptr)
+      ->execute();
+
+    $query = ORM::factory("access_intent")
+      ->select(array("access_intents.$field", "items.left_ptr", "items.right_ptr", "items.id"))
+      ->join("items", "items.id", "access_intents.item_id")
+      ->where("left_ptr", ">=", $item->left_ptr)
+      ->where("right_ptr", "<=", $item->right_ptr)
+      ->where("type", "=", "album")
+      ->where("access_intents.$field", "IS NOT", access::INHERIT)
+      ->order_by("level", "DESC")
+      ->find_all();
+    foreach ($query as $row) {
+      if ($row->$field == access::ALLOW) {
+        // Propagate ALLOW for any row that is still UNKNOWN.
+        db::build()
+          ->update("items")
+          ->set($field, $row->$field)
+          ->where($field, "IS", access::UNKNOWN) // UNKNOWN is NULL so we have to use IS
+          ->where("left_ptr", ">=", $row->left_ptr)
+          ->where("right_ptr", "<=", $row->right_ptr)
+          ->execute();
+      } else if ($row->$field == access::DENY) {
+        // DENY overwrites everything below it
+        db::build()
+          ->update("items")
+          ->set($field, $row->$field)
+          ->where("left_ptr", ">=", $row->left_ptr)
+          ->where("right_ptr", "<=", $row->right_ptr)
+          ->execute();
+      }
+    }
+
+    // Finally, if our intent is DEFAULT at this point it means that we were unable to find a
+    // DENY parent in the hierarchy to propagate from.  So we'll still have a UNKNOWN values in
+    // the hierarchy, and all of those are safe to change to ALLOW.
+    db::build()
+      ->update("items")
+      ->set($field, access::ALLOW)
+      ->where($field, "IS", access::UNKNOWN) // UNKNOWN is NULL so we have to use IS
+      ->where("left_ptr", ">=", $item->left_ptr)
+      ->where("right_ptr", "<=", $item->right_ptr)
+      ->execute();
+  }
+
+  /**
+   * Update the Access_Cache model based on information from the Access_Intent model for non-view
+   * permissions.
+   *
+   * @todo: use database locking
+   *
+   * @param  Group_Model $group
+   * @param  string  $perm_name
+   * @param  Item_Model $item
+   * @return void
+   */
+  private static function _update_access_non_view_cache($group, $perm_name, $item) {
+    $access = ORM::factory("access_intent")->where("item_id", "=", $item->id)->find();
+
+    $field = "{$perm_name}_{$group->id}";
+
+    // If the item's intent is DEFAULT, then we need to back up the chain to find the nearest
+    // parent with an intent and propagate from there.
+    //
+    // @todo To optimize this, we wouldn't need to propagate from the parent, we could just
+    //       propagate from here with the parent's intent.
+    if ($access->$field === access::INHERIT) {
+      $tmp_item = ORM::factory("item")
+        ->join("access_intents", "items.id", "access_intents.item_id")
+        ->where("left_ptr", "<", $item->left_ptr)
+        ->where("right_ptr", ">", $item->right_ptr)
+        ->where($field, "IS NOT", access::UNKNOWN) // UNKNOWN is NULL so we have to use IS NOT
+        ->order_by("left_ptr", "DESC")
+        ->limit(1)
+        ->find();
+      if ($tmp_item->loaded()) {
+        $item = $tmp_item;
+      }
+    }
+
+    // With non-view permissions, each level can override any permissions that came above it
+    // so start at the top and work downwards, overlaying permissions as we go.
+    $query = ORM::factory("access_intent")
+      ->select(array("access_intents.$field", "items.left_ptr", "items.right_ptr"))
+      ->join("items", "items.id", "access_intents.item_id")
+      ->where("left_ptr", ">=", $item->left_ptr)
+      ->where("right_ptr", "<=", $item->right_ptr)
+      ->where($field, "IS NOT", access::INHERIT)
+      ->order_by("level", "ASC")
+      ->find_all();
+    foreach ($query as $row) {
+      $value = ($row->$field === access::ALLOW) ? true : false;
+      db::build()
+        ->update("access_caches")
+        ->set($field, $value)
+        ->where("item_id", "IN",
+                db::build()
+                ->select("id")
+                ->from("items")
+                ->where("left_ptr", ">=", $row->left_ptr)
+                ->where("right_ptr", "<=", $row->right_ptr))
+        ->execute();
+    }
+  }
+
+  /**
+   * Rebuild the .htaccess files that prevent direct access to albums, resizes and thumbnails.  We
+   * call this internally any time we change the view or view_full permissions for guest users.
+   * This function is only public because we use it in maintenance tasks.
+   *
+   * @param  Item_Model   the album
+   * @param  Group_Model  the group whose permission is changing
+   * @param  string       the permission name
+   * @param  string       the new permission value (eg access::DENY)
+   */
+  static function update_htaccess_files($album, $group, $perm_name, $value) {
+    if ($group->id != identity::everybody()->id ||
+        !($perm_name == "view" || $perm_name == "view_full")) {
+      return;
+    }
+
+    $dirs = array($album->file_path());
+    if ($perm_name == "view") {
+      $dirs[] = dirname($album->resize_path());
+      $dirs[] = dirname($album->thumb_path());
+    }
+
+    $base_url = url::base(true);
+    $sep = "?";
+    if (strpos($base_url, "?") !== false) {
+      $sep = "&";
+    }
+    $base_url .= $sep . "kohana_uri=/file_proxy";
+    // Replace "/index.php/?kohana..." with "/index.php?koahan..."
+    // Doesn't apply to "/?kohana..." or "/foo/?kohana..."
+    // Can't check for "index.php" since the file might be renamed, and
+    // there might be more Apache aliases / rewrites at work.
+    $url_path = parse_url($base_url, PHP_URL_PATH);
+    // Does the URL path have a file component?
+    if (preg_match("#[^/]+\.php#i", $url_path)) {
+      $base_url = str_replace("/?", "?", $base_url);
+    }
+
+    foreach ($dirs as $dir) {
+      if ($value === access::DENY) {
+        $fp = fopen("$dir/.htaccess", "w+");
+        fwrite($fp, "<IfModule mod_rewrite.c>\n");
+        fwrite($fp, "  RewriteEngine On\n");
+        fwrite($fp, "  RewriteRule (.*) $base_url/\$1 [L]\n");
+        fwrite($fp, "</IfModule>\n");
+        fwrite($fp, "<IfModule !mod_rewrite.c>\n");
+        fwrite($fp, "  Order Deny,Allow\n");
+        fwrite($fp, "  Deny from All\n");
+        fwrite($fp, "</IfModule>\n");
+        fclose($fp);
+      } else {
+        @unlink($dir . "/.htaccess");
+      }
+    }
+  }
+
+  static function private_key() {
+    return module::get_var("gallery", "private_key");
+  }
+
+  /**
+   * Verify that our htaccess based permission system actually works.  Create a temporary
+   * directory containing an .htaccess file that uses mod_rewrite to redirect /verify to
+   * /success.  Then request that url.  If we retrieve it successfully, then our redirects are
+   * working and our permission system works.
+   */
+  static function htaccess_works() {
+    $success_url = url::file("var/security_test/success");
+
+    @mkdir(VARPATH . "security_test");
+    try {
+      if ($fp = @fopen(VARPATH . "security_test/.htaccess", "w+")) {
+        fwrite($fp, "Options +FollowSymLinks\n");
+        fwrite($fp, "RewriteEngine On\n");
+        fwrite($fp, "RewriteRule verify $success_url [L]\n");
+        fclose($fp);
+      }
+
+      if ($fp = @fopen(VARPATH . "security_test/success", "w+")) {
+        fwrite($fp, "success");
+        fclose($fp);
+      }
+
+      // Proxy our authorization headers so that if the entire Gallery is covered by Basic Auth
+      // this callback will still work.
+      $headers = array();
+      if (function_exists("apache_request_headers")) {
+        $arh = apache_request_headers();
+        if (!empty($arh["Authorization"])) {
+          $headers["Authorization"] = $arh["Authorization"];
+        }
+      }
+      list ($status, $headers, $body) =
+        remote::do_request(url::abs_file("var/security_test/verify"), "GET", $headers);
+      $works = ($status == "HTTP/1.1 200 OK") && ($body == "success");
+    } catch (Exception $e) {
+      @dir::unlink(VARPATH . "security_test");
+      throw $e;
+    }
+    @dir::unlink(VARPATH . "security_test");
+
+    return $works;
+  }
+}
diff --git a/modules/gallery/helpers/ajax.php b/modules/gallery/helpers/ajax.php
new file mode 100644
index 0000000..0c69fe7
--- /dev/null
+++ b/modules/gallery/helpers/ajax.php
@@ -0,0 +1,31 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class ajax_Core {
+  /**
+   * Encode an Ajax response so that it's UTF-7 safe.
+   *
+   * @param  string $message string to print
+   */
+  static function response($content) {
+    header("Content-Type: text/plain; charset=" . Kohana::CHARSET);
+    print "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n";
+    print $content;
+  }
+}
diff --git a/modules/gallery/helpers/album.php b/modules/gallery/helpers/album.php
new file mode 100644
index 0000000..23aed8a
--- /dev/null
+++ b/modules/gallery/helpers/album.php
@@ -0,0 +1,126 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling albums.
+ *
+ * Note: by design, this class does not do any permission checking.
+ */
+class album_Core {
+
+  static function get_add_form($parent) {
+    $form = new Forge("albums/create/{$parent->id}", "", "post", array("id" => "g-add-album-form"));
+    $group = $form->group("add_album")
+      ->label(t("Add an album to %album_title", array("album_title" => $parent->title)));
+    $group->input("title")->label(t("Title"))
+      ->error_messages("required", t("You must provide a title"))
+      ->error_messages("length", t("Your title is too long"));
+    $group->textarea("description")->label(t("Description"));
+    $group->input("name")->label(t("Directory name"))
+      ->error_messages("no_slashes", t("The directory name can't contain the \"/\" character"))
+      ->error_messages("required", t("You must provide a directory name"))
+      ->error_messages("length", t("Your directory name is too long"))
+      ->error_messages("conflict", t("There is already a movie, photo or album with this name"));
+    $group->input("slug")->label(t("Internet Address"))
+      ->error_messages(
+        "reserved", t("This address is reserved and can't be used."))
+      ->error_messages(
+        "not_url_safe",
+        t("The internet address should contain only letters, numbers, hyphens and underscores"))
+      ->error_messages("required", t("You must provide an internet address"))
+      ->error_messages("length", t("Your internet address is too long"));
+    $group->hidden("type")->value("album");
+
+    module::event("album_add_form", $parent, $form);
+
+    $group->submit("")->value(t("Create"));
+    $form->script("")
+      ->url(url::abs_file("modules/gallery/js/albums_form_add.js"));
+
+    return $form;
+  }
+
+  static function get_edit_form($parent) {
+    $form = new Forge(
+      "albums/update/{$parent->id}", "", "post", array("id" => "g-edit-album-form"));
+    $form->hidden("from_id")->value($parent->id);
+    $group = $form->group("edit_item")->label(t("Edit Album"));
+
+    $group->input("title")->label(t("Title"))->value($parent->title)
+        ->error_messages("required", t("You must provide a title"))
+      ->error_messages("length", t("Your title is too long"));
+    $group->textarea("description")->label(t("Description"))->value($parent->description);
+    if ($parent->id != 1) {
+      $group->input("name")->label(t("Directory Name"))->value($parent->name)
+        ->error_messages("conflict", t("There is already a movie, photo or album with this name"))
+        ->error_messages("no_slashes", t("The directory name can't contain a \"/\""))
+        ->error_messages("no_trailing_period", t("The directory name can't end in \".\""))
+        ->error_messages("required", t("You must provide a directory name"))
+        ->error_messages("length", t("Your directory name is too long"));
+      $group->input("slug")->label(t("Internet Address"))->value($parent->slug)
+        ->error_messages(
+          "conflict", t("There is already a movie, photo or album with this internet address"))
+        ->error_messages(
+          "reserved", t("This address is reserved and can't be used."))
+        ->error_messages(
+          "not_url_safe",
+          t("The internet address should contain only letters, numbers, hyphens and underscores"))
+        ->error_messages("required", t("You must provide an internet address"))
+        ->error_messages("length", t("Your internet address is too long"));
+    } else {
+      $group->hidden("name")->value($parent->name);
+      $group->hidden("slug")->value($parent->slug);
+    }
+
+    $sort_order = $group->group("sort_order", array("id" => "g-album-sort-order"))
+      ->label(t("Sort Order"));
+
+    $sort_order->dropdown("column", array("id" => "g-album-sort-column"))
+      ->label(t("Sort by"))
+      ->options(album::get_sort_order_options())
+      ->selected($parent->sort_column);
+    $sort_order->dropdown("direction", array("id" => "g-album-sort-direction"))
+      ->label(t("Order"))
+      ->options(array("ASC" => t("Ascending"),
+                      "DESC" => t("Descending")))
+      ->selected($parent->sort_order);
+
+    module::event("item_edit_form", $parent, $form);
+
+    $group = $form->group("buttons")->label("");
+    $group->hidden("type")->value("album");
+    $group->submit("")->value(t("Modify"));
+    return $form;
+  }
+
+  /**
+   * Return a structured set of all the possible sort orders.
+   */
+  static function get_sort_order_options() {
+    return array("weight" => t("Manual"),
+                 "captured" => t("Date captured"),
+                 "created" => t("Date uploaded"),
+                 "title" => t("Title"),
+                 "name" => t("File name"),
+                 "updated" => t("Date modified"),
+                 "view_count" => t("Number of views"),
+                 "rand_key" => t("Random"));
+  }
+}
diff --git a/modules/gallery/helpers/auth.php b/modules/gallery/helpers/auth.php
new file mode 100644
index 0000000..2eb3c25
--- /dev/null
+++ b/modules/gallery/helpers/auth.php
@@ -0,0 +1,134 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class auth_Core {
+  static function get_login_form($url) {
+    $form = new Forge($url, "", "post", array("id" => "g-login-form"));
+    $form->set_attr("class", "g-narrow");
+    $form->hidden("continue_url")->value(Session::instance()->get("continue_url"));
+    $group = $form->group("login")->label(t("Login"));
+    $group->input("name")->label(t("Username"))->id("g-username")->class(null)
+      ->callback("auth::validate_too_many_failed_logins")
+      ->error_messages(
+        "too_many_failed_logins", t("Too many failed login attempts.  Try again later"));
+    $group->password("password")->label(t("Password"))->id("g-password")->class(null);
+    $group->inputs["name"]->error_messages("invalid_login", t("Invalid name or password"));
+    $group->submit("")->value(t("Login"));
+    return $form;
+  }
+
+  static function login($user) {
+    identity::set_active_user($user);
+    if (identity::is_writable()) {
+      $user->login_count += 1;
+      $user->last_login = time();
+      $user->save();
+    }
+    log::info("user", t("User %name logged in", array("name" => $user->name)));
+    module::event("user_login", $user);
+  }
+
+  static function logout() {
+    $user = identity::active_user();
+    if (!$user->guest) {
+      try {
+        Session::instance()->destroy();
+      } catch (Exception $e) {
+        Kohana_Log::add("error", $e);
+      }
+      module::event("user_logout", $user);
+    }
+    log::info("user", t("User %name logged out", array("name" => $user->name)),
+              t('<a href="%url">%user_name</a>',
+                array("url" => user_profile::url($user->id),
+                      "user_name" => html::clean($user->name))));
+  }
+
+  /**
+   * After there have been 5 failed auth attempts, any failure leads to getting locked out for a
+   * minute.
+   */
+  static function too_many_failures($name) {
+    $failed = ORM::factory("failed_auth")
+      ->where("name", "=", $name)
+      ->find();
+    return ($failed->loaded() &&
+            $failed->count > 5 &&
+            (time() - $failed->time < 60));
+  }
+
+  static function validate_too_many_failed_logins($name_input) {
+    if (auth::too_many_failures($name_input->value)) {
+      $name_input->add_error("too_many_failed_logins", 1);
+    }
+  }
+
+  static function validate_too_many_failed_auth_attempts($form_input) {
+    if (auth::too_many_failures(identity::active_user()->name)) {
+      $form_input->add_error("too_many_failed_auth_attempts", 1);
+    }
+  }
+
+  /**
+   * Record a failed authentication for this user
+   */
+  static function record_failed_attempt($name) {
+    $failed = ORM::factory("failed_auth")
+      ->where("name", "=", $name)
+      ->find();
+    if (!$failed->loaded()) {
+      $failed->name = $name;
+    }
+    $failed->time = time();
+    $failed->count++;
+    $failed->save();
+  }
+
+  /**
+   * Clear any failed logins for this user
+   */
+  static function clear_failed_attempts($user) {
+    ORM::factory("failed_auth")
+      ->where("name", "=", $user->name)
+      ->delete_all();
+  }
+
+  /**
+   * Checks whether the current user (= admin) must
+   * actively re-authenticate before access is given
+   * to the admin area.
+   */
+  static function must_reauth_for_admin_area() {
+    if (!identity::active_user()->admin) {
+      access::forbidden();
+    }
+
+    $session = Session::instance();
+    $last_active_auth = $session->get("active_auth_timestamp", 0);
+    $last_admin_area_activity = $session->get("admin_area_activity_timestamp", 0);
+    $admin_area_timeout = module::get_var("gallery", "admin_area_timeout");
+
+    if (max($last_active_auth, $last_admin_area_activity) + $admin_area_timeout < time()) {
+      return true;
+    }
+
+    $session->set("admin_area_activity_timestamp", time());
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/batch.php b/modules/gallery/helpers/batch.php
new file mode 100644
index 0000000..bf2425e
--- /dev/null
+++ b/modules/gallery/helpers/batch.php
@@ -0,0 +1,40 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class batch_Core {
+  static function start() {
+    $session = Session::instance();
+    $session->set("batch_level", $session->get("batch_level", 0) + 1);
+  }
+
+  static function stop() {
+    $session = Session::instance();
+    $batch_level = $session->get("batch_level", 0) - 1;
+    if ($batch_level > 0) {
+      $session->set("batch_level", $batch_level);
+    } else {
+      $session->delete("batch_level");
+      module::event("batch_complete");
+    }
+  }
+
+  static function in_progress() {
+    return Session::instance()->get("batch_level", 0) > 0;
+  }
+}
diff --git a/modules/gallery/helpers/block_manager.php b/modules/gallery/helpers/block_manager.php
new file mode 100644
index 0000000..a227946
--- /dev/null
+++ b/modules/gallery/helpers/block_manager.php
@@ -0,0 +1,115 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class block_manager_Core {
+  static function get_active($location) {
+    return unserialize(module::get_var("gallery", "blocks_$location", "a:0:{}"));
+  }
+
+  static function set_active($location, $blocks) {
+    module::set_var("gallery", "blocks_$location", serialize($blocks));
+  }
+
+  static function add($location, $module_name, $block_id) {
+    $blocks = block_manager::get_active($location);
+    $blocks[random::int()] = array($module_name, $block_id);
+
+    block_manager::set_active($location, $blocks);
+  }
+
+  static function activate_blocks($module_name) {
+    $block_class = "{$module_name}_block";
+    if (class_exists($block_class) && method_exists($block_class, "get_site_list")) {
+      $blocks = call_user_func(array($block_class, "get_site_list"));
+      foreach (array_keys($blocks) as $block_id) {
+        block_manager::add("site_sidebar", $module_name, $block_id);
+      }
+    }
+  }
+
+  static function remove($location, $block_id) {
+    $blocks = block_manager::get_active($location);
+    unset($blocks[$block_id]);
+    block_manager::set_active($location, $blocks);
+  }
+
+  static function remove_blocks_for_module($location, $module_name) {
+    $blocks = block_manager::get_active($location);
+    foreach ($blocks as $key => $block) {
+      if ($block[0] == $module_name) {
+        unset($blocks[$key]);
+      }
+    }
+    block_manager::set_active($location, $blocks);
+  }
+
+  static function deactivate_blocks($module_name) {
+    $block_class = "{$module_name}_block";
+    if (class_exists($block_class) && method_exists($block_class, "get_site_list")) {
+      $blocks = call_user_func(array($block_class, "get_site_list"));
+      foreach  (array_keys($blocks) as $block_id) {
+        block_manager::remove_blocks_for_module("site_sidebar", $module_name);
+      }
+    }
+
+    if (class_exists($block_class) && method_exists($block_class, "get_admin_list")) {
+      $blocks = call_user_func(array($block_class, "get_admin_list"));
+      foreach (array("dashboard_sidebar", "dashboard_center") as $location) {
+        block_manager::remove_blocks_for_module($location, $module_name);
+      }
+    }
+  }
+
+  static function get_available_admin_blocks() {
+    return self::_get_blocks("get_admin_list");
+  }
+
+  static function get_available_site_blocks() {
+    return self::_get_blocks("get_site_list");
+  }
+
+  private static function _get_blocks($function) {
+    $blocks = array();
+
+    foreach (module::active() as $module) {
+      $class_name = "{$module->name}_block";
+      if (class_exists($class_name) && method_exists($class_name, $function)) {
+        foreach (call_user_func(array($class_name, $function)) as $id => $title) {
+          $blocks["{$module->name}:$id"] = $title;
+        }
+      }
+    }
+    return $blocks;
+  }
+
+  static function get_html($location, $theme=null) {
+    $active = block_manager::get_active($location);
+    $result = "";
+    foreach ($active as $id => $desc) {
+      if (class_exists("$desc[0]_block") && method_exists("$desc[0]_block", "get")) {
+        $block = call_user_func(array("$desc[0]_block", "get"), $desc[1], $theme);
+        if (!empty($block)) {
+          $block->id = $id;
+          $result .= $block;
+        }
+      }
+    }
+    return $result;
+  }
+}
diff --git a/modules/gallery/helpers/data_rest.php b/modules/gallery/helpers/data_rest.php
new file mode 100644
index 0000000..a0a225f
--- /dev/null
+++ b/modules/gallery/helpers/data_rest.php
@@ -0,0 +1,115 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * This resource returns the raw contents of Item_Model data files.  It's analogous to the
+ * file_proxy controller, but it uses the REST authentication model.
+ */
+class data_rest_Core {
+  static function get($request) {
+    $item = rest::resolve($request->url);
+
+    $p = $request->params;
+    if (!isset($p->size) || !in_array($p->size, array("thumb", "resize", "full"))) {
+      throw new Rest_Exception("Bad Request", 400, array("errors" => array("size" => "invalid")));
+    }
+
+    // Note: this code is roughly duplicated in file_proxy, so if you modify this, please look to
+    // see if you should make the same change there as well.
+
+    if ($p->size == "full") {
+      if ($item->is_album()) {
+        throw new Kohana_404_Exception();
+      }
+      access::required("view_full", $item);
+      $file = $item->file_path();
+    } else if ($p->size == "resize") {
+      access::required("view", $item);
+      $file = $item->resize_path();
+    } else {
+      access::required("view", $item);
+      $file = $item->thumb_path();
+    }
+
+    if (!file_exists($file)) {
+      throw new Kohana_404_Exception();
+    }
+
+    header("Content-Length: " . filesize($file));
+
+    if (isset($p->m)) {
+      header("Pragma:");
+      // Check that the content hasn't expired or it wasn't changed since cached
+      expires::check(2592000, $item->updated);
+
+      expires::set(2592000, $item->updated);  // 30 days
+    }
+
+    // We don't need to save the session for this request
+    Session::instance()->abort_save();
+
+    // Dump out the image.  If the item is a movie or album, then its thumbnail will be a JPG.
+    if (($item->is_movie() || $item->is_album()) && $p->size == "thumb") {
+      header("Content-Type: image/jpeg");
+    } else {
+      header("Content-Type: $item->mime_type");
+    }
+
+    if (TEST_MODE) {
+      return $file;
+    } else {
+      Kohana::close_buffers(false);
+
+      if (isset($p->encoding) && $p->encoding == "base64") {
+        print base64_encode(file_get_contents($file));
+      } else {
+        readfile($file);
+      }
+    }
+
+    // We must exit here to keep the regular REST framework reply code from adding more bytes on
+    // at the end or tinkering with headers.
+    exit;
+  }
+
+  static function resolve($id) {
+    $item = ORM::factory("item", $id);
+    if (!access::can("view", $item)) {
+      throw new Kohana_404_Exception();
+    }
+    return $item;
+  }
+
+  static function url($item, $size) {
+    if ($size == "full") {
+      $file = $item->file_path();
+    } else if ($size == "resize") {
+      $file = $item->resize_path();
+    } else {
+      $file = $item->thumb_path();
+    }
+    if (!file_exists($file)) {
+      throw new Kohana_404_Exception();
+    }
+
+    return url::abs_site("rest/data/{$item->id}?size=$size&m=" . filemtime($file));
+  }
+}
+
diff --git a/modules/gallery/helpers/dir.php b/modules/gallery/helpers/dir.php
new file mode 100644
index 0000000..807f7bd
--- /dev/null
+++ b/modules/gallery/helpers/dir.php
@@ -0,0 +1,40 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class dir_Core {
+  static function unlink($path) {
+    if (is_dir($path) && is_writable($path)) {
+      foreach (new DirectoryIterator($path) as $resource) {
+        if ($resource->isDot()) {
+          unset($resource);
+          continue;
+        } else if ($resource->isFile()) {
+          unlink($resource->getPathName());
+        } else if ($resource->isDir()) {
+          dir::unlink($resource->getRealPath());
+        }
+        unset($resource);
+      }
+      return @rmdir($path);
+    }
+    return false;
+  }
+
+
+}
diff --git a/modules/gallery/helpers/encoding.php b/modules/gallery/helpers/encoding.php
new file mode 100644
index 0000000..073aef9
--- /dev/null
+++ b/modules/gallery/helpers/encoding.php
@@ -0,0 +1,35 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class encoding_Core {
+  static function convert_to_utf8($value) {
+    if (function_exists("mb_detect_encoding")) {
+      // Rely on mb_detect_encoding()'s strict mode
+      $src_encoding = mb_detect_encoding($value, mb_detect_order(), true);
+      if ($src_encoding != "UTF-8") {
+        if (function_exists("mb_convert_encoding") && $src_encoding) {
+          $value = mb_convert_encoding($value, "UTF-8", $src_encoding);
+        } else {
+          $value = utf8_encode($value);
+        }
+      }
+    }
+    return $value;
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/gallery.php b/modules/gallery/helpers/gallery.php
new file mode 100644
index 0000000..0adabe4
--- /dev/null
+++ b/modules/gallery/helpers/gallery.php
@@ -0,0 +1,233 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class gallery_Core {
+  const VERSION = "3.0.9";
+  const CODE_NAME = "Chartres";
+  const RELEASE_CHANNEL = "release";
+  const RELEASE_BRANCH = "3.0.x";
+
+  /**
+   * If Gallery is in maintenance mode, then force all non-admins to get routed to a "This site is
+   * down for maintenance" page.
+   */
+  static function maintenance_mode() {
+    if (module::get_var("gallery", "maintenance_mode", 0) &&
+        !identity::active_user()->admin) {
+      try {
+        $class = new ReflectionClass(ucfirst(Router::$controller).'_Controller');
+        $allowed = $class->getConstant("ALLOW_MAINTENANCE_MODE") === true;
+      } catch (ReflectionClass $e) {
+        $allowed = false;
+      }
+      if (!$allowed) {
+        if (Router::$controller == "admin") {
+          // At this point we're in the admin theme and it doesn't have a themed login page, so
+          // we can't just swap in the login controller and have it work.  So redirect back to the
+          // root item where we'll run this code again with the site theme.
+          url::redirect(item::root()->abs_url());
+        } else {
+          Session::instance()->set("continue_url", url::abs_site("admin/maintenance"));
+          Router::$controller = "login";
+          Router::$controller_path = MODPATH . "gallery/controllers/login.php";
+          Router::$method = "html";
+        }
+      }
+    }
+  }
+
+  /**
+   * If the gallery is only available to registered users and the user is not logged in, present
+   * the login page.
+   */
+  static function private_gallery() {
+    if (identity::active_user()->guest &&
+        !access::user_can(identity::guest(), "view", item::root()) &&
+        php_sapi_name() != "cli") {
+      try {
+        $class = new ReflectionClass(ucfirst(Router::$controller).'_Controller');
+        $allowed = $class->getConstant("ALLOW_PRIVATE_GALLERY") === true;
+      } catch (ReflectionClass $e) {
+        $allowed = false;
+      }
+      if (!$allowed) {
+        if (Router::$controller == "admin") {
+          // At this point we're in the admin theme and it doesn't have a themed login page, so
+          // we can't just swap in the login controller and have it work.  So redirect back to the
+          // root item where we'll run this code again with the site theme.
+          url::redirect(item::root()->abs_url());
+        } else {
+          Session::instance()->set("continue_url", url::abs_current());
+          Router::$controller = "login";
+          Router::$controller_path = MODPATH . "gallery/controllers/login.php";
+          Router::$method = "html";
+        }
+      }
+    }
+  }
+
+  /**
+   * This function is called when the Gallery is fully initialized.  We relay it to modules as the
+   * "gallery_ready" event.  Any module that wants to perform an action at the start of every
+   * request should implement the <module>_event::gallery_ready() handler.
+   */
+  static function ready() {
+    // Don't keep a session for robots; it's a waste of database space.
+    if (request::user_agent("robot")) {
+      Session::instance()->abort_save();
+    }
+
+    module::event("gallery_ready");
+  }
+
+  /**
+   * This function is called right before the Kohana framework shuts down.  We relay it to modules
+   * as the "gallery_shutdown" event.  Any module that wants to perform an action at the start of
+   * every request should implement the <module>_event::gallery_shutdown() handler.
+   */
+  static function shutdown() {
+    module::event("gallery_shutdown");
+  }
+
+  /**
+   * Return a unix timestamp in a user specified format including date and time.
+   * @param $timestamp unix timestamp
+   * @return string
+   */
+  static function date_time($timestamp) {
+    return date(module::get_var("gallery", "date_time_format"), $timestamp);
+  }
+
+  /**
+   * Return a unix timestamp in a user specified format that's just the date.
+   * @param $timestamp unix timestamp
+   * @return string
+   */
+  static function date($timestamp) {
+    return date(module::get_var("gallery", "date_format"), $timestamp);
+  }
+
+  /**
+   * Return a unix timestamp in a user specified format that's just the time.
+   * @param $timestamp unix timestamp
+   * @return string
+   */
+  static function time($timestamp) {
+    return date(module::get_var("gallery", "time_format", "H:i:s"), $timestamp);
+  }
+
+  /**
+   * Provide a wrapper function for Kohana::find_file that first strips the extension and
+   * then calls the Kohana::find_file and supplies the extension as the type.
+   * @param   string   directory to search in
+   * @param   string   filename to look for
+   * @param   boolean  file required (optional: default false)
+   * @return  array    if the extension is config, i18n or l10n
+   * @return  string   if the file is found (relative to the DOCROOT)
+   * @return  false    if the file is not found
+   */
+  static function find_file($directory, $file, $required=false) {
+    $file_name = substr($file, 0, -strlen($ext = strrchr($file, '.')));
+    $file_name = Kohana::find_file($directory, $file_name, $required, substr($ext, 1));
+    if (!$file_name) {
+      if (file_exists(DOCROOT . "lib/$directory/$file")) {
+        return "lib/$directory/$file";
+      } else if (file_exists(DOCROOT . "lib/$file")) {
+        return "lib/$file";
+      }
+    }
+
+    if (is_string($file_name)) {
+      // make relative to DOCROOT
+      $parts = explode("/", $file_name);
+      $count = count($parts);
+      foreach ($parts as $idx => $part) {
+        // If this part is "modules" or "themes" make sure that the part 2 after this
+        // is the target directory, and if it is then we're done.  This check makes
+        // sure that if Gallery is installed in a directory called "modules" or "themes"
+        // We don't parse the directory structure incorrectly.
+        if (in_array($part, array("modules", "themes")) &&
+            $idx + 2 < $count &&
+            $parts[$idx + 2] == $directory) {
+          break;
+        }
+        unset($parts[$idx]);
+      }
+      $file_name = implode("/", $parts);
+    }
+    return $file_name;
+  }
+
+  /**
+   * Set the PATH environment variable to the paths specified.
+   * @param  array   Array of paths.  Each array entry can contain a colon separated list of paths.
+   */
+  static function set_path_env($paths) {
+    $path_env = array();
+    foreach ($paths as $path) {
+      if ($path) {
+        array_push($path_env, $path);
+      }
+    }
+    putenv("PATH=" .  implode(":", $path_env));
+  }
+
+  /**
+   * Return a string describing this version of Gallery and the type of release.
+   */
+  static function version_string() {
+    if (gallery::RELEASE_CHANNEL == "git") {
+      $build_number = gallery::build_number();
+      return sprintf(
+        "%s (branch %s, %s)", gallery::VERSION, gallery::RELEASE_BRANCH,
+        $build_number ? " build $build_number" : "unknown build number");
+    } else {
+      return sprintf("%s (%s)", gallery::VERSION, gallery::CODE_NAME);
+    }
+  }
+
+  /**
+   * Return the contents of the .build_number file, which should be a single integer
+   * or return null if the .build_number file is missing.
+   */
+  static function build_number() {
+    $build_file = DOCROOT . ".build_number";
+    if (file_exists($build_file))  {
+      $result = parse_ini_file(DOCROOT . ".build_number");
+      return $result["build_number"];
+    }
+    return null;
+  }
+
+  /**
+   * Return true if we should show the profiler at the bottom of the page.  Note that this
+   * function is called at database setup time so it cannot rely on the database.
+   */
+  static function show_profiler() {
+    return file_exists(VARPATH . "PROFILE");
+  }
+
+  /**
+   * Return true if we should allow Javascript and CSS combining for performance reasons.
+   * Typically we want this, but it's convenient for developers to be able to disable it.
+   */
+  static function allow_css_and_js_combining() {
+    return !file_exists(VARPATH . "DONT_COMBINE");
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/gallery_block.php b/modules/gallery/helpers/gallery_block.php
new file mode 100644
index 0000000..5ac4d74
--- /dev/null
+++ b/modules/gallery/helpers/gallery_block.php
@@ -0,0 +1,145 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class gallery_block_Core {
+  static function get_admin_list() {
+    return array(
+      "welcome" => t("Welcome to Gallery 3!"),
+      "photo_stream" => t("Photo stream"),
+      "log_entries" => t("Log entries"),
+      "stats" => t("Gallery stats"),
+      "platform_info" => t("Platform information"),
+      "project_news" => t("Gallery project news"),
+      "upgrade_checker" => t("Check for Gallery upgrades")
+    );
+  }
+
+  static function get_site_list() {
+    return array("language" => t("Language preference"));
+  }
+
+  static function get($block_id) {
+    $block = new Block();
+    switch ($block_id) {
+    case "welcome":
+      $block->css_id = "g-welcome";
+      $block->title = t("Welcome to Gallery 3");
+      $block->content = new View("admin_block_welcome.html");
+      break;
+
+    case "photo_stream":
+      $block->css_id = "g-photo-stream";
+      $block->title = t("Photo stream");
+      $block->content = new View("admin_block_photo_stream.html");
+      $block->content->photos = ORM::factory("item")
+        ->where("type", "=", "photo")->order_by("created", "DESC")->find_all(10);
+      break;
+
+    case "log_entries":
+      $block->css_id = "g-log-entries";
+      $block->title = t("Log entries");
+      $block->content = new View("admin_block_log_entries.html");
+      $block->content->entries = ORM::factory("log")
+        ->order_by(array("timestamp" => "DESC", "id" => "DESC"))->find_all(5);
+      break;
+
+    case "stats":
+      $block->css_id = "g-stats";
+      $block->title = t("Gallery stats");
+      $block->content = new View("admin_block_stats.html");
+      $block->content->album_count =
+        ORM::factory("item")->where("type", "=", "album")->where("id", "<>", 1)->count_all();
+      $block->content->photo_count = ORM::factory("item")->where("type", "=", "photo")->count_all();
+      break;
+
+    case "platform_info":
+      $block->css_id = "g-platform";
+      $block->title = t("Platform information");
+      $block->content = new View("admin_block_platform.html");
+      break;
+
+    case "project_news":
+      $block->css_id = "g-project-news";
+      $block->title = t("Gallery project news");
+      $block->content = new View("admin_block_news.html");
+      $block->content->feed = feed::parse("http://galleryproject.org/node/feed", 3);
+      break;
+
+    case "block_adder":
+      if ($form = gallery_block::get_add_block_form()) {
+        $block->css_id = "g-block-adder";
+        $block->title = t("Dashboard content");
+        $block->content = $form;
+      } else {
+        $block = "";
+      }
+      break;
+
+    case "language":
+      $locales = locales::installed();
+      if (count($locales) > 1) {
+        foreach ($locales as $locale => $display_name) {
+          $locales[$locale] = SafeString::of_safe_html($display_name);
+        }
+        $block = new Block();
+        $block->css_id = "g-user-language-block";
+        $block->title = t("Language preference");
+        $block->content = new View("user_languages_block.html");
+        $block->content->installed_locales = array_merge(array("" => t("« none »")), $locales);
+        $block->content->selected = (string) locales::cookie_locale();
+      } else {
+        $block = "";
+      }
+      break;
+
+    case "upgrade_checker":
+      $block = new Block();
+      $block->css_id = "g-upgrade-available-block";
+      $block->title = t("Check for Gallery upgrades");
+      $block->content = new View("upgrade_checker_block.html");
+      $block->content->version_info = upgrade_checker::version_info();
+      $block->content->auto_check_enabled = upgrade_checker::auto_check_enabled();
+      $block->content->new_version = upgrade_checker::get_upgrade_message();
+      $block->content->build_number = gallery::build_number();
+    }
+    return $block;
+  }
+
+  static function get_add_block_form() {
+    $available_blocks = block_manager::get_available_admin_blocks();
+
+    $active = array();
+    foreach (array_merge(block_manager::get_active("dashboard_sidebar"),
+                         block_manager::get_active("dashboard_center")) as $b) {
+      unset($available_blocks[implode(":", $b)]);
+    }
+
+    if (!$available_blocks) {
+      return;
+    }
+
+    $form = new Forge("admin/dashboard/add_block", "", "post",
+                      array("id" => "g-add-dashboard-block-form"));
+    $group = $form->group("add_block")->label(t("Add Block"));
+    $group->dropdown("id")->label(t("Available blocks"))->options($available_blocks);
+    $group->submit("center")->value(t("Add to center"));
+    $group->submit("sidebar")->value(t("Add to sidebar"));
+    return $form;
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/gallery_error.php b/modules/gallery/helpers/gallery_error.php
new file mode 100644
index 0000000..76c8ca9
--- /dev/null
+++ b/modules/gallery/helpers/gallery_error.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class gallery_error_Core {
+  static function error_handler($severity, $message, $filename, $lineno) {
+    if (error_reporting() == 0) {
+      return;
+    }
+
+    if (error_reporting() & $severity) {
+      throw new ErrorException($message, 0, $severity, $filename, $lineno);
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php
new file mode 100644
index 0000000..a319b9c
--- /dev/null
+++ b/modules/gallery/helpers/gallery_event.php
@@ -0,0 +1,621 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class gallery_event_Core {
+  /**
+   * Initialization.
+   */
+  static function gallery_ready() {
+    if (!get_cfg_var("date.timezone")) {
+      if (!(rand() % 4)) {
+        Kohana_Log::add("error", "date.timezone setting not detected in " .
+                        get_cfg_var("cfg_file_path") . " falling back to UTC.  " .
+                        "Consult http://php.net/manual/function.get-cfg-var.php for help.");
+      }
+    }
+
+    identity::load_user();
+    theme::load_themes();
+    locales::set_request_locale();
+  }
+
+  static function gallery_shutdown() {
+    // Every 500th request, do a pass over var/logs and var/tmp and delete old files.
+    // Limit ourselves to deleting a single file so that we don't spend too much CPU
+    // time on it.  As long as servers call this at least twice a day they'll eventually
+    // wind up with a clean var/logs directory because we only create 1 file a day there.
+    // var/tmp might be stickier because theoretically we could wind up spamming that
+    // dir with a lot of files.  But let's start with this and refine as we go.
+    if (!(rand() % 500)) {
+      // Note that this code is roughly duplicated in gallery_task::file_cleanup
+      $threshold = time() - 1209600; // older than 2 weeks
+      foreach(array("logs", "tmp") as $dir) {
+        $dir = VARPATH . $dir;
+        if ($dh = opendir($dir)) {
+          while (($file = readdir($dh)) !== false) {
+            if ($file[0] == ".") {
+              continue;
+            }
+
+            // Ignore directories for now, but we should really address them in the long term.
+            if (is_dir("$dir/$file")) {
+              continue;
+            }
+
+            if (filemtime("$dir/$file") <= $threshold) {
+              unlink("$dir/$file");
+              break;
+            }
+          }
+        }
+      }
+    }
+    // Delete all files marked using system::delete_later.
+    system::delete_marked_files();
+  }
+
+  static function user_deleted($user) {
+    $admin = identity::admin_user();
+    if (!empty($admin)) {          // could be empty if there is not identity provider
+      db::build()
+        ->update("tasks")
+        ->set("owner_id", $admin->id)
+        ->where("owner_id", "=", $user->id)
+        ->execute();
+      db::build()
+        ->update("items")
+        ->set("owner_id", $admin->id)
+        ->where("owner_id", "=", $user->id)
+        ->execute();
+      db::build()
+        ->update("logs")
+        ->set("user_id", $admin->id)
+        ->where("user_id", "=", $user->id)
+        ->execute();
+    }
+  }
+
+  static function identity_provider_changed($old_provider, $new_provider) {
+    $admin = identity::admin_user();
+    db::build()
+      ->update("tasks")
+      ->set("owner_id", $admin->id)
+      ->execute();
+    db::build()
+      ->update("items")
+      ->set("owner_id", $admin->id)
+      ->execute();
+    db::build()
+      ->update("logs")
+      ->set("user_id", $admin->id)
+      ->execute();
+    module::set_var("gallery", "email_from", $admin->email);
+    module::set_var("gallery", "email_reply_to", $admin->email);
+  }
+
+  static function group_created($group) {
+    access::add_group($group);
+  }
+
+  static function group_deleted($group) {
+    access::delete_group($group);
+  }
+
+  static function item_created($item) {
+    access::add_item($item);
+
+    // Build our thumbnail/resizes.
+    try {
+      graphics::generate($item);
+    } catch (Exception $e) {
+      log::error("graphics", t("Couldn't create a thumbnail or resize for %item_title",
+                               array("item_title" => $item->title)),
+                 html::anchor($item->abs_url(), t("details")));
+      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+    }
+
+    if ($item->is_photo() || $item->is_movie()) {
+      // If the parent has no cover item, make this it.
+      $parent = $item->parent();
+      if (access::can("edit", $parent) && $parent->album_cover_item_id == null)  {
+        item::make_album_cover($item);
+      }
+    }
+  }
+
+  static function item_deleted($item) {
+    access::delete_item($item);
+
+    // Find any other albums that had the deleted item as the album cover and null it out.
+    // In some cases this may leave us with a missing album cover up in this item's parent
+    // hierarchy, but in most cases it'll work out fine.
+    foreach (ORM::factory("item")
+             ->where("album_cover_item_id", "=", $item->id)
+             ->find_all() as $parent) {
+      item::remove_album_cover($parent);
+    }
+
+    $parent = $item->parent();
+    if (!$parent->album_cover_item_id) {
+      // Assume that we deleted the album cover
+      if (batch::in_progress()) {
+        // Remember that this parent is missing an album cover, for later.
+        $batch_missing_album_cover = Session::instance()->get("batch_missing_album_cover", array());
+        $batch_missing_album_cover[$parent->id] = 1;
+        Session::instance()->set("batch_missing_album_cover", $batch_missing_album_cover);
+      } else {
+        // Choose the first viewable child as the new cover.
+        if ($child = $parent->viewable()->children(1)->current()) {
+          item::make_album_cover($child);
+        }
+      }
+    }
+  }
+
+  static function item_updated_data_file($item) {
+    graphics::generate($item);
+
+    // Update any places where this is the album cover
+    foreach (ORM::factory("item")
+             ->where("album_cover_item_id", "=", $item->id)
+             ->find_all() as $target) {
+      $target->thumb_dirty = 1;
+      $target->save();
+      graphics::generate($target);
+    }
+  }
+
+  static function batch_complete() {
+    // Set the album covers for any items that where we probably deleted the album cover during
+    // this batch.  The item may have been deleted, so don't count on it being around.  Choose the
+    // first child as the new album cover.
+    // NOTE: if the first child doesn't have an album cover, then this won't work.
+    foreach (array_keys(Session::instance()->get("batch_missing_album_cover", array())) as $id) {
+      $item = ORM::factory("item", $id);
+      if ($item->loaded() && !$item->album_cover_item_id) {
+        if ($child = $item->children(1)->current()) {
+          item::make_album_cover($child);
+        }
+      }
+    }
+    Session::instance()->delete("batch_missing_album_cover");
+  }
+
+  static function item_moved($item, $old_parent) {
+    if ($item->is_album()) {
+      access::recalculate_album_permissions($item->parent());
+    } else {
+      access::recalculate_photo_permissions($item);
+    }
+
+    // If the new parent doesn't have an album cover, make this it.
+    if (!$item->parent()->album_cover_item_id) {
+      item::make_album_cover($item);
+    }
+  }
+
+  static function user_login($user) {
+    // If this user is an admin, check to see if there are any post-install tasks that we need
+    // to run and take care of those now.
+    if ($user->admin && module::get_var("gallery", "choose_default_tookit", null)) {
+      graphics::choose_default_toolkit();
+      module::clear_var("gallery", "choose_default_tookit");
+    }
+    Session::instance()->set("active_auth_timestamp", time());
+    auth::clear_failed_attempts($user);
+  }
+
+  static function user_auth_failed($name) {
+    auth::record_failed_attempt($name);
+  }
+
+  static function user_auth($user) {
+    auth::clear_failed_attempts($user);
+    Session::instance()->set("active_auth_timestamp", time());
+  }
+
+  static function item_index_data($item, $data) {
+    $data[] = $item->description;
+    $data[] = $item->name;
+    $data[] = $item->title;
+  }
+
+  static function user_menu($menu, $theme) {
+    if ($theme->page_subtype != "login") {
+      $user = identity::active_user();
+      if ($user->guest) {
+        $menu->append(Menu::factory("dialog")
+                      ->id("user_menu_login")
+                      ->css_id("g-login-link")
+                      ->url(url::site("login/ajax"))
+                      ->label(t("Login")));
+      } else {
+        $csrf = access::csrf_token();
+        $menu->append(Menu::factory("link")
+                      ->id("user_menu_edit_profile")
+                      ->css_id("g-user-profile-link")
+                      ->view("login_current_user.html")
+                      ->url(user_profile::url($user->id))
+                      ->label($user->display_name()));
+
+        if (Router::$controller == "admin") {
+          $continue_url = url::abs_site("");
+        } else if ($item = $theme->item()) {
+          if (access::user_can(identity::guest(), "view", $theme->item)) {
+            $continue_url = $item->abs_url();
+          } else {
+            $continue_url = item::root()->abs_url();
+          }
+        } else {
+          $continue_url = url::abs_current();
+        }
+
+        $menu->append(Menu::factory("link")
+                      ->id("user_menu_logout")
+                      ->css_id("g-logout-link")
+                      ->url(url::site("logout?csrf=$csrf&amp;continue_url=" . urlencode($continue_url)))
+                      ->label(t("Logout")));
+      }
+    }
+  }
+
+  static function site_menu($menu, $theme, $item_css_selector) {
+    if ($theme->page_subtype != "login") {
+      $menu->append(Menu::factory("link")
+                    ->id("home")
+                    ->label(t("Home"))
+                    ->url(item::root()->url()));
+
+
+      $item = $theme->item();
+
+      if (!empty($item)) {
+        $can_edit = $item && access::can("edit", $item);
+        $can_add = $item && access::can("add", $item);
+
+        if ($can_add) {
+          $menu->append($add_menu = Menu::factory("submenu")
+                        ->id("add_menu")
+                        ->label(t("Add")));
+          $is_album_writable =
+            is_writable($item->is_album() ? $item->file_path() : $item->parent()->file_path());
+          if ($is_album_writable) {
+            $add_menu->append(Menu::factory("dialog")
+                              ->id("add_photos_item")
+                              ->label(t("Add photos"))
+                              ->url(url::site("uploader/index/$item->id")));
+            if ($item->is_album()) {
+              $add_menu->append(Menu::factory("dialog")
+                                ->id("add_album_item")
+                                ->label(t("Add an album"))
+                                ->url(url::site("form/add/albums/$item->id?type=album")));
+            }
+          } else {
+            message::warning(t("The album '%album_name' is not writable.",
+                               array("album_name" => $item->title)));
+          }
+        }
+
+        switch ($item->type) {
+        case "album":
+          $option_text = t("Album options");
+          $edit_text = t("Edit album");
+          $delete_text = t("Delete album");
+          break;
+        case "movie":
+          $option_text = t("Movie options");
+          $edit_text = t("Edit movie");
+          $delete_text = t("Delete movie");
+          break;
+        default:
+          $option_text = t("Photo options");
+          $edit_text = t("Edit photo");
+          $delete_text = t("Delete photo");
+        }
+
+        $menu->append($options_menu = Menu::factory("submenu")
+                      ->id("options_menu")
+                      ->label($option_text));
+        if ($item && ($can_edit || $can_add)) {
+          if ($can_edit) {
+            $options_menu->append(Menu::factory("dialog")
+                                  ->id("edit_item")
+                                  ->label($edit_text)
+                                  ->url(url::site("form/edit/{$item->type}s/$item->id?from_id={$item->id}")));
+          }
+
+          if ($item->is_album()) {
+            if ($can_edit) {
+              $options_menu->append(Menu::factory("dialog")
+                                    ->id("edit_permissions")
+                                    ->label(t("Edit permissions"))
+                                    ->url(url::site("permissions/browse/$item->id")));
+            }
+          }
+        }
+
+        $csrf = access::csrf_token();
+        $page_type = $theme->page_type();
+        if ($can_edit && $item->is_photo() && graphics::can("rotate")) {
+          $options_menu
+            ->append(
+              Menu::factory("ajax_link")
+              ->id("rotate_ccw")
+              ->label(t("Rotate 90° counter clockwise"))
+              ->css_class("ui-icon-rotate-ccw")
+              ->ajax_handler("function(data) { " .
+                             "\$.gallery_replace_image(data, \$('$item_css_selector')) }")
+              ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&amp;from_id={$item->id}&amp;page_type=$page_type")))
+            ->append(
+              Menu::factory("ajax_link")
+              ->id("rotate_cw")
+              ->label(t("Rotate 90° clockwise"))
+              ->css_class("ui-icon-rotate-cw")
+              ->ajax_handler("function(data) { " .
+                             "\$.gallery_replace_image(data, \$('$item_css_selector')) }")
+              ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&amp;from_id={$item->id}&amp;page_type=$page_type")));
+        }
+
+        if ($item->id != item::root()->id) {
+          $parent = $item->parent();
+          if (access::can("edit", $parent)) {
+            // We can't make this item the highlight if it's an album with no album cover, or if it's
+            // already the album cover.
+            if (($item->type == "album" && empty($item->album_cover_item_id)) ||
+                ($item->type == "album" && $parent->album_cover_item_id == $item->album_cover_item_id) ||
+                $parent->album_cover_item_id == $item->id) {
+              $disabledState = "ui-state-disabled";
+            } else {
+              $disabledState = "";
+            }
+
+            if ($item->parent()->id != 1) {
+              $options_menu
+                ->append(
+                  Menu::factory("ajax_link")
+                  ->id("make_album_cover")
+                  ->label(t("Choose as the album cover"))
+                  ->css_class("ui-icon-star $disabledState")
+                  ->ajax_handler("function(data) { window.location.reload() }")
+                  ->url(url::site("quick/make_album_cover/$item->id?csrf=$csrf")));
+            }
+            $options_menu
+              ->append(
+                Menu::factory("dialog")
+                ->id("delete")
+                ->label($delete_text)
+                ->css_class("ui-icon-trash")
+                ->css_class("g-quick-delete")
+                ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&amp;from_id={$item->id}&amp;page_type=$page_type")));
+          }
+        }
+      }
+
+      if (identity::active_user()->admin) {
+        $menu->append($admin_menu = Menu::factory("submenu")
+                ->id("admin_menu")
+                ->label(t("Admin")));
+        module::event("admin_menu", $admin_menu, $theme);
+
+        $settings_menu = $admin_menu->get("settings_menu");
+        uasort($settings_menu->elements, array("Menu", "title_comparator"));
+      }
+    }
+  }
+
+  static function admin_menu($menu, $theme) {
+    $menu
+      ->append(Menu::factory("link")
+               ->id("dashboard")
+               ->label(t("Dashboard"))
+               ->url(url::site("admin")))
+      ->append(Menu::factory("submenu")
+               ->id("settings_menu")
+               ->label(t("Settings"))
+               ->append(Menu::factory("link")
+                        ->id("graphics_toolkits")
+                        ->label(t("Graphics"))
+                        ->url(url::site("admin/graphics")))
+               ->append(Menu::factory("link")
+                        ->id("movies_settings")
+                        ->label(t("Movies"))
+                        ->url(url::site("admin/movies")))
+               ->append(Menu::factory("link")
+                        ->id("languages")
+                        ->label(t("Languages"))
+                        ->url(url::site("admin/languages")))
+               ->append(Menu::factory("link")
+                        ->id("advanced")
+                        ->label(t("Advanced"))
+                        ->url(url::site("admin/advanced_settings"))))
+      ->append(Menu::factory("link")
+               ->id("modules")
+               ->label(t("Modules"))
+               ->url(url::site("admin/modules")))
+      ->append(Menu::factory("submenu")
+               ->id("content_menu")
+               ->label(t("Content")))
+      ->append(Menu::factory("submenu")
+               ->id("appearance_menu")
+               ->label(t("Appearance"))
+               ->append(Menu::factory("link")
+                        ->id("themes")
+                        ->label(t("Theme choice"))
+                        ->url(url::site("admin/themes")))
+               ->append(Menu::factory("link")
+                        ->id("theme_options")
+                        ->label(t("Theme options"))
+                        ->url(url::site("admin/theme_options")))
+               ->append(Menu::factory("link")
+                        ->id("sidebar")
+                        ->label(t("Manage sidebar"))
+                        ->url(url::site("admin/sidebar"))))
+      ->append(Menu::factory("submenu")
+               ->id("statistics_menu")
+               ->label(t("Statistics")))
+      ->append(Menu::factory("link")
+               ->id("maintenance")
+               ->label(t("Maintenance"))
+               ->url(url::site("admin/maintenance")));
+    return $menu;
+  }
+
+  static function context_menu($menu, $theme, $item, $thumb_css_selector) {
+    $menu->append($options_menu = Menu::factory("submenu")
+                  ->id("options_menu")
+                  ->label(t("Options"))
+                  ->css_class("ui-icon-carat-1-n"));
+
+    $page_type = $theme->page_type();
+    if (access::can("edit", $item)) {
+      switch ($item->type) {
+      case "movie":
+        $edit_title = t("Edit this movie");
+        $delete_title = t("Delete this movie");
+        break;
+
+      case "album":
+        $edit_title = t("Edit this album");
+        $delete_title = t("Delete this album");
+        break;
+
+      default:
+        $edit_title = t("Edit this photo");
+        $delete_title = t("Delete this photo");
+        break;
+      }
+      $cover_title = t("Choose as the album cover");
+
+      $csrf = access::csrf_token();
+
+      $theme_item = $theme->item();
+      $options_menu->append(Menu::factory("dialog")
+                            ->id("edit")
+                            ->label($edit_title)
+                            ->css_class("ui-icon-pencil")
+                            ->url(url::site("quick/form_edit/$item->id?from_id={$theme_item->id}")));
+
+      if ($item->is_photo() && graphics::can("rotate")) {
+        $options_menu
+          ->append(
+            Menu::factory("ajax_link")
+            ->id("rotate_ccw")
+            ->label(t("Rotate 90° counter clockwise"))
+            ->css_class("ui-icon-rotate-ccw")
+            ->ajax_handler("function(data) { " .
+                           "\$.gallery_replace_image(data, \$('$thumb_css_selector')) }")
+            ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&amp;from_id={$theme_item->id}&amp;page_type=$page_type")))
+          ->append(
+            Menu::factory("ajax_link")
+            ->id("rotate_cw")
+            ->label(t("Rotate 90° clockwise"))
+            ->css_class("ui-icon-rotate-cw")
+            ->ajax_handler("function(data) { " .
+                           "\$.gallery_replace_image(data, \$('$thumb_css_selector')) }")
+            ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&amp;from_id={$theme_item->id}&amp;page_type=$page_type")));
+      }
+
+      $parent = $item->parent();
+      if (access::can("edit", $parent)) {
+        // We can't make this item the highlight if it's an album with no album cover, or if it's
+        // already the album cover.
+        if (($item->type == "album" && empty($item->album_cover_item_id)) ||
+            ($item->type == "album" && $parent->album_cover_item_id == $item->album_cover_item_id) ||
+            $parent->album_cover_item_id == $item->id) {
+          $disabledState = "ui-state-disabled";
+        } else {
+          $disabledState = "";
+        }
+        if ($item->parent()->id != 1) {
+          $options_menu
+            ->append(Menu::factory("ajax_link")
+                     ->id("make_album_cover")
+                     ->label($cover_title)
+                     ->css_class("ui-icon-star $disabledState")
+                     ->ajax_handler("function(data) { window.location.reload() }")
+                     ->url(url::site("quick/make_album_cover/$item->id?csrf=$csrf")));
+        }
+        $options_menu
+          ->append(Menu::factory("dialog")
+                   ->id("delete")
+                   ->label($delete_title)
+                   ->css_class("ui-icon-trash")
+                   ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&amp;" .
+                                   "from_id={$theme_item->id}&amp;page_type=$page_type")));
+      }
+
+      if ($item->is_album()) {
+        $options_menu
+          ->append(Menu::factory("dialog")
+                   ->id("add_item")
+                   ->label(t("Add a photo"))
+                   ->css_class("ui-icon-plus")
+                   ->url(url::site("uploader/index/$item->id")))
+          ->append(Menu::factory("dialog")
+                   ->id("add_album")
+                   ->label(t("Add an album"))
+                   ->css_class("ui-icon-note")
+                   ->url(url::site("form/add/albums/$item->id?type=album")))
+          ->append(Menu::factory("dialog")
+                   ->id("edit_permissions")
+                   ->label(t("Edit permissions"))
+                   ->css_class("ui-icon-key")
+                   ->url(url::site("permissions/browse/$item->id")));
+      }
+    }
+  }
+
+  static function show_user_profile($data) {
+    $v = new View("user_profile_info.html");
+
+    $fields = array("name" => t("Name"), "locale" => t("Language Preference"),
+                    "email" => t("Email"), "full_name" => t("Full name"), "url" => t("Web site"));
+    if (!$data->user->guest) {
+      $fields = array("name" => t("Name"), "full_name" => t("Full name"), "url" => t("Web site"));
+    }
+    $v->user_profile_data = array();
+    foreach ($fields as $field => $label) {
+      if (!empty($data->user->$field)) {
+        $value = $data->user->$field;
+        if ($field == "locale") {
+          $value = locales::display_name($value);
+        } else if ($field == "url") {
+          $value = html::mark_clean(html::anchor(html::clean($data->user->$field)));
+        }
+        $v->user_profile_data[(string) $label] = $value;
+      }
+    }
+    $data->content[] = (object) array("title" => t("User information"), "view" => $v);
+
+  }
+
+  static function user_updated($original_user, $updated_user) {
+    // If the default from/reply-to email address is set to the install time placeholder value
+    // of unknown@unknown.com then adopt the value from the first admin to set their own email
+    // address so that we at least have a valid address for the Gallery.
+    if ($updated_user->admin) {
+      $email = module::get_var("gallery", "email_from", "");
+      if ($email == "unknown@unknown.com") {
+        module::set_var("gallery", "email_from", $updated_user->email);
+        module::set_var("gallery", "email_reply_to", $updated_user->email);
+      }
+    }
+  }
+}
diff --git a/modules/gallery/helpers/gallery_graphics.php b/modules/gallery/helpers/gallery_graphics.php
new file mode 100644
index 0000000..eb76353
--- /dev/null
+++ b/modules/gallery/helpers/gallery_graphics.php
@@ -0,0 +1,183 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class gallery_graphics_Core {
+  /**
+   * Rotate an image.  Valid options are degrees
+   *
+   * @param string     $input_file
+   * @param string     $output_file
+   * @param array      $options
+   * @param Item_Model $item (optional)
+   */
+  static function rotate($input_file, $output_file, $options, $item=null) {
+    graphics::init_toolkit();
+
+    $temp_file = system::temp_filename("rotate_", pathinfo($output_file, PATHINFO_EXTENSION));
+    module::event("graphics_rotate", $input_file, $temp_file, $options, $item);
+
+    if (@filesize($temp_file) > 0) {
+      // A graphics_rotate event made an image - move it to output_file and use it.
+      @rename($temp_file, $output_file);
+    } else {
+      // No events made an image - proceed with standard process.
+      if (@filesize($input_file) == 0) {
+        throw new Exception("@todo EMPTY_INPUT_FILE");
+      }
+
+      if (!isset($options["degrees"])) {
+        $options["degrees"] = 0;
+      }
+
+      // Rotate the image.  This also implicitly converts its format if needed.
+      Image::factory($input_file)
+        ->quality(module::get_var("gallery", "image_quality"))
+        ->rotate($options["degrees"])
+        ->save($output_file);
+    }
+
+    module::event("graphics_rotate_completed", $input_file, $output_file, $options, $item);
+  }
+
+  /**
+   * Resize an image.  Valid options are width, height and master.  Master is one of the Image
+   * master dimension constants.
+   *
+   * @param string     $input_file
+   * @param string     $output_file
+   * @param array      $options
+   * @param Item_Model $item (optional)
+   */
+  static function resize($input_file, $output_file, $options, $item=null) {
+    graphics::init_toolkit();
+
+    $temp_file = system::temp_filename("resize_", pathinfo($output_file, PATHINFO_EXTENSION));
+    module::event("graphics_resize", $input_file, $temp_file, $options, $item);
+
+    if (@filesize($temp_file) > 0) {
+      // A graphics_resize event made an image - move it to output_file and use it.
+      @rename($temp_file, $output_file);
+    } else {
+      // No events made an image - proceed with standard process.
+      if (@filesize($input_file) == 0) {
+        throw new Exception("@todo EMPTY_INPUT_FILE");
+      }
+
+      list ($input_width, $input_height, $input_mime, $input_extension) =
+        photo::get_file_metadata($input_file);
+      if ($input_width && $input_height &&
+          (empty($options["width"]) || empty($options["height"]) || empty($options["master"]) ||
+          (max($input_width, $input_height) <= min($options["width"], $options["height"])))) {
+        // Photo dimensions well-defined, but options not well-defined or would upscale the image.
+        // Do not resize.  Check mimes to see if we can copy the file or if we need to convert it.
+        // (checking mimes avoids needlessly converting jpg to jpeg, etc.)
+        $output_mime = legal_file::get_photo_types_by_extension(pathinfo($output_file, PATHINFO_EXTENSION));
+        if ($input_mime && $output_mime && ($input_mime == $output_mime)) {
+          // Mimes well-defined and identical - copy input to output
+          copy($input_file, $output_file);
+        } else {
+          // Mimes not well-defined or not the same - convert input to output
+          $image = Image::factory($input_file)
+            ->quality(module::get_var("gallery", "image_quality"))
+            ->save($output_file);
+        }
+      } else {
+        // Resize the image.  This also implicitly converts its format if needed.
+        $image = Image::factory($input_file)
+          ->resize($options["width"], $options["height"], $options["master"])
+          ->quality(module::get_var("gallery", "image_quality"));
+        if (graphics::can("sharpen")) {
+          $image->sharpen(module::get_var("gallery", "image_sharpen"));
+        }
+        $image->save($output_file);
+      }
+    }
+
+    module::event("graphics_resize_completed", $input_file, $output_file, $options, $item);
+  }
+
+  /**
+   * Overlay an image on top of the input file.
+   *
+   * Valid options are: file, position, transparency, padding
+   *
+   * Valid positions: northwest, north, northeast,
+   *                  west, center, east,
+   *                  southwest, south, southeast
+   *
+   * padding is in pixels
+   *
+   * @param string     $input_file
+   * @param string     $output_file
+   * @param array      $options
+   * @param Item_Model $item (optional)
+   */
+  static function composite($input_file, $output_file, $options, $item=null) {
+    try {
+      graphics::init_toolkit();
+
+      $temp_file = system::temp_filename("composite_", pathinfo($output_file, PATHINFO_EXTENSION));
+      module::event("graphics_composite", $input_file, $temp_file, $options, $item);
+
+      if (@filesize($temp_file) > 0) {
+        // A graphics_composite event made an image - move it to output_file and use it.
+        @rename($temp_file, $output_file);
+      } else {
+        // No events made an image - proceed with standard process.
+
+        list ($width, $height) = photo::get_file_metadata($input_file);
+        list ($w_width, $w_height) = photo::get_file_metadata($options["file"]);
+
+        $pad = isset($options["padding"]) ? $options["padding"] : 10;
+        $top = $pad;
+        $left = $pad;
+        $y_center = max($height / 2 - $w_height / 2, $pad);
+        $x_center = max($width / 2 - $w_width / 2, $pad);
+        $bottom = max($height - $w_height - $pad, $pad);
+        $right = max($width - $w_width - $pad, $pad);
+
+        switch ($options["position"]) {
+        case "northwest": $x = $left;     $y = $top;       break;
+        case "north":     $x = $x_center; $y = $top;       break;
+        case "northeast": $x = $right;    $y = $top;       break;
+        case "west":      $x = $left;     $y = $y_center;  break;
+        case "center":    $x = $x_center; $y = $y_center;  break;
+        case "east":      $x = $right;    $y = $y_center;  break;
+        case "southwest": $x = $left;     $y = $bottom;    break;
+        case "south":     $x = $x_center; $y = $bottom;    break;
+        case "southeast": $x = $right;    $y = $bottom;    break;
+        }
+
+        Image::factory($input_file)
+          ->composite($options["file"], $x, $y, $options["transparency"])
+          ->quality(module::get_var("gallery", "image_quality"))
+          ->save($output_file);
+      }
+
+      module::event("graphics_composite_completed", $input_file, $output_file, $options, $item);
+    } catch (ErrorException $e) {
+      // Unlike rotate and resize, composite catches its exceptions here.  This is because
+      // composite is typically called for watermarks.  If during thumb/resize generation
+      // the watermark fails, we'd still like the image resized, just without its watermark.
+      // If the exception isn't caught here, graphics::generate will replace it with a
+      // placeholder.
+      Kohana_Log::add("error", $e->getMessage());
+    }
+  }
+}
diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php
new file mode 100644
index 0000000..d49be83
--- /dev/null
+++ b/modules/gallery/helpers/gallery_installer.php
@@ -0,0 +1,844 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class gallery_installer {
+  static function install() {
+    $db = Database::instance();
+    $db->query("CREATE TABLE {access_caches} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `item_id` int(9),
+                 PRIMARY KEY (`id`),
+                 KEY (`item_id`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {access_intents} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `item_id` int(9),
+                 PRIMARY KEY (`id`))
+               DEFAULT CHARSET=utf8;");
+
+    // Using a simple index instead of a unique key for the
+    // key column to avoid handling of concurrency issues
+    // on insert. Thus allowing concurrent inserts on the
+    // same cache key, as does Memcache / xcache.
+    $db->query("CREATE TABLE {caches} (
+                `id` int(9) NOT NULL auto_increment,
+                `key` varchar(255) NOT NULL,
+                `tags` varchar(255),
+                `expiration` int(9) NOT NULL,
+                `cache` longblob,
+                PRIMARY KEY (`id`),
+                UNIQUE KEY (`key`),
+                KEY (`tags`))
+                DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {failed_auths} (
+                `id` int(9) NOT NULL auto_increment,
+                `count` int(9) NOT NULL,
+                `name` varchar(255) NOT NULL,
+                `time` int(9) NOT NULL,
+                PRIMARY KEY (`id`))
+                DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {graphics_rules} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `active` BOOLEAN default 0,
+                 `args` varchar(255) default NULL,
+                 `module_name` varchar(64) NOT NULL,
+                 `operation` varchar(64) NOT NULL,
+                 `priority` int(9) NOT NULL,
+                 `target`  varchar(32) NOT NULL,
+                 PRIMARY KEY (`id`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {incoming_translations} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `key` char(32) NOT NULL,
+                 `locale` char(10) NOT NULL,
+                 `message` text NOT NULL,
+                 `revision` int(9) DEFAULT NULL,
+                 `translation` text,
+                 PRIMARY KEY (`id`),
+                 UNIQUE KEY(`key`, `locale`),
+                 KEY `locale_key` (`locale`, `key`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {items} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `album_cover_item_id` int(9) default NULL,
+                 `captured` int(9) default NULL,
+                 `created` int(9) default NULL,
+                 `description` text default NULL,
+                 `height` int(9) default NULL,
+                 `left_ptr` int(9) NOT NULL,
+                 `level` int(9) NOT NULL,
+                 `mime_type` varchar(64) default NULL,
+                 `name` varchar(255) default NULL,
+                 `owner_id` int(9) default NULL,
+                 `parent_id` int(9) NOT NULL,
+                 `rand_key` decimal(11,10) default NULL,
+                 `relative_path_cache` varchar(255) default NULL,
+                 `relative_url_cache` varchar(255) default NULL,
+                 `resize_dirty` boolean default 1,
+                 `resize_height` int(9) default NULL,
+                 `resize_width` int(9) default NULL,
+                 `right_ptr` int(9) NOT NULL,
+                 `slug` varchar(255) default NULL,
+                 `sort_column` varchar(64) default NULL,
+                 `sort_order` char(4) default 'ASC',
+                 `thumb_dirty` boolean default 1,
+                 `thumb_height` int(9) default NULL,
+                 `thumb_width` int(9) default NULL,
+                 `title` varchar(255) default NULL,
+                 `type` varchar(32) NOT NULL,
+                 `updated` int(9) default NULL,
+                 `view_count` int(9) default 0,
+                 `weight` int(9) NOT NULL default 0,
+                 `width` int(9) default NULL,
+                 PRIMARY KEY (`id`),
+                 KEY `parent_id` (`parent_id`),
+                 KEY `type` (`type`),
+                 KEY `random` (`rand_key`),
+                 KEY `weight` (`weight` DESC),
+                 KEY `left_ptr` (`left_ptr`),
+                 KEY `relative_path_cache` (`relative_path_cache`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {logs} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `category` varchar(64) default NULL,
+                 `html` varchar(255) default NULL,
+                 `message` text default NULL,
+                 `referer` varchar(255) default NULL,
+                 `severity` int(9) default 0,
+                 `timestamp` int(9) default 0,
+                 `url` varchar(255) default NULL,
+                 `user_id` int(9) default 0,
+                 PRIMARY KEY (`id`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {messages} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `key` varchar(255) default NULL,
+                 `severity` varchar(32) default NULL,
+                 `value` text default NULL,
+                 PRIMARY KEY (`id`),
+                 UNIQUE KEY(`key`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {modules} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `active` BOOLEAN default 0,
+                 `name` varchar(64) default NULL,
+                 `version` int(9) default NULL,
+                 `weight` int(9) default NULL,
+                 PRIMARY KEY (`id`),
+                 UNIQUE KEY(`name`),
+                 KEY (`weight`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {outgoing_translations} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `base_revision` int(9) DEFAULT NULL,
+                 `key` char(32) NOT NULL,
+                 `locale` char(10) NOT NULL,
+                 `message` text NOT NULL,
+                 `translation` text,
+                 PRIMARY KEY (`id`),
+                 UNIQUE KEY(`key`, `locale`),
+                 KEY `locale_key` (`locale`, `key`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {permissions} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `display_name` varchar(64) default NULL,
+                 `name` varchar(64) default NULL,
+                 PRIMARY KEY (`id`),
+                 UNIQUE KEY(`name`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {sessions} (
+                `session_id` varchar(127) NOT NULL,
+                `data` text NOT NULL,
+                `last_activity` int(10) UNSIGNED NOT NULL,
+                PRIMARY KEY (`session_id`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {tasks} (
+                `id` int(9) NOT NULL auto_increment,
+                `callback` varchar(128) default NULL,
+                `context` text NOT NULL,
+                `done` boolean default 0,
+                `name` varchar(128) default NULL,
+                `owner_id` int(9) default NULL,
+                `percent_complete` int(9) default 0,
+                `state` varchar(32) default NULL,
+                `status` varchar(255) default NULL,
+                `updated` int(9) default NULL,
+                PRIMARY KEY (`id`),
+                KEY (`owner_id`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {themes} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `name` varchar(64) default NULL,
+                 `version` int(9) default NULL,
+                 PRIMARY KEY (`id`),
+                 UNIQUE KEY(`name`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE {vars} (
+                `id` int(9) NOT NULL auto_increment,
+                `module_name` varchar(64) NOT NULL,
+                `name` varchar(64) NOT NULL,
+                `value` text,
+                PRIMARY KEY (`id`),
+                UNIQUE KEY(`module_name`, `name`))
+               DEFAULT CHARSET=utf8;");
+
+    foreach (array("albums", "logs", "modules", "resizes", "thumbs", "tmp", "uploads") as $dir) {
+      @mkdir(VARPATH . $dir);
+      if (in_array($dir, array("logs", "tmp", "uploads"))) {
+        self::_protect_directory(VARPATH . $dir);
+      }
+    }
+
+    access::register_permission("view", "View");
+    access::register_permission("view_full", "View full size");
+    access::register_permission("edit", "Edit");
+    access::register_permission("add", "Add");
+
+    // Mark for translation (must be the same strings as used above)
+    t("View full size");
+    t("View");
+    t("Edit");
+    t("Add");
+
+    // Hardcode the first item to sidestep ORM validation rules
+    $now = time();
+    db::build()->insert(
+      "items",
+      array("created" => $now,
+            "description" => "",
+            "left_ptr" => 1,
+            "level" => 1,
+            "parent_id" => 0,
+            "resize_dirty" => 1,
+            "right_ptr" => 2,
+            "sort_column" => "weight",
+            "sort_order" => "ASC",
+            "thumb_dirty" => 1,
+            "title" => "Gallery",
+            "type" => "album",
+            "updated" => $now,
+            "weight" => 1))
+      ->execute();
+    $root = ORM::factory("item", 1);
+    access::add_item($root);
+
+    module::set_var("gallery", "active_site_theme", "wind");
+    module::set_var("gallery", "active_admin_theme", "admin_wind");
+    module::set_var("gallery", "page_size", 9);
+    module::set_var("gallery", "thumb_size", 200);
+    module::set_var("gallery", "resize_size", 640);
+    module::set_var("gallery", "default_locale", "en_US");
+    module::set_var("gallery", "image_quality", 75);
+    module::set_var("gallery", "image_sharpen", 15);
+    module::set_var("gallery", "upgrade_checker_auto_enabled", true);
+
+    // Add rules for generating our thumbnails and resizes
+    graphics::add_rule(
+      "gallery", "thumb", "gallery_graphics::resize",
+      array("width" => 200, "height" => 200, "master" => Image::AUTO),
+      100);
+    graphics::add_rule(
+      "gallery", "resize", "gallery_graphics::resize",
+      array("width" => 640, "height" => 640, "master" => Image::AUTO),
+      100);
+
+    // Instantiate default themes (site and admin)
+    foreach (array("wind", "admin_wind") as $theme_name) {
+      $theme_info = new ArrayObject(parse_ini_file(THEMEPATH . $theme_name . "/theme.info"),
+                                    ArrayObject::ARRAY_AS_PROPS);
+      $theme = ORM::factory("theme");
+      $theme->name = $theme_name;
+      $theme->version = $theme_info->version;
+      $theme->save();
+    }
+
+    block_manager::add("dashboard_sidebar", "gallery", "block_adder");
+    block_manager::add("dashboard_sidebar", "gallery", "stats");
+    block_manager::add("dashboard_sidebar", "gallery", "platform_info");
+    block_manager::add("dashboard_sidebar", "gallery", "project_news");
+    block_manager::add("dashboard_center", "gallery", "welcome");
+    block_manager::add("dashboard_center", "gallery", "upgrade_checker");
+    block_manager::add("dashboard_center", "gallery", "photo_stream");
+    block_manager::add("dashboard_center", "gallery", "log_entries");
+
+    module::set_var("gallery", "choose_default_tookit", 1);
+    module::set_var("gallery", "date_format", "Y-M-d");
+    module::set_var("gallery", "date_time_format", "Y-M-d H:i:s");
+    module::set_var("gallery", "time_format", "H:i:s");
+    module::set_var("gallery", "show_credits", 1);
+    // Mark string for translation
+    $powered_by_string = t("Powered by <a href=\"%url\">%gallery_version</a>",
+                           array("locale" => "root"));
+    module::set_var("gallery", "credits", (string) $powered_by_string);
+    module::set_var("gallery", "simultaneous_upload_limit", 5);
+    module::set_var("gallery", "admin_area_timeout", 90 * 60);
+    module::set_var("gallery", "maintenance_mode", 0);
+    module::set_var("gallery", "visible_title_length", 15);
+    module::set_var("gallery", "favicon_url", "lib/images/favicon.ico");
+    module::set_var("gallery", "apple_touch_icon_url", "lib/images/apple-touch-icon.png");
+    module::set_var("gallery", "email_from", "");
+    module::set_var("gallery", "email_reply_to", "");
+    module::set_var("gallery", "email_line_length", 70);
+    module::set_var("gallery", "email_header_separator", serialize("\n"));
+    module::set_var("gallery", "show_user_profiles_to", "registered_users");
+    module::set_var("gallery", "extra_binary_paths", "/usr/local/bin:/opt/local/bin:/opt/bin");
+    module::set_var("gallery", "timezone", null);
+    module::set_var("gallery", "lock_timeout", 1);
+    module::set_var("gallery", "movie_extract_frame_time", 3);
+    module::set_var("gallery", "movie_allow_uploads", "autodetect");
+  }
+
+  static function upgrade($version) {
+    $db = Database::instance();
+    if ($version == 1) {
+      module::set_var("gallery", "date_format", "Y-M-d");
+      module::set_var("gallery", "date_time_format", "Y-M-d H:i:s");
+      module::set_var("gallery", "time_format", "H:i:s");
+      module::set_version("gallery", $version = 2);
+    }
+
+    if ($version == 2) {
+      module::set_var("gallery", "show_credits", 1);
+      module::set_version("gallery", $version = 3);
+    }
+
+    if ($version == 3) {
+      $db->query("CREATE TABLE {caches} (
+                 `id` varchar(255) NOT NULL,
+                 `tags` varchar(255),
+                 `expiration` int(9) NOT NULL,
+                 `cache` text,
+                 PRIMARY KEY (`id`),
+                 KEY (`tags`))
+                 DEFAULT CHARSET=utf8;");
+      module::set_version("gallery", $version = 4);
+    }
+
+    if ($version == 4) {
+      Cache::instance()->delete_all();
+      $db->query("ALTER TABLE {caches} MODIFY COLUMN `cache` LONGBLOB");
+      module::set_version("gallery", $version = 5);
+    }
+
+    if ($version == 5) {
+      Cache::instance()->delete_all();
+      $db->query("ALTER TABLE {caches} DROP COLUMN `id`");
+      $db->query("ALTER TABLE {caches} ADD COLUMN `key` varchar(255) NOT NULL");
+      $db->query("ALTER TABLE {caches} ADD COLUMN `id` int(9) NOT NULL auto_increment PRIMARY KEY");
+      module::set_version("gallery", $version = 6);
+    }
+
+    if ($version == 6) {
+      module::clear_var("gallery", "version");
+      module::set_version("gallery", $version = 7);
+    }
+
+    if ($version == 7) {
+      $groups = identity::groups();
+      $permissions = ORM::factory("permission")->find_all();
+      foreach($groups as $group) {
+        foreach($permissions as $permission) {
+          // Update access intents
+          $db->query("ALTER TABLE {access_intents} MODIFY COLUMN {$permission->name}_{$group->id} BINARY(1) DEFAULT NULL");
+          // Update access cache
+          if ($permission->name === "view") {
+            $db->query("ALTER TABLE {items} MODIFY COLUMN {$permission->name}_{$group->id} BINARY(1) DEFAULT FALSE");
+          } else {
+            $db->query("ALTER TABLE {access_caches} MODIFY COLUMN {$permission->name}_{$group->id} BINARY(1) NOT NULL DEFAULT FALSE");
+          }
+        }
+      }
+      module::set_version("gallery", $version = 8);
+    }
+
+    if ($version == 8) {
+      $db->query("ALTER TABLE {items} CHANGE COLUMN `left`  `left_ptr`  INT(9) NOT NULL;");
+      $db->query("ALTER TABLE {items} CHANGE COLUMN `right` `right_ptr` INT(9) NOT NULL;");
+      module::set_version("gallery", $version = 9);
+    }
+
+    if ($version == 9) {
+      $db->query("ALTER TABLE {items} ADD KEY `weight` (`weight` DESC);");
+
+      module::set_version("gallery", $version = 10);
+    }
+
+    if ($version == 10) {
+      module::set_var("gallery", "image_sharpen", 15);
+
+      module::set_version("gallery", $version = 11);
+    }
+
+    if ($version == 11) {
+      $db->query("ALTER TABLE {items} ADD COLUMN `relative_url_cache` varchar(255) DEFAULT NULL");
+      $db->query("ALTER TABLE {items} ADD COLUMN `slug` varchar(255) DEFAULT NULL");
+
+      // This is imperfect since some of the slugs may contain invalid characters, but it'll do
+      // for now because we don't want a lengthy operation here.
+      $db->query("UPDATE {items} SET `slug` = `name`");
+
+      // Flush all path caches because we're going to start urlencoding them.
+      $db->query("UPDATE {items} SET `relative_url_cache` = NULL, `relative_path_cache` = NULL");
+      module::set_version("gallery", $version = 12);
+    }
+
+    if ($version == 12) {
+      if (module::get_var("gallery", "active_site_theme") == "default") {
+        module::set_var("gallery", "active_site_theme", "wind");
+      }
+      if (module::get_var("gallery", "active_admin_theme") == "admin_default") {
+        module::set_var("gallery", "active_admin_theme", "admin_wind");
+      }
+      module::set_version("gallery", $version = 13);
+    }
+
+    if ($version == 13) {
+      // Add rules for generating our thumbnails and resizes
+      Database::instance()->query(
+        "UPDATE {graphics_rules} SET `operation` = CONCAT('gallery_graphics::', `operation`);");
+      module::set_version("gallery", $version = 14);
+    }
+
+    if ($version == 14) {
+      $sidebar_blocks = block_manager::get_active("site_sidebar");
+      if (empty($sidebar_blocks)) {
+        $available_blocks = block_manager::get_available_site_blocks();
+        foreach  (array_keys(block_manager::get_available_site_blocks()) as $id) {
+          $sidebar_blocks[] = explode(":", $id);
+        }
+        block_manager::set_active("site_sidebar", $sidebar_blocks);
+      }
+      module::set_version("gallery", $version = 15);
+    }
+
+    if ($version == 15) {
+      module::set_var("gallery", "identity_provider", "user");
+      module::set_version("gallery", $version = 16);
+    }
+
+    // Convert block keys to an md5 hash of the module and block name
+    if ($version == 16) {
+      foreach (array("dashboard_sidebar", "dashboard_center", "site_sidebar") as $location) {
+        $blocks = block_manager::get_active($location);
+        $new_blocks = array();
+        foreach ($blocks as $block) {
+          $new_blocks[md5("{$block[0]}:{$block[1]}")] = $block;
+        }
+        block_manager::set_active($location, $new_blocks);
+      }
+      module::set_version("gallery", $version = 17);
+    }
+
+    // We didn't like md5 hashes so convert block keys back to random keys to allow duplicates.
+    if ($version == 17) {
+      foreach (array("dashboard_sidebar", "dashboard_center", "site_sidebar") as $location) {
+        $blocks = block_manager::get_active($location);
+        $new_blocks = array();
+        foreach ($blocks as $block) {
+          $new_blocks[random::int()] = $block;
+        }
+        block_manager::set_active($location, $new_blocks);
+      }
+      module::set_version("gallery", $version = 18);
+    }
+
+    // Rename blocks_site.sidebar to blocks_site_sidebar
+    if ($version == 18) {
+      $blocks = block_manager::get_active("site.sidebar");
+      block_manager::set_active("site_sidebar", $blocks);
+      module::clear_var("gallery", "blocks_site.sidebar");
+      module::set_version("gallery", $version = 19);
+    }
+
+    // Set a default for the number of simultaneous uploads
+    // Version 20 was reverted in 57adefc5baa7a2b0dfcd3e736e80c2fa86d3bfa2, so skip it.
+    if ($version == 19 || $version == 20) {
+      module::set_var("gallery", "simultaneous_upload_limit", 5);
+      module::set_version("gallery", $version = 21);
+    }
+
+    // Update the graphics rules table so that the maximum height for resizes is 640 not 480.
+    // Fixes ticket #671
+    if ($version == 21) {
+      $resize_rule = ORM::factory("graphics_rule")
+        ->where("id", "=", "2")
+        ->find();
+      // make sure it hasn't been changed already
+      $args = unserialize($resize_rule->args);
+      if ($args["height"] == 480 && $args["width"] == 640) {
+        $args["height"] = 640;
+        $resize_rule->args = serialize($args);
+        $resize_rule->save();
+      }
+      module::set_version("gallery", $version = 22);
+    }
+
+    // Update slug values to be legal.  We should have done this in the 11->12 upgrader, but I was
+    // lazy.  Mea culpa!
+    if ($version == 22) {
+      foreach (db::build()
+               ->from("items")
+               ->select("id", "slug")
+               ->where(db::expr("`slug` REGEXP '[^_A-Za-z0-9-]'"), "=", 1)
+               ->execute() as $row) {
+        $new_slug = item::convert_filename_to_slug($row->slug);
+        if (empty($new_slug)) {
+          $new_slug = random::int();
+        }
+        db::build()
+          ->update("items")
+          ->set("slug", $new_slug)
+          ->set("relative_url_cache", null)
+          ->where("id", "=", $row->id)
+          ->execute();
+      }
+      module::set_version("gallery", $version = 23);
+    }
+
+    if ($version == 23) {
+      $db->query("CREATE TABLE {failed_logins} (
+                  `id` int(9) NOT NULL auto_increment,
+                  `count` int(9) NOT NULL,
+                  `name` varchar(255) NOT NULL,
+                  `time` int(9) NOT NULL,
+                  PRIMARY KEY (`id`))
+                  DEFAULT CHARSET=utf8;");
+      module::set_version("gallery", $version = 24);
+    }
+
+    if ($version == 24) {
+      foreach (array("logs", "tmp", "uploads") as $dir) {
+        self::_protect_directory(VARPATH . $dir);
+      }
+      module::set_version("gallery", $version = 25);
+    }
+
+    if ($version == 25) {
+      db::build()
+        ->update("items")
+        ->set("title", db::expr("`name`"))
+        ->and_open()
+        ->where("title", "IS", null)
+        ->or_where("title", "=", "")
+        ->close()
+        ->execute();
+      module::set_version("gallery", $version = 26);
+    }
+
+    if ($version == 26) {
+      if (in_array("failed_logins", Database::instance()->list_tables())) {
+        $db->query("RENAME TABLE {failed_logins} TO {failed_auths}");
+      }
+      module::set_version("gallery", $version = 27);
+    }
+
+    if ($version == 27) {
+      // Set the admin area timeout to 90 minutes
+      module::set_var("gallery", "admin_area_timeout", 90 * 60);
+      module::set_version("gallery", $version = 28);
+    }
+
+    if ($version == 28) {
+      module::set_var("gallery", "credits", "Powered by <a href=\"%url\">%gallery_version</a>");
+      module::set_version("gallery", $version = 29);
+    }
+
+    if ($version == 29) {
+      $db->query("ALTER TABLE {caches} ADD KEY (`key`);");
+      module::set_version("gallery", $version = 30);
+    }
+
+    if ($version == 30) {
+      module::set_var("gallery", "maintenance_mode", 0);
+      module::set_version("gallery", $version = 31);
+    }
+
+    if ($version == 31) {
+      $db->query("ALTER TABLE {modules} ADD COLUMN `weight` int(9) DEFAULT NULL");
+      $db->query("ALTER TABLE {modules} ADD KEY (`weight`)");
+      db::update("modules")
+        ->set("weight", db::expr("`id`"))
+        ->execute();
+      module::set_version("gallery", $version = 32);
+    }
+
+    if ($version == 32) {
+      $db->query("ALTER TABLE {items} ADD KEY (`left_ptr`)");
+      module::set_version("gallery", $version = 33);
+    }
+
+    if ($version == 33) {
+      $db->query("ALTER TABLE {access_caches} ADD KEY (`item_id`)");
+      module::set_version("gallery", $version = 34);
+    }
+
+    if ($version == 34) {
+      module::set_var("gallery", "visible_title_length", 15);
+      module::set_version("gallery", $version = 35);
+    }
+
+    if ($version == 35) {
+      module::set_var("gallery", "favicon_url", "lib/images/favicon.ico");
+      module::set_version("gallery", $version = 36);
+    }
+
+    if ($version == 36) {
+      module::set_var("gallery", "email_from", "admin@example.com");
+      module::set_var("gallery", "email_reply_to", "public@example.com");
+      module::set_var("gallery", "email_line_length", 70);
+      module::set_var("gallery", "email_header_separator", serialize("\n"));
+      module::set_version("gallery", $version = 37);
+    }
+
+    // Changed our minds and decided that the initial value should be empty
+    // But don't just reset it blindly, only do it if the value is version 37 default
+    if ($version == 37) {
+      $email = module::get_var("gallery", "email_from", "");
+      if ($email == "admin@example.com") {
+        module::set_var("gallery", "email_from", "");
+      }
+      $email = module::get_var("gallery", "email_reply_to", "");
+      if ($email == "admin@example.com") {
+        module::set_var("gallery", "email_reply_to", "");
+      }
+      module::set_version("gallery", $version = 38);
+    }
+
+    if ($version == 38) {
+      module::set_var("gallery", "show_user_profiles_to", "registered_users");
+      module::set_version("gallery", $version = 39);
+    }
+
+    if ($version == 39) {
+      module::set_var("gallery", "extra_binary_paths", "/usr/local/bin:/opt/local/bin:/opt/bin");
+      module::set_version("gallery", $version = 40);
+    }
+
+    if ($version == 40) {
+      module::clear_var("gallery", "_cache");
+      module::set_version("gallery", $version = 41);
+    }
+
+    if ($version == 41) {
+      $db->query("TRUNCATE TABLE {caches}");
+      $db->query("ALTER TABLE {caches} DROP INDEX `key`, ADD UNIQUE `key` (`key`)");
+      module::set_version("gallery", $version = 42);
+    }
+
+    if ($version == 42) {
+      $db->query("ALTER TABLE {items} CHANGE `description` `description` text DEFAULT NULL");
+      module::set_version("gallery", $version = 43);
+    }
+
+    if ($version == 43) {
+      $db->query("ALTER TABLE {items} CHANGE `rand_key` `rand_key` DECIMAL(11, 10)");
+      module::set_version("gallery", $version = 44);
+    }
+
+    if ($version == 44) {
+      $db->query("ALTER TABLE {messages} CHANGE `value` `value` text default NULL");
+      module::set_version("gallery", $version = 45);
+    }
+
+    if ($version == 45) {
+      // Splice the upgrade_checker block into the admin dashboard at the top
+      // of the page, but under the welcome block if it's in the first position.
+      $blocks = block_manager::get_active("dashboard_center");
+      $index = count($blocks) && current($blocks) == array("gallery", "welcome") ? 1 : 0;
+      array_splice($blocks, $index, 0, array(random::int() => array("gallery", "upgrade_checker")));
+      block_manager::set_active("dashboard_center", $blocks);
+
+      module::set_var("gallery", "upgrade_checker_auto_enabled", true);
+      module::set_version("gallery", $version = 46);
+    }
+
+    if ($version == 46) {
+      module::set_var("gallery", "apple_touch_icon_url", "lib/images/apple-touch-icon.png");
+      module::set_version("gallery", $version = 47);
+    }
+
+    if ($version == 47 || $version == 48) {
+      // Add configuration variable to set timezone.  Defaults to the currently
+      // used timezone (from PHP configuration).  Note that in v48 we were
+      // setting this value incorrectly, so we're going to stomp this value for v49.
+      module::set_var("gallery", "timezone", null);
+      module::set_version("gallery", $version = 49);
+    }
+
+    if ($version == 49) {
+      // In v49 we changed the Item_Model validation code to disallow files with two dots in them,
+      // but we didn't rename any files which fail to validate, so as soon as you do anything to
+      // change those files (eg. as a side effect of getting the url or file path) it fails to
+      // validate.  Fix those here.  This might be slow, but if it times out it can just pick up
+      // where it left off.
+      foreach (db::build()
+               ->from("items")
+               ->select("id")
+               ->where("type", "<>", "album")
+               ->where(db::expr("`name` REGEXP '\\\\..*\\\\.'"), "=", 1)
+               ->order_by("id", "asc")
+               ->execute() as $row) {
+        set_time_limit(30);
+        $item = ORM::factory("item", $row->id);
+        $item->name = legal_file::smash_extensions($item->name);
+        $item->save();
+      }
+      module::set_version("gallery", $version = 50);
+    }
+
+    if ($version == 50) {
+      // In v51, we added a lock_timeout variable so that administrators could edit the time out
+      // from 1 second to a higher variable if their system runs concurrent parallel uploads for
+      // instance.
+      module::set_var("gallery", "lock_timeout", 1);
+      module::set_version("gallery", $version = 51);
+    }
+
+    if ($version == 51) {
+      // In v52, we added functions to the legal_file helper that map photo and movie file
+      // extensions to their mime types (and allow extension of the list by other modules).  During
+      // this process, we correctly mapped m4v files to video/x-m4v, correcting a previous error
+      // where they were mapped to video/mp4.  This corrects the existing items.
+      db::build()
+        ->update("items")
+        ->set("mime_type", "video/x-m4v")
+        ->where("name", "REGEXP", "\.m4v$") // case insensitive since name column is utf8_general_ci
+        ->execute();
+      module::set_version("gallery", $version = 52);
+    }
+
+    if ($version == 52) {
+      // In v53, we added the ability to change the default time used when extracting frames from
+      // movies.  Previously we hard-coded this at 3 seconds, so we use that as the default.
+      module::set_var("gallery", "movie_extract_frame_time", 3);
+      module::set_version("gallery", $version = 53);
+    }
+
+    if ($version == 53) {
+      // In v54, we changed how we check for name and slug conflicts in Item_Model.  Previously,
+      // we checked the whole filename.  As a result, "foo.jpg" and "foo.png" were not considered
+      // conflicting if their slugs were different (a rare case in practice since server_add and
+      // uploader would give them both the same slug "foo").  Now, we check the filename without its
+      // extension.  This upgrade stanza fixes any conflicts where they were previously allowed.
+
+      // This might be slow, but if it times out it can just pick up where it left off.
+
+      // Find and loop through each conflict (e.g. "foo.jpg", "foo.png", and "foo.flv" are one
+      // conflict; "bar.jpg", "bar.png", and "bar.flv" are another)
+      foreach (db::build()
+               ->select_distinct(array("parent_base_name" =>
+                 db::expr("CONCAT(`parent_id`, ':', LOWER(SUBSTR(`name`, 1, LOCATE('.', `name`) - 1)))")))
+               ->select(array("C" => "COUNT(\"*\")"))
+               ->from("items")
+               ->where("type", "<>", "album")
+               ->having("C", ">", 1)
+               ->group_by("parent_base_name")
+               ->execute() as $conflict) {
+        list ($parent_id, $base_name) = explode(":", $conflict->parent_base_name, 2);
+        $base_name_escaped = Database::escape_for_like($base_name);
+        // Loop through the items for each conflict
+        foreach (db::build()
+                 ->from("items")
+                 ->select("id")
+                 ->where("type", "<>", "album")
+                 ->where("parent_id", "=", $parent_id)
+                 ->where("name", "LIKE", "{$base_name_escaped}.%")
+                 ->limit(1000000)  // required to satisfy SQL syntax (no offset without limit)
+                 ->offset(1)       // skips the 0th item
+                 ->execute() as $row) {
+          set_time_limit(30);
+          $item = ORM::factory("item", $row->id);
+          $item->name = $item->name;  // this will force Item_Model to check for conflicts on save
+          $item->save();
+        }
+      }
+      module::set_version("gallery", $version = 54);
+    }
+
+    if ($version == 54) {
+      $db->query("ALTER TABLE {items} ADD KEY `relative_path_cache` (`relative_path_cache`)");
+      module::set_version("gallery", $version = 55);
+    }
+
+    if ($version == 55) {
+      // In v56, we added the ability to change the default behavior regarding movie uploads.  It
+      // can be set to "always", "never", or "autodetect" to match the previous behavior where they
+      // are allowed only if FFmpeg is found.
+      module::set_var("gallery", "movie_allow_uploads", "autodetect");
+      module::set_version("gallery", $version = 56);
+    }
+
+    if ($version == 56) {
+      // Cleanup possible instances where resize_dirty of albums or movies was set to 0.  This is
+      // unlikely to have occurred, and doesn't currently matter much since albums and movies don't
+      // have resize images anyway.  However, it may be useful to be consistent here going forward.
+      db::build()
+        ->update("items")
+        ->set("resize_dirty", 1)
+        ->where("type", "<>", "photo")
+        ->execute();
+      module::set_version("gallery", $version = 57);
+    }
+  }
+
+  static function uninstall() {
+    $db = Database::instance();
+    $db->query("DROP TABLE IF EXISTS {access_caches}");
+    $db->query("DROP TABLE IF EXISTS {access_intents}");
+    $db->query("DROP TABLE IF EXISTS {graphics_rules}");
+    $db->query("DROP TABLE IF EXISTS {incoming_translations}");
+    $db->query("DROP TABLE IF EXISTS {failed_auths}");
+    $db->query("DROP TABLE IF EXISTS {items}");
+    $db->query("DROP TABLE IF EXISTS {logs}");
+    $db->query("DROP TABLE IF EXISTS {modules}");
+    $db->query("DROP TABLE IF EXISTS {outgoing_translations}");
+    $db->query("DROP TABLE IF EXISTS {permissions}");
+    $db->query("DROP TABLE IF EXISTS {sessions}");
+    $db->query("DROP TABLE IF EXISTS {tasks}");
+    $db->query("DROP TABLE IF EXISTS {themes}");
+    $db->query("DROP TABLE IF EXISTS {vars}");
+    $db->query("DROP TABLE IF EXISTS {caches}");
+    foreach (array("albums", "resizes", "thumbs", "uploads",
+                   "modules", "logs", "database.php") as $entry) {
+      system("/bin/rm -rf " . VARPATH . $entry);
+    }
+  }
+
+  static function _protect_directory($dir) {
+    $fp = @fopen("$dir/.htaccess", "w+");
+    fwrite($fp, "DirectoryIndex .htaccess\nSetHandler Gallery_Security_Do_Not_Remove\n" .
+           "Options None\n<IfModule mod_rewrite.c>\nRewriteEngine off\n</IfModule>\n" .
+           "Order allow,deny\nDeny from all\n");
+    fclose($fp);
+  }
+}
diff --git a/modules/gallery/helpers/gallery_rss.php b/modules/gallery/helpers/gallery_rss.php
new file mode 100644
index 0000000..d6b3302
--- /dev/null
+++ b/modules/gallery/helpers/gallery_rss.php
@@ -0,0 +1,76 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class gallery_rss_Core {
+  static function available_feeds($item, $tag) {
+    $feeds["gallery/latest"] = t("Latest photos and movies");
+
+    if ($item) {
+      $feed_item = $item -> is_album() ? $item : $item->parent();
+
+      $feeds["gallery/album/{$feed_item->id}"] =
+          t("%title photos and movies", array("title" => $feed_item->title));
+    }
+
+    return $feeds;
+  }
+
+  static function feed($feed_id, $offset, $limit, $id) {
+    $feed = new stdClass();
+    switch ($feed_id) {
+    case "latest":
+      $feed->items = ORM::factory("item")
+        ->viewable()
+        ->where("type", "<>", "album")
+        ->order_by("created", "DESC")
+        ->find_all($limit, $offset);
+
+      $all_items = ORM::factory("item")
+        ->viewable()
+        ->where("type", "<>", "album")
+        ->order_by("created", "DESC");
+
+      $feed->max_pages = ceil($all_items->find_all()->count() / $limit);
+      $feed->title = t("%site_title - Recent updates", array("site_title" => item::root()->title));
+      $feed->description = t("Recent updates");
+      return $feed;
+
+    case "album":
+      $item = ORM::factory("item", $id);
+      access::required("view", $item);
+
+      $feed->items = $item
+        ->viewable()
+        ->descendants($limit, $offset, array(array("type", "=", "photo")));
+      $feed->max_pages = ceil(
+        $item->viewable()->descendants_count(array(array("type", "=", "photo"))) / $limit);
+      if ($item->id == item::root()->id) {
+        $feed->title = html::purify($item->title);
+      } else {
+        $feed->title = t("%site_title - %item_title",
+                         array("site_title" => item::root()->title,
+                               "item_title" => $item->title));
+      }
+      $feed->description = nl2br(html::purify($item->description));
+
+      return $feed;
+    }
+  }
+}
diff --git a/modules/gallery/helpers/gallery_task.php b/modules/gallery/helpers/gallery_task.php
new file mode 100644
index 0000000..618cf8f
--- /dev/null
+++ b/modules/gallery/helpers/gallery_task.php
@@ -0,0 +1,826 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class gallery_task_Core {
+  const FIX_STATE_START_MPTT = 0;
+  const FIX_STATE_RUN_MPTT = 1;
+  const FIX_STATE_START_ALBUMS = 2;
+  const FIX_STATE_RUN_ALBUMS = 3;
+  const FIX_STATE_START_DUPE_SLUGS = 4;
+  const FIX_STATE_RUN_DUPE_SLUGS = 5;
+  const FIX_STATE_START_DUPE_NAMES = 6;
+  const FIX_STATE_RUN_DUPE_NAMES = 7;
+  const FIX_STATE_START_DUPE_BASE_NAMES = 8;
+  const FIX_STATE_RUN_DUPE_BASE_NAMES = 9;
+  const FIX_STATE_START_REBUILD_ITEM_CACHES = 10;
+  const FIX_STATE_RUN_REBUILD_ITEM_CACHES = 11;
+  const FIX_STATE_START_MISSING_ACCESS_CACHES = 12;
+  const FIX_STATE_RUN_MISSING_ACCESS_CACHES = 13;
+  const FIX_STATE_DONE = 14;
+
+  static function available_tasks() {
+    $dirty_count = graphics::find_dirty_images_query()->count_records();
+    $tasks = array();
+    $tasks[] = Task_Definition::factory()
+                 ->callback("gallery_task::rebuild_dirty_images")
+                 ->name(t("Rebuild Images"))
+                 ->description($dirty_count ?
+                               t2("You have one out of date photo",
+                                  "You have %count out of date photos",
+                                  $dirty_count)
+                               : t("All your photos are up to date"))
+      ->severity($dirty_count ? log::WARNING : log::SUCCESS);
+
+    $tasks[] = Task_Definition::factory()
+                 ->callback("gallery_task::update_l10n")
+                 ->name(t("Update translations"))
+                 ->description(t("Download new and updated translated strings"))
+      ->severity(log::SUCCESS);
+
+    $tasks[] = Task_Definition::factory()
+                 ->callback("gallery_task::file_cleanup")
+                 ->name(t("Remove old files"))
+                 ->description(t("Remove expired files from the logs and tmp directory"))
+      ->severity(log::SUCCESS);
+
+    $tasks[] = Task_Definition::factory()
+      ->callback("gallery_task::fix")
+      ->name(t("Fix your Gallery"))
+      ->description(t("Fix a variety of problems that might cause your Gallery to act strangely.  Requires maintenance mode."))
+      ->severity(log::SUCCESS);
+
+    return $tasks;
+  }
+
+  /**
+   * Task that rebuilds all dirty images.
+   * @param Task_Model the task
+   */
+  static function rebuild_dirty_images($task) {
+    $errors = array();
+    try {
+      // Choose the dirty images in a random order so that if we run this task multiple times
+      // concurrently each task is rebuilding different images simultaneously.
+      $result = graphics::find_dirty_images_query()->select("id")
+        ->select(db::expr("RAND() as r"))
+        ->order_by("r", "ASC")
+        ->execute();
+      $total_count = $task->get("total_count", $result->count());
+      $mode = $task->get("mode", "init");
+      if ($mode == "init") {
+        $task->set("total_count", $total_count);
+        $task->set("mode", "process");
+        batch::start();
+      }
+
+      $completed = $task->get("completed", 0);
+      $ignored = $task->get("ignored", array());
+
+      $i = 0;
+
+      // If there's no work left to do, skip to the end.  This can happen if we resume a task long
+      // after the work got done in some other task.
+      if (!$result->count()) {
+        $completed = $total_count;
+      }
+
+      foreach ($result as $row) {
+        if (array_key_exists($row->id, $ignored)) {
+          continue;
+        }
+
+        $item = ORM::factory("item", $row->id);
+        if ($item->loaded()) {
+          try {
+            graphics::generate($item);
+            $completed++;
+
+            $errors[] = t("Successfully rebuilt images for '%title'",
+                          array("title" => html::purify($item->title)));
+          } catch (Exception $e) {
+            $errors[] = t("Unable to rebuild images for '%title'",
+                          array("title" => html::purify($item->title)));
+            $errors[] = (string)$e;
+            $ignored[$item->id] = 1;
+          }
+        }
+
+        if (++$i == 2) {
+          break;
+        }
+      }
+
+      $task->status = t2("Updated: 1 image. Total: %total_count.",
+                         "Updated: %count images. Total: %total_count.",
+                         $completed,
+                         array("total_count" => $total_count));
+
+      if ($completed < $total_count) {
+        $task->percent_complete = (int)(100 * ($completed + count($ignored)) / $total_count);
+      } else {
+        $task->percent_complete = 100;
+      }
+
+      $task->set("completed", $completed);
+      $task->set("ignored", $ignored);
+      if ($task->percent_complete == 100) {
+        $task->done = true;
+        $task->state = "success";
+        batch::stop();
+        site_status::clear("graphics_dirty");
+      }
+    } catch (Exception $e) {
+      Kohana_Log::add("error",(string)$e);
+      $task->done = true;
+      $task->state = "error";
+      $task->status = $e->getMessage();
+      $errors[] = (string)$e;
+    }
+    if ($errors) {
+      $task->log($errors);
+    }
+  }
+
+  static function update_l10n($task) {
+    $errors = array();
+    try {
+      $start = microtime(true);
+      $data = Cache::instance()->get("update_l10n_cache:{$task->id}");
+      if ($data) {
+        list($dirs, $files, $cache, $num_fetched) = unserialize($data);
+      }
+      $i = 0;
+
+      switch ($task->get("mode", "init")) {
+      case "init":  // 0%
+        $dirs = array("gallery", "modules", "themes", "installer");
+        $files = $cache = array();
+        $num_fetched = 0;
+        $task->set("mode", "find_files");
+        $task->status = t("Finding files");
+        break;
+
+      case "find_files":  // 0% - 10%
+        while (($dir = array_pop($dirs)) && microtime(true) - $start < 0.5) {
+          if (in_array(basename($dir), array("tests", "lib"))) {
+            continue;
+          }
+
+          foreach (glob(DOCROOT . "$dir/*") as $path) {
+            $relative_path = str_replace(DOCROOT, "", $path);
+            if (is_dir($path)) {
+              $dirs[] = $relative_path;
+            } else {
+              $files[] = $relative_path;
+            }
+          }
+        }
+
+        $task->status = t2("Finding files: found 1 file",
+                           "Finding files: found %count files", count($files));
+
+        if (!$dirs) {
+          $task->set("mode", "scan_files");
+          $task->set("total_files", count($files));
+          $task->status = t("Scanning files");
+          $task->percent_complete = 10;
+        }
+        break;
+
+      case "scan_files": // 10% - 70%
+        while (($file = array_pop($files)) && microtime(true) - $start < 0.5) {
+          $file = DOCROOT . $file;
+          switch (pathinfo($file, PATHINFO_EXTENSION)) {
+          case "php":
+            l10n_scanner::scan_php_file($file, $cache);
+            break;
+
+          case "info":
+            l10n_scanner::scan_info_file($file, $cache);
+            break;
+          }
+        }
+
+        $total_files = $task->get("total_files");
+        $task->status = t2("Scanning files: scanned 1 file",
+                           "Scanning files: scanned %count files", $total_files - count($files));
+
+        $task->percent_complete = 10 + 60 * ($total_files - count($files)) / $total_files;
+        if (empty($files)) {
+          $task->set("mode", "fetch_updates");
+          $task->status = t("Fetching updates");
+          $task->percent_complete = 70;
+        }
+        break;
+
+      case "fetch_updates":  // 70% - 100%
+        // Send fetch requests in batches until we're done
+        $num_remaining = l10n_client::fetch_updates($num_fetched);
+        if ($num_remaining) {
+          $total = $num_fetched + $num_remaining;
+          $task->percent_complete = 70 + 30 * ((float) $num_fetched / $total);
+        } else {
+          Gallery_I18n::clear_cache();
+
+          $task->done = true;
+          $task->state = "success";
+          $task->status = t("Translations installed/updated");
+          $task->percent_complete = 100;
+        }
+      }
+
+      if (!$task->done) {
+        Cache::instance()->set("update_l10n_cache:{$task->id}",
+                               serialize(array($dirs, $files, $cache, $num_fetched)),
+                               array("l10n"));
+      } else {
+        Cache::instance()->delete("update_l10n_cache:{$task->id}");
+      }
+    } catch (Exception $e) {
+      Kohana_Log::add("error",(string)$e);
+      $task->done = true;
+      $task->state = "error";
+      $task->status = $e->getMessage();
+      $errors[] = (string)$e;
+    }
+    if ($errors) {
+      $task->log($errors);
+    }
+  }
+
+  /**
+   * Task that removes old files from var/logs and var/tmp.
+   * @param Task_Model the task
+   */
+  static function file_cleanup($task) {
+    $errors = array();
+    try {
+      $start = microtime(true);
+      $data = Cache::instance()->get("file_cleanup_cache:{$task->id}");
+      $files = $data ? unserialize($data) : array();
+      $i = 0;
+      $current = 0;
+      $total = 0;
+
+      switch ($task->get("mode", "init")) {
+      case "init":
+        $threshold = time() - 1209600; // older than 2 weeks
+        // Note that this code is roughly duplicated in gallery_event::gallery_shutdown
+        foreach(array("logs", "tmp") as $dir) {
+          $dir = VARPATH . $dir;
+          if ($dh = opendir($dir)) {
+            while (($file = readdir($dh)) !== false) {
+              if ($file[0] == ".") {
+                continue;
+              }
+
+              // Ignore directories for now, but we should really address them in the long term.
+              if (is_dir("$dir/$file")) {
+                continue;
+              }
+
+              if (filemtime("$dir/$file") <= $threshold) {
+                $files[] = "$dir/$file";
+              }
+            }
+          }
+        }
+        $task->set("mode", "delete_files");
+        $task->set("current", 0);
+        $task->set("total", count($files));
+        Cache::instance()->set("file_cleanup_cache:{$task->id}", serialize($files),
+                               array("file_cleanup"));
+        if (count($files) == 0) {
+          break;
+        }
+
+      case "delete_files":
+        $current = $task->get("current");
+        $total = $task->get("total");
+        while ($current < $total && microtime(true) - $start < 1) {
+          @unlink($files[$current]);
+          $task->log(t("%file removed", array("file" => $files[$current++])));
+        }
+        $task->percent_complete = $current / $total * 100;
+        $task->set("current", $current);
+      }
+
+      $task->status = t2("Removed: 1 file. Total: %total_count.",
+                         "Removed: %count files. Total: %total_count.",
+                         $current, array("total_count" => $total));
+
+      if ($total == $current) {
+        $task->done = true;
+        $task->state = "success";
+        $task->percent_complete = 100;
+      }
+    } catch (Exception $e) {
+      Kohana_Log::add("error",(string)$e);
+      $task->done = true;
+      $task->state = "error";
+      $task->status = $e->getMessage();
+      $errors[] = (string)$e;
+    }
+    if ($errors) {
+      $task->log($errors);
+    }
+  }
+
+  static function fix($task) {
+    $start = microtime(true);
+
+    $total = $task->get("total");
+    if (empty($total)) {
+      $item_count = db::build()->count_records("items");
+      $total = 0;
+
+      // mptt: 2 operations for every item
+      $total += 2 * $item_count;
+
+      // album audit (permissions and bogus album covers): 1 operation for every album
+      $total += db::build()->where("type", "=", "album")->count_records("items");
+
+      // one operation for each dupe slug, dupe name, dupe base name, and missing access cache
+      foreach (array("find_dupe_slugs", "find_dupe_names", "find_dupe_base_names",
+                     "find_missing_access_caches") as $func) {
+        foreach (self::$func() as $row) {
+          $total++;
+        }
+      }
+
+      // one operation to rebuild path and url caches;
+      $total += 1 * $item_count;
+
+      $task->set("total", $total);
+      $task->set("state", $state = self::FIX_STATE_START_MPTT);
+      $task->set("ptr", 1);
+      $task->set("completed", 0);
+    }
+
+    $completed = $task->get("completed");
+    $state = $task->get("state");
+
+    if (!module::get_var("gallery", "maintenance_mode")) {
+      module::set_var("gallery", "maintenance_mode", 1);
+    }
+
+    // This is a state machine that checks each item in the database.  It verifies the following
+    // attributes for an item.
+    // 1. Left and right MPTT pointers are correct
+    // 2. The .htaccess permission files for restricted items exist and are well formed.
+    // 3. The relative_path_cache and relative_url_cache values are set to null.
+    // 4. there are no album_cover_item_ids pointing to missing items
+    //
+    // We'll do a depth-first tree walk over our hierarchy using only the adjacency data because
+    // we don't trust MPTT here (that might be what we're here to fix!).  Avoid avoid using ORM
+    // calls as much as possible since they're expensive.
+    //
+    // NOTE: the MPTT check will only traverse items that have valid parents.  It's possible that
+    // we have some tree corruption where there are items with parent ids to non-existent items.
+    // We should probably do something about that.
+    while ($state != self::FIX_STATE_DONE && microtime(true) - $start < 1.5) {
+      switch ($state) {
+      case self::FIX_STATE_START_MPTT:
+        $task->set("ptr", $ptr = 1);
+        $task->set("stack", item::root()->id . "L1");
+        $state = self::FIX_STATE_RUN_MPTT;
+        break;
+
+      case self::FIX_STATE_RUN_MPTT:
+        $ptr = $task->get("ptr");
+        $stack = explode(" ", $task->get("stack"));
+        preg_match("/([0-9]+)([A-Z])([0-9]+)/", array_pop($stack), $matches);  // e.g. "12345L10"
+        list ( , $id, $ptr_mode, $level) = $matches;  // Skip the 0th entry of matches.
+        switch ($ptr_mode) {
+        case "L":
+          // Albums could be parent nodes.
+          $stack[] = "{$id}R{$level}";
+          db::build()
+            ->update("items")
+            ->set("left_ptr", $ptr++)
+            ->where("id", "=", $id)
+            ->execute();
+
+          $level++;
+          foreach (db::build()
+                   ->select(array("id", "type"))
+                   ->from("items")
+                   ->where("parent_id", "=", $id)
+                   ->order_by("left_ptr", "DESC") // DESC since array_pop effectively reverses them
+                   ->execute() as $child) {
+            $stack[] = ($child->type == "album") ? "{$child->id}L{$level}" : "{$child->id}B{$level}";
+          }
+          $completed++;
+          break;
+        case "B":
+          // Non-albums must be leaf nodes.
+          db::build()
+            ->update("items")
+            ->set("left_ptr", $ptr++)
+            ->set("right_ptr", $ptr++)
+            ->set("level", $level)
+            ->set("relative_path_cache", null)
+            ->set("relative_url_cache", null)
+            ->where("id", "=", $id)
+            ->execute();
+          $completed += 2;  // we updated two pointers
+          break;
+        case "R":
+          db::build()
+            ->update("items")
+            ->set("right_ptr", $ptr++)
+            ->set("level", $level)
+            ->set("relative_path_cache", null)
+            ->set("relative_url_cache", null)
+            ->where("id", "=", $id)
+            ->execute();
+          $completed++;
+        }
+        $task->set("ptr", $ptr);
+        $task->set("stack", implode(" ", $stack));
+
+        if (empty($stack)) {
+          $state = self::FIX_STATE_START_DUPE_SLUGS;
+        }
+        break;
+
+
+      case self::FIX_STATE_START_DUPE_SLUGS:
+        $stack = array();
+        foreach (self::find_dupe_slugs() as $row) {
+          list ($parent_id, $slug) = explode(":", $row->parent_slug, 2);
+          $stack[] = join(":", array($parent_id, $slug));
+        }
+        if ($stack) {
+          $task->set("stack", implode(" ", $stack));
+          $state = self::FIX_STATE_RUN_DUPE_SLUGS;
+        } else {
+          $state = self::FIX_STATE_START_DUPE_NAMES;
+        }
+        break;
+
+      case self::FIX_STATE_RUN_DUPE_SLUGS:
+        $stack = explode(" ", $task->get("stack"));
+        list ($parent_id, $slug) = explode(":", array_pop($stack));
+
+        // We want to leave the first one alone and update all conflicts to be random values.
+        $fixed = 0;
+        $conflicts = ORM::factory("item")
+          ->where("parent_id", "=", $parent_id)
+          ->where("slug", "=", $slug)
+          ->find_all(1, 1);
+        if ($conflicts->count() && $conflict = $conflicts->current()) {
+          $task->log("Fixing conflicting slug for item id {$conflict->id}");
+          db::build()
+            ->update("items")
+            ->set("slug", $slug . "-" . (string)rand(1000, 9999))
+            ->where("id", "=", $conflict->id)
+            ->execute();
+
+          // We fixed one conflict, but there might be more so put this parent back on the stack
+          // and try again.  We won't consider it completed when we don't fix a conflict.  This
+          // guarantees that we won't spend too long fixing one set of conflicts, and that we
+          // won't stop before all are fixed.
+          $stack[] = "$parent_id:$slug";
+          break;
+        }
+        $task->set("stack", implode(" ", $stack));
+        $completed++;
+
+        if (empty($stack)) {
+          $state = self::FIX_STATE_START_DUPE_NAMES;
+        }
+        break;
+
+      case self::FIX_STATE_START_DUPE_NAMES:
+        $stack = array();
+        foreach (self::find_dupe_names() as $row) {
+          list ($parent_id, $name) = explode(":", $row->parent_name, 2);
+          $stack[] = join(":", array($parent_id, $name));
+        }
+        if ($stack) {
+          $task->set("stack", implode(" ", $stack));
+          $state = self::FIX_STATE_RUN_DUPE_NAMES;
+        } else {
+          $state = self::FIX_STATE_START_DUPE_BASE_NAMES;
+        }
+        break;
+
+      case self::FIX_STATE_RUN_DUPE_NAMES:
+        // NOTE: This does *not* attempt to fix the file system!
+        $stack = explode(" ", $task->get("stack"));
+        list ($parent_id, $name) = explode(":", array_pop($stack));
+
+        $fixed = 0;
+        // We want to leave the first one alone and update all conflicts to be random values.
+        $conflicts = ORM::factory("item")
+          ->where("parent_id", "=", $parent_id)
+          ->where("name", "=", $name)
+          ->find_all(1, 1);
+        if ($conflicts->count() && $conflict = $conflicts->current()) {
+          $task->log("Fixing conflicting name for item id {$conflict->id}");
+          if (!$conflict->is_album() && preg_match("/^(.*)(\.[^\.\/]*?)$/", $conflict->name, $matches)) {
+            $item_base_name = $matches[1];
+            $item_extension = $matches[2]; // includes a leading dot
+          } else {
+            $item_base_name = $conflict->name;
+            $item_extension = "";
+          }
+          db::build()
+            ->update("items")
+            ->set("name", $item_base_name . "-" . (string)rand(1000, 9999) . $item_extension)
+            ->where("id", "=", $conflict->id)
+            ->execute();
+
+          // We fixed one conflict, but there might be more so put this parent back on the stack
+          // and try again.  We won't consider it completed when we don't fix a conflict.  This
+          // guarantees that we won't spend too long fixing one set of conflicts, and that we
+          // won't stop before all are fixed.
+          $stack[] = "$parent_id:$name";
+          break;
+        }
+        $task->set("stack", implode(" ", $stack));
+        $completed++;
+
+        if (empty($stack)) {
+          $state = self::FIX_STATE_START_DUPE_BASE_NAMES;
+        }
+        break;
+
+      case self::FIX_STATE_START_DUPE_BASE_NAMES:
+        $stack = array();
+        foreach (self::find_dupe_base_names() as $row) {
+          list ($parent_id, $base_name) = explode(":", $row->parent_base_name, 2);
+          $stack[] = join(":", array($parent_id, $base_name));
+        }
+        if ($stack) {
+          $task->set("stack", implode(" ", $stack));
+          $state = self::FIX_STATE_RUN_DUPE_BASE_NAMES;
+        } else {
+          $state = self::FIX_STATE_START_ALBUMS;
+        }
+        break;
+
+      case self::FIX_STATE_RUN_DUPE_BASE_NAMES:
+        // NOTE: This *does* attempt to fix the file system!  So, it must go *after* run_dupe_names.
+        $stack = explode(" ", $task->get("stack"));
+        list ($parent_id, $base_name) = explode(":", array_pop($stack));
+        $base_name_escaped = Database::escape_for_like($base_name);
+
+        $fixed = 0;
+        // We want to leave the first one alone and update all conflicts to be random values.
+        $conflicts = ORM::factory("item")
+          ->where("parent_id", "=", $parent_id)
+          ->where("name", "LIKE", "{$base_name_escaped}.%")
+          ->where("type", "<>", "album")
+          ->find_all(1, 1);
+        if ($conflicts->count() && $conflict = $conflicts->current()) {
+          $task->log("Fixing conflicting name for item id {$conflict->id}");
+          if (preg_match("/^(.*)(\.[^\.\/]*?)$/", $conflict->name, $matches)) {
+            $item_base_name = $matches[1]; // unlike $base_name, this always maintains capitalization
+            $item_extension = $matches[2]; // includes a leading dot
+          } else {
+            $item_base_name = $conflict->name;
+            $item_extension = "";
+          }
+          // Unlike conflicts found in run_dupe_names, these items are likely to have an intact
+          // file system.  Let's use the item save logic to rebuild the paths and rename the files
+          // if possible.
+          try {
+            $conflict->name = $item_base_name . "-" . (string)rand(1000, 9999) . $item_extension;
+            $conflict->validate();
+            // If we get here, we're safe to proceed with save
+            $conflict->save();
+          } catch (Exception $e) {
+            // Didn't work.  Edit database directly without fixing file system.
+            db::build()
+              ->update("items")
+              ->set("name", $item_base_name . "-" . (string)rand(1000, 9999) . $item_extension)
+              ->where("id", "=", $conflict->id)
+              ->execute();
+          }
+
+          // We fixed one conflict, but there might be more so put this parent back on the stack
+          // and try again.  We won't consider it completed when we don't fix a conflict.  This
+          // guarantees that we won't spend too long fixing one set of conflicts, and that we
+          // won't stop before all are fixed.
+          $stack[] = "$parent_id:$base_name";
+          break;
+        }
+        $task->set("stack", implode(" ", $stack));
+        $completed++;
+
+        if (empty($stack)) {
+          $state = self::FIX_STATE_START_ALBUMS;
+        }
+        break;
+
+      case self::FIX_STATE_START_ALBUMS:
+        $stack = array();
+        foreach (db::build()
+                 ->select("id")
+                 ->from("items")
+                 ->where("type", "=", "album")
+                 ->execute() as $row) {
+          $stack[] = $row->id;
+        }
+        $task->set("stack", implode(" ", $stack));
+        $state = self::FIX_STATE_RUN_ALBUMS;
+        break;
+
+      case self::FIX_STATE_RUN_ALBUMS:
+        $stack = explode(" ", $task->get("stack"));
+        $id = array_pop($stack);
+
+        $item = ORM::factory("item", $id);
+        if ($item->album_cover_item_id) {
+          $album_cover_item = ORM::factory("item", $item->album_cover_item_id);
+          if (!$album_cover_item->loaded()) {
+            $item->album_cover_item_id = null;
+            $item->save();
+          }
+        }
+
+        $everybody = identity::everybody();
+        $view_col = "view_{$everybody->id}";
+        $view_full_col = "view_full_{$everybody->id}";
+        $intent = ORM::factory("access_intent")->where("item_id", "=", $id)->find();
+        if ($intent->$view_col === access::DENY) {
+          access::update_htaccess_files($item, $everybody, "view", access::DENY);
+        }
+        if ($intent->$view_full_col === access::DENY) {
+          access::update_htaccess_files($item, $everybody, "view_full", access::DENY);
+        }
+        $task->set("stack", implode(" ", $stack));
+        $completed++;
+
+        if (empty($stack)) {
+          $state = self::FIX_STATE_START_REBUILD_ITEM_CACHES;
+        }
+        break;
+
+      case self::FIX_STATE_START_REBUILD_ITEM_CACHES:
+        $stack = array();
+        foreach (self::find_empty_item_caches(500) as $row) {
+          $stack[] = $row->id;
+        }
+        $task->set("stack", implode(" ", $stack));
+        $state = self::FIX_STATE_RUN_REBUILD_ITEM_CACHES;
+        break;
+
+      case self::FIX_STATE_RUN_REBUILD_ITEM_CACHES:
+        $stack = explode(" ", $task->get("stack"));
+        if (!empty($stack)) {
+          $id = array_pop($stack);
+          $item = ORM::factory("item", $id);
+          $item->relative_path();  // this rebuilds the cache and saves the item as a side-effect
+          $task->set("stack", implode(" ", $stack));
+          $completed++;
+        }
+
+        if (empty($stack)) {
+          // Try refilling the stack
+          foreach (self::find_empty_item_caches(500) as $row) {
+            $stack[] = $row->id;
+          }
+          $task->set("stack", implode(" ", $stack));
+
+          if (empty($stack)) {
+            $state = self::FIX_STATE_START_MISSING_ACCESS_CACHES;
+          }
+        }
+        break;
+
+      case self::FIX_STATE_START_MISSING_ACCESS_CACHES:
+        $stack = array();
+        foreach (self::find_missing_access_caches_limited(500) as $row) {
+          $stack[] = $row->id;
+        }
+        $task->set("stack", implode(" ", $stack));
+        $state = self::FIX_STATE_RUN_MISSING_ACCESS_CACHES;
+        break;
+
+      case self::FIX_STATE_RUN_MISSING_ACCESS_CACHES:
+        $stack = array_filter(explode(" ", $task->get("stack"))); // filter removes empty/zero ids
+        if (!empty($stack)) {
+          $id = array_pop($stack);
+          $access_cache = ORM::factory("access_cache");
+          $access_cache->item_id = $id;
+          $access_cache->save();
+          $task->set("stack", implode(" ", $stack));
+          $completed++;
+        }
+
+        if (empty($stack)) {
+          // Try refilling the stack
+          foreach (self::find_missing_access_caches_limited(500) as $row) {
+            $stack[] = $row->id;
+          }
+          $task->set("stack", implode(" ", $stack));
+
+          if (empty($stack)) {
+            // The new cache rows are there, but they're incorrectly populated so we have to fix
+            // them.  If this turns out to be too slow, we'll have to refactor
+            // access::recalculate_permissions to allow us to do it in slices.
+            access::recalculate_album_permissions(item::root());
+            $state = self::FIX_STATE_DONE;
+          }
+        }
+        break;
+      }
+    }
+
+    $task->set("state", $state);
+    $task->set("completed", $completed);
+
+    if ($state == self::FIX_STATE_DONE) {
+      $task->done = true;
+      $task->state = "success";
+      $task->percent_complete = 100;
+      module::set_var("gallery", "maintenance_mode", 0);
+    } else {
+      $task->percent_complete = round(100 * $completed / $total);
+    }
+    $task->status = t2("One operation complete", "%count / %total operations complete", $completed,
+                       array("total" => $total));
+  }
+
+  static function find_dupe_slugs() {
+    return db::build()
+      ->select_distinct(
+        array("parent_slug" => db::expr("CONCAT(`parent_id`, ':', LOWER(`slug`))")))
+      ->select("id")
+      ->select(array("C" => "COUNT(\"*\")"))
+      ->from("items")
+      ->having("C", ">", 1)
+      ->group_by("parent_slug")
+      ->execute();
+  }
+
+  static function find_dupe_names() {
+    // looking for photos, movies, and albums
+    return db::build()
+      ->select_distinct(
+        array("parent_name" => db::expr("CONCAT(`parent_id`, ':', LOWER(`name`))")))
+      ->select("id")
+      ->select(array("C" => "COUNT(\"*\")"))
+      ->from("items")
+      ->having("C", ">", 1)
+      ->group_by("parent_name")
+      ->execute();
+  }
+
+  static function find_dupe_base_names() {
+    // looking for photos or movies, not albums
+    return db::build()
+      ->select_distinct(
+        array("parent_base_name" => db::expr("CONCAT(`parent_id`, ':', LOWER(SUBSTR(`name`, 1, LOCATE('.', `name`) - 1)))")))
+      ->select("id")
+      ->select(array("C" => "COUNT(\"*\")"))
+      ->from("items")
+      ->where("type", "<>", "album")
+      ->having("C", ">", 1)
+      ->group_by("parent_base_name")
+      ->execute();
+  }
+
+  static function find_empty_item_caches($limit) {
+    return db::build()
+      ->select("items.id")
+      ->from("items")
+      ->where("relative_path_cache", "is", null)
+      ->or_where("relative_url_cache", "is", null)
+      ->limit($limit)
+      ->execute();
+  }
+
+  static function find_missing_access_caches() {
+    return self::find_missing_access_caches_limited(1 << 16);
+  }
+
+  static function find_missing_access_caches_limited($limit) {
+    return db::build()
+      ->select("items.id")
+      ->from("items")
+      ->join("access_caches", "items.id", "access_caches.item_id", "left")
+      ->where("access_caches.id", "is", null)
+      ->limit($limit)
+      ->execute();
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/gallery_theme.php b/modules/gallery/helpers/gallery_theme.php
new file mode 100644
index 0000000..3c6d71e
--- /dev/null
+++ b/modules/gallery/helpers/gallery_theme.php
@@ -0,0 +1,151 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class gallery_theme_Core {
+  static function head($theme) {
+    $session = Session::instance();
+    $buf = "";
+    $buf .= $theme->css("gallery.css");
+    if ($session->get("debug")) {
+      $buf .= $theme->css("debug.css");
+    }
+
+    if (module::is_active("rss")) {
+      if ($item = $theme->item()) {
+        if ($item->is_album()) {
+          $buf .= rss::feed_link("gallery/album/{$item->id}");
+        } else {
+          $buf .= rss::feed_link("gallery/album/{$item->parent()->id}");
+        }
+      } else if ($tag = $theme->tag()) {
+        $buf .= rss::feed_link("tag/tag/{$tag->id}");
+      }
+    }
+
+    if (count(locales::installed())) {
+      // Needed by the languages block
+      $buf .= $theme->script("jquery.cookie.js");
+    }
+
+    if ($session->get("l10n_mode", false)) {
+      $buf .= $theme->css("l10n_client.css")
+        . $theme->script("jquery.cookie.js")
+        . $theme->script("l10n_client.js");
+    }
+
+    $buf .= $theme->css("uploadify/uploadify.css");
+    return $buf;
+  }
+
+  static function admin_head($theme) {
+    $buf = $theme->css("gallery.css");
+    $buf .= $theme->script("gallery.panel.js");
+    $session = Session::instance();
+    if ($session->get("debug")) {
+      $buf .= $theme->css("debug.css");
+    }
+
+    if ($session->get("l10n_mode", false)) {
+      $buf .= $theme->css("l10n_client.css");
+      $buf .= $theme->script("jquery.cookie.js");
+      $buf .= $theme->script("l10n_client.js");
+    }
+    return $buf;
+  }
+
+  static function page_bottom($theme) {
+    $session = Session::instance();
+    if (gallery::show_profiler()) {
+      Profiler::enable();
+      $profiler = new Profiler();
+      $profiler->render();
+    }
+    $content = "";
+    if ($session->get("l10n_mode", false)) {
+      $content .= L10n_Client_Controller::l10n_form();
+    }
+
+    if ($session->get_once("after_install")) {
+      $content .= new View("welcome_message_loader.html");
+    }
+
+    if (identity::active_user()->admin && upgrade_checker::should_auto_check()) {
+      $content .= '<script type="text/javascript">
+        $.ajax({url: "' . url::site("admin/upgrade_checker/check_now?csrf=" .
+                                    access::csrf_token()) . '"});
+        </script>';
+    }
+    return $content;
+  }
+
+  static function admin_page_bottom($theme) {
+    $session = Session::instance();
+    if (gallery::show_profiler()) {
+      Profiler::enable();
+      $profiler = new Profiler();
+      $profiler->render();
+    }
+
+    // Redirect to the root album when the admin session expires.
+    $content = '<script type="text/javascript">
+      var adminReauthCheck = function() {
+        $.ajax({url: "' . url::site("admin?reauth_check=1") . '",
+                dataType: "json",
+                success: function(data){
+                  if ("location" in data) {
+                    document.location = data.location;
+                  }
+                }});
+      };
+      setInterval("adminReauthCheck();", 60 * 1000);
+      </script>';
+
+    if (upgrade_checker::should_auto_check()) {
+      $content .= '<script type="text/javascript">
+        $.ajax({url: "' . url::site("admin/upgrade_checker/check_now?csrf=" .
+                                    access::csrf_token()) . '"});
+        </script>';
+    }
+
+    if ($session->get("l10n_mode", false)) {
+      $content .= "\n" . L10n_Client_Controller::l10n_form();
+    }
+    return $content;
+  }
+
+  static function credits() {
+    $version_string = SafeString::of_safe_html(
+      '<bdo dir="ltr">Gallery ' . gallery::version_string() . '</bdo>');
+    return "<li class=\"g-first\">" .
+      t(module::get_var("gallery", "credits"),
+        array("url" => "http://galleryproject.org",
+              "gallery_version" => $version_string)) .
+      "</li>";
+  }
+
+  static function admin_credits() {
+    return gallery_theme::credits();
+  }
+
+  static function body_attributes() {
+    if (locales::is_rtl()) {
+      return 'class="rtl"';
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php
new file mode 100644
index 0000000..459784c
--- /dev/null
+++ b/modules/gallery/helpers/graphics.php
@@ -0,0 +1,546 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class graphics_Core {
+  private static $init;
+  private static $_rules_cache = array();
+
+  /**
+   * Add a new graphics rule.
+   *
+   * Rules are applied to targets (thumbnails and resizes) in priority order.  Rules are functions
+   * in the graphics class.  So for example, the following rule:
+   *
+   *   graphics::add_rule("gallery", "thumb", "gallery_graphics::resize",
+   *                       array("width" => 200, "height" => 200, "master" => Image::AUTO), 100);
+   *
+   * Specifies that "gallery" is adding a rule to resize thumbnails down to a max of 200px on
+   * the longest side.  The gallery module adds default rules at a priority of 100.  You can set
+   * higher and lower priorities to perform operations before or after this fires.
+   *
+   * @param string  $module_name the module that added the rule
+   * @param string  $target      the target for this operation ("thumb" or "resize")
+   * @param string  $operation   the name of the operation (<defining class>::method)
+   * @param array   $args        arguments to the operation
+   * @param integer $priority    the priority for this rule (lower priorities are run first)
+   */
+  static function add_rule($module_name, $target, $operation, $args, $priority) {
+    $rule = ORM::factory("graphics_rule");
+    $rule->module_name = $module_name;
+    $rule->target = $target;
+    $rule->operation = $operation;
+    $rule->priority = $priority;
+    $rule->args = serialize($args);
+    $rule->active = true;
+    $rule->save();
+
+    graphics::mark_dirty($target == "thumb", $target == "resize");
+  }
+
+  /**
+   * Remove any matching graphics rules
+   * @param string  $module_name the module that added the rule
+   * @param string  $target      the target for this operation ("thumb" or "resize")
+   * @param string  $operation   the name of the operation(<defining class>::method)
+   */
+  static function remove_rule($module_name, $target, $operation) {
+    db::build()
+      ->delete("graphics_rules")
+      ->where("module_name", "=", $module_name)
+      ->where("target", "=", $target)
+      ->where("operation", "=", $operation)
+      ->execute();
+
+    graphics::mark_dirty($target == "thumb", $target == "resize");
+  }
+
+  /**
+   * Remove all rules for this module
+   * @param string $module_name
+   */
+  static function remove_rules($module_name) {
+    $status = db::build()
+      ->delete("graphics_rules")
+      ->where("module_name", "=", $module_name)
+      ->execute();
+    if (count($status)) {
+      graphics::mark_dirty(true, true);
+    }
+  }
+
+  /**
+   * Activate the rules for this module, typically done when the module itself is deactivated.
+   * Note that this does not mark images as dirty so that if you deactivate and reactivate a
+   * module it won't cause all of your images to suddenly require a rebuild.
+   */
+  static function activate_rules($module_name) {
+    db::build()
+      ->update("graphics_rules")
+      ->set("active", true)
+      ->where("module_name", "=", $module_name)
+      ->execute();
+  }
+
+  /**
+   * Deactivate the rules for this module, typically done when the module itself is deactivated.
+   * Note that this does not mark images as dirty so that if you deactivate and reactivate a
+   * module it won't cause all of your images to suddenly require a rebuild.
+   */
+  static function deactivate_rules($module_name) {
+    db::build()
+      ->update("graphics_rules")
+      ->set("active", false)
+      ->where("module_name", "=", $module_name)
+      ->execute();
+  }
+
+  /**
+   * Rebuild the thumb and resize for the given item.
+   * @param Item_Model $item
+   */
+  static function generate($item) {
+    if ($item->thumb_dirty) {
+      $ops["thumb"] = $item->thumb_path();
+    }
+    if ($item->resize_dirty && $item->is_photo()) {
+      $ops["resize"] = $item->resize_path();
+    }
+
+    try {
+      foreach ($ops as $target => $output_file) {
+        $working_file = $item->file_path();
+        // Delete anything that might already be there
+        @unlink($output_file);
+        switch ($item->type) {
+        case "movie":
+          // Run movie_extract_frame events, which can either:
+          //  - generate an output file, bypassing the ffmpeg-based movie::extract_frame
+          //  - add to the options sent to movie::extract_frame (e.g. change frame extract time,
+          //    add de-interlacing arguments to ffmpeg... see movie helper for more info)
+          // Note that the args are similar to those of the events in gallery_graphics
+          $movie_options_wrapper = new stdClass();
+          $movie_options_wrapper->movie_options = array();
+          module::event("movie_extract_frame", $working_file, $output_file,
+                        $movie_options_wrapper, $item);
+          // If no output_file generated by events, run movie::extract_frame with movie_options
+          clearstatcache();
+          if (@filesize($output_file) == 0) {
+            try {
+              movie::extract_frame($working_file, $output_file, $movie_options_wrapper->movie_options);
+              // If we're here, we know ffmpeg is installed and the movie is valid.  Because the
+              // user may not always have had ffmpeg installed, the movie's width, height, and
+              // mime type may need updating.  Let's use this opportunity to make sure they're
+              // correct.  It's not optimal to do it at this low level, but it's not trivial to find
+              // these cases quickly in an upgrade script.
+              list ($width, $height, $mime_type) = movie::get_file_metadata($working_file);
+              // Only set them if they need updating to avoid marking them as "changed"
+              if (($item->width != $width) || ($item->height != $height) ||
+                  ($item->mime_type != $mime_type)) {
+                $item->width = $width;
+                $item->height = $height;
+                $item->mime_type = $mime_type;
+              }
+            } catch (Exception $e) {
+              // Didn't work, likely because of MISSING_FFMPEG - use placeholder
+              graphics::_replace_image_with_placeholder($item, $target);
+              break;
+            }
+          }
+          $working_file = $output_file;
+
+        case "photo":
+          // Run the graphics rules (for both movies and photos)
+          foreach (self::_get_rules($target) as $rule) {
+            $args = array($working_file, $output_file, unserialize($rule->args), $item);
+            call_user_func_array($rule->operation, $args);
+            $working_file = $output_file;
+          }
+          break;
+
+        case "album":
+          if (!$cover = $item->album_cover()) {
+            // This album has no cover; copy its placeholder image.  Because of an old bug, it's
+            // possible that there's an album cover item id that points to an invalid item.  In that
+            // case, just null out the album cover item id.  It's not optimal to do that at this low
+            // level, but it's not trivial to find these cases quickly in an upgrade script and if we
+            // don't do this, the album may be permanently marked as "needs rebuilding"
+            //
+            // ref: http://sourceforge.net/apps/trac/gallery/ticket/1172
+            //      http://galleryproject.org/node/96926
+            if ($item->album_cover_item_id) {
+              $item->album_cover_item_id = null;
+              $item->save();
+            }
+            graphics::_replace_image_with_placeholder($item, $target);
+            break;
+          }
+          if ($cover->thumb_dirty) {
+            graphics::generate($cover);
+          }
+          if (!$cover->thumb_dirty) {
+            // Make the album cover from the cover item's thumb.  Run gallery_graphics::resize with
+            // null options and it will figure out if this is a direct copy or conversion to jpg.
+            $working_file = $cover->thumb_path();
+            gallery_graphics::resize($working_file, $output_file, null, $item);
+          }
+          break;
+        }
+      }
+
+      if (!empty($ops["thumb"])) {
+        if (file_exists($item->thumb_path())) {
+          $item->thumb_dirty = 0;
+        } else {
+          Kohana_Log::add("error", "Failed to rebuild thumb image: $item->title");
+          graphics::_replace_image_with_placeholder($item, "thumb");
+        }
+      }
+
+      if (!empty($ops["resize"]))  {
+        if (file_exists($item->resize_path())) {
+          $item->resize_dirty = 0;
+        } else {
+          Kohana_Log::add("error", "Failed to rebuild resize image: $item->title");
+          graphics::_replace_image_with_placeholder($item, "resize");
+        }
+      }
+      graphics::_update_item_dimensions($item);
+      $item->save();
+    } catch (Exception $e) {
+      // Something went wrong rebuilding the image.  Replace with the placeholder images,
+      // leave it dirty and move on.
+      Kohana_Log::add("error", "Caught exception rebuilding images: {$item->title}\n" .
+                      $e->getMessage() . "\n" . $e->getTraceAsString());
+      if ($item->is_photo()) {
+        graphics::_replace_image_with_placeholder($item, "resize");
+      }
+      graphics::_replace_image_with_placeholder($item, "thumb");
+      try {
+        graphics::_update_item_dimensions($item);
+      } catch (Exception $e) {
+        // Looks like get_file_metadata couldn't identify our placeholders.  We should never get
+        // here, but in the odd case we do, we need to do something.  Let's put in hardcoded values.
+        if ($item->is_photo()) {
+          list ($item->resize_width, $item->resize_height) = array(200, 200);
+        }
+        list ($item->thumb_width, $item->thumb_height) = array(200, 200);
+      }
+      $item->save();
+      throw $e;
+    }
+  }
+
+  private static function _update_item_dimensions($item) {
+    if ($item->is_photo()) {
+      list ($item->resize_width, $item->resize_height) =
+        photo::get_file_metadata($item->resize_path());
+    }
+    list ($item->thumb_width, $item->thumb_height) =
+      photo::get_file_metadata($item->thumb_path());
+  }
+
+  private static function _replace_image_with_placeholder($item, $target) {
+    if ($item->is_album() && !$item->album_cover_item_id) {
+      $input_path = MODPATH . "gallery/images/missing_album_cover.jpg";
+    } else if ($item->is_movie() || ($item->is_album() && $item->album_cover()->is_movie())) {
+      $input_path = MODPATH . "gallery/images/missing_movie.jpg";
+    } else {
+      $input_path = MODPATH . "gallery/images/missing_photo.jpg";
+    }
+
+    if ($target == "thumb") {
+      $output_path = $item->thumb_path();
+      $size = module::get_var("gallery", "thumb_size", 200);
+    } else {
+      $output_path = $item->resize_path();
+      $size = module::get_var("gallery", "resize_size", 640);
+    }
+    $options = array("width" => $size, "height" => $size, "master" => Image::AUTO);
+
+    try {
+      // Copy/convert/resize placeholder as needed.
+      gallery_graphics::resize($input_path, $output_path, $options, null);
+    } catch (Exception $e) {
+      // Copy/convert/resize didn't work.  Add to the log and copy the jpg version (which could have
+      // a non-jpg extension).  This is less than ideal, but it's better than putting nothing
+      // there and causing theme views to act strangely because a file is missing.
+      // @todo we should handle this better.
+      Kohana_Log::add("error", "Caught exception converting placeholder for missing image: " .
+                      $item->title . "\n" . $e->getMessage() . "\n" . $e->getTraceAsString());
+      copy($input_path, $output_path);
+    }
+
+    if (!file_exists($output_path)) {
+      // Copy/convert/resize didn't throw an exception, but still didn't work - do the same as above.
+      // @todo we should handle this better.
+      Kohana_Log::add("error", "Failed to convert placeholder for missing image: $item->title");
+      copy($input_path, $output_path);
+    }
+  }
+
+  private static function _get_rules($target) {
+    if (empty(self::$_rules_cache[$target])) {
+      $rules = array();
+      foreach (ORM::factory("graphics_rule")
+               ->where("target", "=", $target)
+               ->where("active", "=", true)
+               ->order_by("priority", "asc")
+               ->find_all() as $rule) {
+        $rules[] = (object)$rule->as_array();
+      }
+      self::$_rules_cache[$target] = $rules;
+    }
+    return self::$_rules_cache[$target];
+  }
+
+  /**
+   * Return a query result that locates all items with dirty images.
+   * @return Database_Result Query result
+   */
+  static function find_dirty_images_query() {
+    return db::build()
+      ->from("items")
+      ->and_open()
+      ->where("thumb_dirty", "=", 1)
+      ->and_open()
+      ->where("type", "<>", "album")
+      ->or_where("album_cover_item_id", "IS NOT", null)
+      ->close()
+      ->or_open()
+      ->where("resize_dirty", "=", 1)
+      ->where("type", "=", "photo")
+      ->close()
+      ->close();
+  }
+
+  /**
+   * Mark thumbnails and resizes as dirty.  They will have to be rebuilt.  Optionally, only those of
+   * a specified type and/or mime type can be marked (e.g. $type="movie" to rebuild movies only).
+   */
+  static function mark_dirty($thumbs, $resizes, $type=null, $mime_type=null) {
+    if ($thumbs || $resizes) {
+      $db = db::build()
+        ->update("items");
+      if ($type) {
+        $db->where("type", "=", $type);
+      }
+      if ($mime_type) {
+        $db->where("mime_type", "=", $mime_type);
+      }
+      if ($thumbs) {
+        $db->set("thumb_dirty", 1);
+      }
+      if ($resizes) {
+        $db->set("resize_dirty", 1);
+      }
+      $db->execute();
+    }
+
+    $count = graphics::find_dirty_images_query()->count_records();
+    if ($count) {
+      site_status::warning(
+        t2("One of your photos is out of date. <a %attrs>Click here to fix it</a>",
+           "%count of your photos are out of date. <a %attrs>Click here to fix them</a>",
+           $count,
+           array("attrs" => html::mark_clean(sprintf(
+             'href="%s" class="g-dialog-link"',
+             url::site("admin/maintenance/start/gallery_task::rebuild_dirty_images?csrf=__CSRF__"))))),
+        "graphics_dirty");
+    }
+  }
+
+  /**
+   * Detect which graphics toolkits are available on this system.  Return an array of key value
+   * pairs where the key is one of gd, imagemagick, graphicsmagick and the value is information
+   * about that toolkit.  For GD we return the version string, and for ImageMagick and
+   * GraphicsMagick we return the path to the directory containing the appropriate binaries.
+   */
+  static function detect_toolkits() {
+    $toolkits = new stdClass();
+    $toolkits->gd = new stdClass();
+    $toolkits->imagemagick = new stdClass();
+    $toolkits->graphicsmagick = new stdClass();
+
+    // GD is special, it doesn't use exec()
+    $gd = function_exists("gd_info") ? gd_info() : array();
+    $toolkits->gd->name = "GD";
+    if (!isset($gd["GD Version"])) {
+      $toolkits->gd->installed = false;
+      $toolkits->gd->error = t("GD is not installed");
+    } else {
+      $toolkits->gd->installed = true;
+      $toolkits->gd->version = $gd["GD Version"];
+      $toolkits->gd->rotate = function_exists("imagerotate");
+      $toolkits->gd->sharpen = function_exists("imageconvolution");
+      $toolkits->gd->binary = "";
+      $toolkits->gd->dir = "";
+
+      if (!$toolkits->gd->rotate && !$toolkits->gd->sharpen) {
+        $toolkits->gd->error =
+          t("You have GD version %version, but it lacks image rotation and sharpening.",
+            array("version" => $gd["GD Version"]));
+      } else if (!$toolkits->gd->rotate) {
+        $toolkits->gd->error =
+          t("You have GD version %version, but it lacks image rotation.",
+            array("version" => $gd["GD Version"]));
+      } else if (!$toolkits->gd->sharpen) {
+        $toolkits->gd->error =
+          t("You have GD version %version, but it lacks image sharpening.",
+            array("version" => $gd["GD Version"]));
+      }
+    }
+
+    if (!function_exists("exec")) {
+      $toolkits->imagemagick->installed = false;
+      $toolkits->imagemagick->error = t("ImageMagick requires the <b>exec</b> function");
+
+      $toolkits->graphicsmagick->installed = false;
+      $toolkits->graphicsmagick->error = t("GraphicsMagick requires the <b>exec</b> function");
+    } else {
+      // ImageMagick & GraphicsMagick
+      $magick_kits = array(
+        "imagemagick" => array(
+          "name" => "ImageMagick", "binary" => "convert", "version_arg" => "-version",
+          "version_regex" => "/Version: \S+ (\S+)/"),
+        "graphicsmagick" => array(
+          "name" => "GraphicsMagick", "binary" => "gm", "version_arg" => "version",
+          "version_regex" => "/\S+ (\S+)/"));
+      // Loop through the kits
+      foreach ($magick_kits as $index => $settings) {
+        $path = system::find_binary(
+          $settings["binary"], module::get_var("gallery", "graphics_toolkit_path"));
+        $toolkits->$index->name = $settings["name"];
+        if ($path) {
+          if (@is_file($path) &&
+              preg_match(
+                $settings["version_regex"], shell_exec($path . " " . $settings["version_arg"]), $matches)) {
+            $version = $matches[1];
+
+            $toolkits->$index->installed = true;
+            $toolkits->$index->version = $version;
+            $toolkits->$index->binary = $path;
+            $toolkits->$index->dir = dirname($path);
+            $toolkits->$index->rotate = true;
+            $toolkits->$index->sharpen = true;
+          } else {
+            $toolkits->$index->installed = false;
+            $toolkits->$index->error =
+              t("%toolkit_name is installed, but PHP's open_basedir restriction prevents Gallery from using it.",
+                array("toolkit_name" => $settings["name"]));
+          }
+        } else {
+          $toolkits->$index->installed = false;
+          $toolkits->$index->error =
+            t("We could not locate %toolkit_name on your system.",
+              array("toolkit_name" => $settings["name"]));
+        }
+      }
+    }
+
+    return $toolkits;
+  }
+
+  /**
+   * This needs to be run once, after the initial install, to choose a graphics toolkit.
+   */
+  static function choose_default_toolkit() {
+    // Detect a graphics toolkit
+    $toolkits = graphics::detect_toolkits();
+    foreach (array("imagemagick", "graphicsmagick", "gd") as $tk) {
+      if ($toolkits->$tk->installed) {
+        module::set_var("gallery", "graphics_toolkit", $tk);
+        module::set_var("gallery", "graphics_toolkit_path", $toolkits->$tk->dir);
+        break;
+      }
+    }
+
+    if (!module::get_var("gallery", "graphics_toolkit")) {
+      site_status::warning(
+        t("Graphics toolkit missing!  Please <a href=\"%url\">choose a toolkit</a>",
+          array("url" => html::mark_clean(url::site("admin/graphics")))),
+        "missing_graphics_toolkit");
+    }
+  }
+
+  /**
+   * Choose which driver the Kohana Image library uses.
+   */
+  static function init_toolkit() {
+    if (self::$init) {
+      return;
+    }
+    switch(module::get_var("gallery", "graphics_toolkit")) {
+    case "gd":
+      Kohana_Config::instance()->set("image.driver", "GD");
+      break;
+
+    case "imagemagick":
+      Kohana_Config::instance()->set("image.driver", "ImageMagick");
+      Kohana_Config::instance()->set(
+        "image.params.directory", module::get_var("gallery", "graphics_toolkit_path"));
+      break;
+
+    case "graphicsmagick":
+      Kohana_Config::instance()->set("image.driver", "GraphicsMagick");
+      Kohana_Config::instance()->set(
+        "image.params.directory", module::get_var("gallery", "graphics_toolkit_path"));
+      break;
+    }
+
+    self::$init = 1;
+  }
+
+  /**
+   * Verify that a specific graphics function is available with the active toolkit.
+   * @param  string  $func (eg rotate, sharpen)
+   * @return boolean
+   */
+  static function can($func) {
+    if (module::get_var("gallery", "graphics_toolkit") == "gd") {
+      switch ($func) {
+      case "rotate":
+        return function_exists("imagerotate");
+
+      case "sharpen":
+        return function_exists("imageconvolution");
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Return the max file size that this graphics toolkit can handle.
+   */
+  static function max_filesize() {
+    if (module::get_var("gallery", "graphics_toolkit") == "gd") {
+      $memory_limit = trim(ini_get("memory_limit"));
+      $memory_limit_bytes = num::convert_to_bytes($memory_limit);
+
+      // GD expands images in memory and uses 4 bytes of RAM for every byte
+      // in the file.
+      $max_filesize = $memory_limit_bytes / 4;
+      $max_filesize_human_readable = num::convert_to_human_readable($max_filesize);
+      return array($max_filesize, $max_filesize_human_readable);
+    }
+
+    // Some arbitrarily large size
+    return array(1000000000, "1G");
+  }
+}
diff --git a/modules/gallery/helpers/identity.php b/modules/gallery/helpers/identity.php
new file mode 100644
index 0000000..5fc0f2f
--- /dev/null
+++ b/modules/gallery/helpers/identity.php
@@ -0,0 +1,247 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class identity_Core {
+  protected static $available;
+
+  /**
+   * Return a list of installed Identity Drivers.
+   *
+   * @return boolean true if the driver supports updates; false if read only
+   */
+  static function providers() {
+    if (empty(self::$available)) {
+      $drivers = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS);
+      foreach (module::available() as $module_name => $module) {
+        if (file_exists(MODPATH . "{$module_name}/config/identity.php")) {
+          $drivers->$module_name = $module->description;
+        }
+      }
+      self::$available = $drivers;
+    }
+    return self::$available;
+  }
+
+  /**
+   * Frees the current instance of the identity provider so the next call to instance will reload
+   *
+   * @param   string  configuration
+   * @return  Identity_Core
+   */
+  static function reset() {
+    IdentityProvider::reset();
+  }
+
+  /**
+   * Make sure that we have a session and group_ids cached in the session.
+   */
+  static function load_user() {
+    try {
+      // Call IdentityProvider::instance() now to force the load of the user interface classes.
+      // We are about to load the active user from the session and which needs the user definition
+      // class, which can't be reached by Kohana's heiracrchical lookup.
+      IdentityProvider::instance();
+
+      $session = Session::instance();
+      if (!($user = $session->get("user"))) {
+        identity::set_active_user($user = identity::guest());
+      }
+
+      // The installer cannot set a user into the session, so it just sets an id which we should
+      // upconvert into a user.
+      // @todo set the user name into the session instead of 2 and then use it to get the
+      //       user object
+      if ($user === 2) {
+        $session->delete("user");  // delete it so that identity code isn't confused by the integer
+        auth::login(IdentityProvider::instance()->admin_user());
+      }
+
+      // Cache the group ids for a day to trade off performance for security updates.
+      if (!$session->get("group_ids") || $session->get("group_ids_timeout", 0) < time()) {
+        $ids = array();
+        foreach ($user->groups() as $group) {
+          $ids[] = $group->id;
+        }
+        $session->set("group_ids", $ids);
+        $session->set("group_ids_timeout", time() + 86400);
+      }
+    } catch (Exception $e) {
+      // Log it, so we at least have so notification that we swallowed the exception.
+      Kohana_Log::add("error", "load_user Exception: " .
+                      $e->getMessage() . "\n" . $e->getTraceAsString());
+      try {
+        Session::instance()->destroy();
+      } catch (Exception $e) {
+        // We don't care if there was a problem destroying the session.
+      }
+      url::redirect(item::root()->abs_url());
+    }
+  }
+
+  /**
+   * Return the array of group ids this user belongs to
+   *
+   * @return array
+   */
+  static function group_ids_for_active_user() {
+    return Session::instance()->get("group_ids", array(1));
+  }
+
+  /**
+   * Return the active user.  If there's no active user, return the guest user.
+   *
+   * @return User_Definition
+   */
+  static function active_user() {
+    // @todo (maybe) cache this object so we're not always doing session lookups.
+    $user = Session::instance()->get("user", null);
+    if (!isset($user)) {
+      // Don't do this as a fallback in the Session::get() call because it can trigger unnecessary
+      // work.
+      $user = identity::guest();
+    }
+    return $user;
+  }
+
+  /**
+   * Change the active user.
+   * @param User_Definition $user
+   */
+  static function set_active_user($user) {
+    $session = Session::instance();
+    $session->set("user", $user);
+    $session->delete("group_ids");
+    identity::load_user();
+  }
+
+  /**
+   * Determine if if the current driver supports updates.
+   *
+   * @return boolean true if the driver supports updates; false if read only
+   */
+  static function is_writable() {
+    return IdentityProvider::instance()->is_writable();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::guest.
+   */
+  static function guest() {
+    return IdentityProvider::instance()->guest();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::admin_user.
+   */
+  static function admin_user() {
+    return IdentityProvider::instance()->admin_user();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::create_user.
+   */
+  static function create_user($name, $full_name, $password, $email) {
+    return IdentityProvider::instance()->create_user($name, $full_name, $password, $email);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::is_correct_password.
+   */
+  static function is_correct_password($user, $password) {
+    return IdentityProvider::instance()->is_correct_password($user, $password);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_user.
+   */
+  static function lookup_user($id) {
+    return IdentityProvider::instance()->lookup_user($id);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_user_by_name.
+   */
+  static function lookup_user_by_name($name) {
+    return IdentityProvider::instance()->lookup_user_by_name($name);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::create_group.
+   */
+  static function create_group($name) {
+    return IdentityProvider::instance()->create_group($name);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::everybody.
+   */
+  static function everybody() {
+    return IdentityProvider::instance()->everybody();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::registered_users.
+   */
+  static function registered_users() {
+    return IdentityProvider::instance()->registered_users();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_group.
+   */
+  static function lookup_group($id) {
+    return IdentityProvider::instance()->lookup_group($id);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_group_by_name.
+   */
+  static function lookup_group_by_name($name) {
+    return IdentityProvider::instance()->lookup_group_by_name($name);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::get_user_list.
+   */
+  static function get_user_list($ids) {
+    return IdentityProvider::instance()->get_user_list($ids);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::groups.
+   */
+  static function groups() {
+    return IdentityProvider::instance()->groups();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::add_user_to_group.
+   */
+  static function add_user_to_group($user, $group) {
+    return IdentityProvider::instance()->add_user_to_group($user, $group);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::remove_user_to_group.
+   */
+  static function remove_user_from_group($user, $group) {
+    return IdentityProvider::instance()->remove_user_from_group($user, $group);
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php
new file mode 100644
index 0000000..9882a9c
--- /dev/null
+++ b/modules/gallery/helpers/item.php
@@ -0,0 +1,433 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class item_Core {
+  static function move($source, $target) {
+    access::required("view", $source);
+    access::required("view", $target);
+    access::required("edit", $source);
+    access::required("edit", $target);
+
+    $parent = $source->parent();
+    if ($parent->album_cover_item_id == $source->id) {
+      if ($parent->children_count() > 1) {
+        foreach ($parent->children(2) as $child) {
+          if ($child->id != $source->id) {
+            $new_cover_item = $child;
+            break;
+          }
+        }
+        item::make_album_cover($new_cover_item);
+      } else {
+        item::remove_album_cover($parent);
+      }
+    }
+
+    $orig_name = $source->name;
+    $source->parent_id = $target->id;
+    $source->save();
+    if ($orig_name != $source->name) {
+      switch ($source->type) {
+      case "album":
+        message::info(
+          t("Album <b>%old_name</b> renamed to <b>%new_name</b> to avoid a conflict",
+            array("old_name" => $orig_name, "new_name" => $source->name)));
+        break;
+
+      case "photo":
+        message::info(
+          t("Photo <b>%old_name</b> renamed to <b>%new_name</b> to avoid a conflict",
+            array("old_name" => $orig_name, "new_name" => $source->name)));
+        break;
+
+      case "movie":
+        message::info(
+          t("Movie <b>%old_name</b> renamed to <b>%new_name</b> to avoid a conflict",
+            array("old_name" => $orig_name, "new_name" => $source->name)));
+        break;
+      }
+    }
+
+    // If the target has no cover item, make this it.
+    if ($target->album_cover_item_id == null)  {
+      item::make_album_cover($source);
+    }
+  }
+
+  static function make_album_cover($item) {
+    $parent = $item->parent();
+    access::required("view", $item);
+    access::required("view", $parent);
+    access::required("edit", $parent);
+
+    $old_album_cover_id = $parent->album_cover_item_id;
+
+    model_cache::clear();
+    $parent->album_cover_item_id = $item->is_album() ? $item->album_cover_item_id : $item->id;
+    $parent->save();
+    graphics::generate($parent);
+
+    // Walk up the parent hierarchy and set album covers if necessary
+    $grand_parent = $parent->parent();
+    if ($grand_parent && access::can("edit", $grand_parent) &&
+        $grand_parent->album_cover_item_id == null)  {
+      item::make_album_cover($parent);
+    }
+
+    // When albums are album covers themselves, we hotlink directly to the target item.  This
+    // means that when we change an album cover, the grandparent may have a deep link to the old
+    // album cover.  So find any parent albums that had the old item as their album cover and
+    // switch them over to the new item.
+    if ($old_album_cover_id) {
+      foreach ($item->parents(array(array("album_cover_item_id", "=", $old_album_cover_id)))
+               as $ancestor) {
+        if (access::can("edit", $ancestor)) {
+          $ancestor->album_cover_item_id = $parent->album_cover_item_id;
+          $ancestor->save();
+          graphics::generate($ancestor);
+        }
+      }
+    }
+  }
+
+  static function remove_album_cover($album) {
+    access::required("view", $album);
+    access::required("edit", $album);
+
+    model_cache::clear();
+    $album->album_cover_item_id = null;
+    $album->save();
+    graphics::generate($album);
+  }
+
+  /**
+   * Sanitize a filename into something presentable as an item title
+   * @param string $filename
+   * @return string title
+   */
+  static function convert_filename_to_title($filename) {
+    $title = strtr($filename, "_", " ");
+    $title = preg_replace("/\..{3,4}$/", "", $title);
+    $title = preg_replace("/ +/", " ", $title);
+    return $title;
+  }
+
+  /**
+   * Convert a filename into something we can use as a url component.
+   * @param string $filename
+   */
+  static function convert_filename_to_slug($filename) {
+    $result = str_replace("&", "-and-", $filename);
+    $result = str_replace(" ", "-", $result);
+
+    // It's not easy to extend the text helper since it's called by the Input class which is
+    // referenced in hooks/init_gallery, so it's
+    if (class_exists("transliterate")) {
+      $result = transliterate::utf8_to_ascii($result);
+    } else {
+      $result = text::transliterate_to_ascii($result);
+    }
+    $result = preg_replace("/[^A-Za-z0-9-_]+/", "-", $result);
+    $result = preg_replace("/-+/", "-", $result);
+    return trim($result, "-");
+  }
+
+  /**
+   * Display delete confirmation message and form
+   * @param object $item
+   * @return string form
+   */
+  static function get_delete_form($item) {
+    $page_type = Input::instance()->get("page_type");
+    $from_id = Input::instance()->get("from_id");
+    $form = new Forge(
+      "quick/delete/$item->id?page_type=$page_type&from_id=$from_id", "",
+      "post", array("id" => "g-confirm-delete"));
+    $group = $form->group("confirm_delete")->label(t("Confirm Deletion"));
+    $group->submit("")->value(t("Delete"));
+    $form->script("")
+      ->url(url::abs_file("modules/gallery/js/item_form_delete.js"));
+    return $form;
+  }
+
+  /**
+   * Get the next weight value
+   */
+  static function get_max_weight() {
+    // Guard against an empty result when we create the first item.  It's unfortunate that we
+    // have to check this every time.
+    // @todo: figure out a better way to bootstrap the weight.
+    $result = db::build()
+      ->select("weight")->from("items")
+      ->order_by("weight", "desc")->limit(1)
+      ->execute()->current();
+    return ($result ? $result->weight : 0) + 1;
+  }
+
+  /**
+   * Add a set of restrictions to any following queries to restrict access only to items
+   * viewable by the active user.
+   * @chainable
+   */
+  static function viewable($model) {
+    $view_restrictions = array();
+    if (!identity::active_user()->admin) {
+      foreach (identity::group_ids_for_active_user() as $id) {
+        $view_restrictions[] = array("items.view_$id", "=", access::ALLOW);
+      }
+    }
+
+    if (count($view_restrictions)) {
+      $model->and_open()->merge_or_where($view_restrictions)->close();
+    }
+
+    return $model;
+  }
+
+  /**
+   * Find an item by its path.  If there's no match, return an empty Item_Model.
+   * NOTE: the caller is responsible for performing security checks on the resulting item.
+   * @param string $path
+   * @return object Item_Model
+   */
+  static function find_by_path($path) {
+    $path = trim($path, "/");
+
+    // The root path name is NULL not "", hence this workaround.
+    if ($path == "") {
+      return item::root();
+    }
+
+    // Check to see if there's an item in the database with a matching relative_path_cache value.
+    // Since that field is urlencoded, we must urlencoded the components of the path.
+    foreach (explode("/", $path) as $part) {
+      $encoded_array[] = rawurlencode($part);
+    }
+    $encoded_path = join("/", $encoded_array);
+    $item = ORM::factory("item")
+      ->where("relative_path_cache", "=", $encoded_path)
+      ->find();
+    if ($item->loaded()) {
+      return $item;
+    }
+
+    // Since the relative_path_cache field is a cache, it can be unavailable.  If we don't find
+    // anything, fall back to checking the path the hard way.
+    $paths = explode("/", $path);
+    foreach (ORM::factory("item")
+             ->where("name", "=", end($paths))
+             ->where("level", "=", count($paths) + 1)
+             ->find_all() as $item) {
+      if (urldecode($item->relative_path()) == $path) {
+        return $item;
+      }
+    }
+
+    return new Item_Model();
+  }
+
+
+  /**
+   * Locate an item using the URL.  We assume that the url is in the form /a/b/c where each
+   * component matches up with an item slug.  If there's no match, return an empty Item_Model
+   * NOTE: the caller is responsible for performing security checks on the resulting item.
+   * @param string $url the relative url fragment
+   * @return Item_Model
+   */
+  static function find_by_relative_url($relative_url) {
+    // In most cases, we'll have an exact match in the relative_url_cache item field.
+    // but failing that, walk down the tree until we find it.  The fallback code will fix caches
+    // as it goes, so it'll never be run frequently.
+    $item = ORM::factory("item")->where("relative_url_cache", "=", $relative_url)->find();
+    if (!$item->loaded()) {
+      $segments = explode("/", $relative_url);
+      foreach (ORM::factory("item")
+               ->where("slug", "=", end($segments))
+               ->where("level", "=", count($segments) + 1)
+               ->find_all() as $match) {
+        if ($match->relative_url() == $relative_url) {
+          $item = $match;
+        }
+      }
+    }
+    return $item;
+  }
+
+  /**
+   * Return the root Item_Model
+   * @return Item_Model
+   */
+  static function root() {
+    return model_cache::get("item", 1);
+  }
+
+  /**
+   * Return a query to get a random Item_Model, with optional filters.
+   * Usage: item::random_query()->execute();
+   *
+   * Note: You can add your own ->where() clauses but if your Gallery is
+   * small or your where clauses are over-constrained you may wind up with
+   * no item.  You should try running this a few times in a loop if you
+   * don't get an item back.
+   */
+  static function random_query() {
+    // Pick a random number and find the item that's got nearest smaller number.
+    // This approach works best when the random numbers in the system are roughly evenly
+    // distributed so this is going to be more efficient with larger data sets.
+    return ORM::factory("item")
+      ->viewable()
+      ->where("rand_key", "<", random::percent())
+      ->order_by("rand_key", "DESC");
+  }
+
+  /**
+   * Find the position of the given item in its parent album.  The resulting
+   * value is 1-indexed, so the first child in the album is at position 1.
+   *
+   * @param Item_Model $item
+   * @param array      $where an array of arrays, each compatible with ORM::where()
+   */
+  static function get_position($item, $where=array()) {
+    $album = $item->parent();
+
+    if (!strcasecmp($album->sort_order, "DESC")) {
+      $comp = ">";
+    } else {
+      $comp = "<";
+    }
+    $query_model = ORM::factory("item");
+
+    // If the comparison column has NULLs in it, we can't use comparators on it
+    // and will have to deal with it the hard way.
+    $count = $query_model->viewable()
+      ->where("parent_id", "=", $album->id)
+      ->where($album->sort_column, "IS", null)
+      ->merge_where($where)
+      ->count_all();
+
+    if (empty($count)) {
+      // There are no NULLs in the sort column, so we can just use it directly.
+      $sort_column = $album->sort_column;
+
+      $position = $query_model->viewable()
+        ->where("parent_id", "=", $album->id)
+        ->where($sort_column, $comp, $item->$sort_column)
+        ->merge_where($where)
+        ->count_all();
+
+      // We stopped short of our target value in the sort (notice that we're
+      // using a inequality comparator above) because it's possible that we have
+      // duplicate values in the sort column.  An equality check would just
+      // arbitrarily pick one of those multiple possible equivalent columns,
+      // which would mean that if you choose a sort order that has duplicates,
+      // it'd pick any one of them as the child's "position".
+      //
+      // Fix this by doing a 2nd query where we iterate over the equivalent
+      // columns and add them to our position count.
+      foreach ($query_model->viewable()
+               ->select("id")
+               ->where("parent_id", "=", $album->id)
+               ->where($sort_column, "=", $item->$sort_column)
+               ->merge_where($where)
+               ->order_by(array("id" => "ASC"))
+               ->find_all() as $row) {
+        $position++;
+        if ($row->id == $item->id) {
+          break;
+        }
+      }
+    } else {
+      // There are NULLs in the sort column, so we can't use MySQL comparators.
+      // Fall back to iterating over every child row to get to the current one.
+      // This can be wildly inefficient for really large albums, but it should
+      // be a rare case that the user is sorting an album with null values in
+      // the sort column.
+      //
+      // Reproduce the children() functionality here using Database directly to
+      // avoid loading the whole ORM for each row.
+      $order_by = array($album->sort_column => $album->sort_order);
+      // Use id as a tie breaker
+      if ($album->sort_column != "id") {
+        $order_by["id"] = "ASC";
+      }
+
+      $position = 0;
+      foreach ($query_model->viewable()
+               ->select("id")
+               ->where("parent_id", "=", $album->id)
+               ->merge_where($where)
+               ->order_by($order_by)
+               ->find_all() as $row) {
+        $position++;
+        if ($row->id == $item->id) {
+          break;
+        }
+      }
+    }
+
+    return $position;
+  }
+
+  /**
+   * Set the display context callback for any future item renders.
+   */
+  static function set_display_context_callback() {
+    if (!request::user_agent("robot")) {
+      $args = func_get_args();
+      Cache::instance()->set("display_context_" . $sid = Session::instance()->id(), $args,
+                             array("display_context"));
+    }
+  }
+
+  /**
+   * Get rid of the display context callback
+   */
+  static function clear_display_context_callback() {
+    Cache::instance()->delete("display_context_" . $sid = Session::instance()->id());
+  }
+
+  /**
+   * Call the display context callback for the given item
+   */
+  static function get_display_context($item) {
+    if (!request::user_agent("robot")) {
+      $args = Cache::instance()->get("display_context_" . $sid = Session::instance()->id());
+      $callback = $args[0];
+      $args[0] = $item;
+    }
+
+    if (empty($callback)) {
+      $callback = "Albums_Controller::get_display_context";
+      $args = array($item);
+    }
+    return call_user_func_array($callback, $args);
+  }
+
+  /**
+   * Reset all child weights of a given album to a monotonically increasing sequence based on the
+   * current sort order of the album.
+   */
+  static function resequence_child_weights($album) {
+    $weight = 0;
+    foreach ($album->children() as $child) {
+      $child->weight = ++$weight;
+      $child->save();
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/item_rest.php b/modules/gallery/helpers/item_rest.php
new file mode 100644
index 0000000..efeba2e
--- /dev/null
+++ b/modules/gallery/helpers/item_rest.php
@@ -0,0 +1,210 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class item_rest_Core {
+  /**
+   * For items that are collections, you can specify the following additional query parameters to
+   * query the collection.  You can specify them in any combination.
+   *
+   *   scope=direct
+   *     Only return items that are immediately under this one
+   *   scope=all
+   *     Return items anywhere under this one
+   *
+   *   name=<substring>
+   *     Only return items where the name contains this substring
+   *
+   *   random=true
+   *     Return a single random item
+   *
+   *   type=<comma separate list of photo, movie or album>
+   *     Limit the type to types in this list, eg: "type=photo,movie".
+   *     Also limits the types returned in the member collections (same behaviour as item_rest).
+   */
+  static function get($request) {
+    $item = rest::resolve($request->url);
+    access::required("view", $item);
+
+    $p = $request->params;
+    if (isset($p->random)) {
+      $orm = item::random_query()->offset(0)->limit(1);
+    } else {
+      $orm = ORM::factory("item")->viewable();
+    }
+
+    if (empty($p->scope)) {
+      $p->scope = "direct";
+    }
+
+    if (!in_array($p->scope, array("direct", "all"))) {
+      throw new Rest_Exception("Bad Request", 400);
+    }
+
+    if ($p->scope == "direct") {
+      $orm->where("parent_id", "=", $item->id);
+    } else {
+      $orm->where("left_ptr", ">", $item->left_ptr);
+      $orm->where("right_ptr", "<", $item->right_ptr);
+    }
+
+    if (isset($p->name)) {
+      $orm->where("name", "LIKE", "%" . Database::escape_for_like($p->name) . "%");
+    }
+
+    if (isset($p->type)) {
+      $orm->where("type", "IN", explode(",", $p->type));
+    }
+
+    // Apply the item's sort order, using id as the tie breaker.
+    // See Item_Model::children()
+    $order_by = array($item->sort_column => $item->sort_order);
+    if ($item->sort_column != "id") {
+      $order_by["id"] = "ASC";
+    }
+    $orm->order_by($order_by);
+
+    $result = array(
+      "url" => $request->url,
+      "entity" => $item->as_restful_array(),
+      "relationships" => rest::relationships("item", $item));
+    if ($item->is_album()) {
+      $result["members"] = array();
+      foreach ($orm->find_all() as $child) {
+        $result["members"][] = rest::url("item", $child);
+      }
+    }
+
+    return $result;
+  }
+
+  static function put($request) {
+    $item = rest::resolve($request->url);
+    access::required("edit", $item);
+
+    if ($entity = $request->params->entity) {
+      // Only change fields from a whitelist.
+      foreach (array("album_cover", "captured", "description",
+                     "height", "mime_type", "name", "parent", "rand_key", "resize_dirty",
+                     "resize_height", "resize_width", "slug", "sort_column", "sort_order",
+                     "thumb_dirty", "thumb_height", "thumb_width", "title", "view_count",
+                     "width") as $key) {
+        switch ($key) {
+        case "album_cover":
+          if (property_exists($entity, "album_cover")) {
+            $album_cover_item = rest::resolve($entity->album_cover);
+            access::required("view", $album_cover_item);
+            $item->album_cover_item_id = $album_cover_item->id;
+          }
+          break;
+
+        case "parent":
+          if (property_exists($entity, "parent")) {
+            $parent = rest::resolve($entity->parent);
+            access::required("edit", $parent);
+            $item->parent_id = $parent->id;
+          }
+          break;
+        default:
+          if (property_exists($entity, $key)) {
+            $item->$key = $entity->$key;
+          }
+        }
+      }
+    }
+
+    // Replace the data file, if required
+    if (($item->is_photo() || $item->is_movie()) && isset($request->file)) {
+      $item->set_data_file($request->file);
+    }
+
+    $item->save();
+
+    if (isset($request->params->members) && $item->sort_column == "weight") {
+      $weight = 0;
+      foreach ($request->params->members as $url) {
+        $child = rest::resolve($url);
+        if ($child->parent_id == $item->id && $child->weight != $weight) {
+          $child->weight = $weight;
+          $child->save();
+        }
+        $weight++;
+      }
+    }
+  }
+
+  static function post($request) {
+    $parent = rest::resolve($request->url);
+    access::required("add", $parent);
+
+    $entity = $request->params->entity;
+    $item = ORM::factory("item");
+    switch ($entity->type) {
+    case "album":
+      $item->type = "album";
+      $item->parent_id = $parent->id;
+      $item->name = $entity->name;
+      $item->title = isset($entity->title) ? $entity->title : $entity->name;
+      $item->description = isset($entity->description) ? $entity->description : null;
+      $item->slug = isset($entity->slug) ? $entity->slug : null;
+      $item->save();
+      break;
+
+    case "photo":
+    case "movie":
+      if (empty($request->file)) {
+        throw new Rest_Exception(
+          "Bad Request", 400, array("errors" => array("file" => t("Upload failed"))));
+      }
+    $item->type = $entity->type;
+    $item->parent_id = $parent->id;
+    $item->set_data_file($request->file);
+    $item->name = $entity->name;
+    $item->title = isset($entity->title) ? $entity->title : $entity->name;
+    $item->description = isset($entity->description) ? $entity->description : null;
+    $item->slug = isset($entity->slug) ? $entity->slug : null;
+    $item->save();
+    break;
+
+    default:
+      throw new Rest_Exception(
+        "Bad Request", 400, array("errors" => array("type" => "invalid")));
+    }
+
+    return array("url" => rest::url("item", $item));
+  }
+
+  static function delete($request) {
+    $item = rest::resolve($request->url);
+    access::required("edit", $item);
+
+    $item->delete();
+  }
+
+  static function resolve($id) {
+    $item = ORM::factory("item", $id);
+    if (!access::can("view", $item)) {
+      throw new Kohana_404_Exception();
+    }
+    return $item;
+  }
+
+  static function url($item) {
+    return url::abs_site("rest/item/{$item->id}");
+  }
+}
diff --git a/modules/gallery/helpers/items_rest.php b/modules/gallery/helpers/items_rest.php
new file mode 100644
index 0000000..7622c53
--- /dev/null
+++ b/modules/gallery/helpers/items_rest.php
@@ -0,0 +1,96 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class items_rest_Core {
+  /**
+   * To retrieve a collection of items, you can specify the following query parameters to specify
+   * the type of the collection.  If both are specified, then the url parameter is used and the
+   * ancestors_for is ignored.  Specifying the "type" parameter with the urls parameter, will
+   * filter the results based on the specified type.  Using the type parameter with the
+   * ancestors_for parameter makes no sense and will be ignored.
+   *
+   *   urls=["url1","url2","url3"]
+   *     Return items that match the specified urls.  Typically used to return the member detail
+   *
+   *   ancestors_for=url
+   *     Return the ancestors of the specified item
+   *
+   *   type=<comma separate list of photo, movie or album>
+   *     Limit the type to types in this list, eg: "type=photo,movie".
+   *     Also limits the types returned in the member collections (same behaviour as item_rest).
+   *     Ignored if ancestors_for is set.
+   */
+  static function get($request) {
+    $items = array();
+    $types = array();
+
+    if (isset($request->params->urls)) {
+      if (isset($request->params->type)) {
+        $types = explode(",", $request->params->type);
+      }
+
+      foreach (json_decode($request->params->urls) as $url) {
+        $item = rest::resolve($url);
+        if (!access::can("view", $item)) {
+          continue;
+        }
+
+        if (empty($types) || in_array($item->type, $types)) {
+          $items[] = items_rest::_format_restful_item($item, $types);
+        }
+      }
+    } else if (isset($request->params->ancestors_for)) {
+      $item = rest::resolve($request->params->ancestors_for);
+      if (!access::can("view", $item)) {
+        throw new Kohana_404_Exception();
+      }
+      $items[] = items_rest::_format_restful_item($item, $types);
+      while (($item = $item->parent()) != null) {
+        array_unshift($items, items_rest::_format_restful_item($item, $types));
+      };
+    }
+
+    return $items;
+  }
+
+  static function resolve($id) {
+    $item = ORM::factory("item", $id);
+    if (!access::can("view", $item)) {
+      throw new Kohana_404_Exception();
+    }
+    return $item;
+  }
+
+  private static function _format_restful_item($item, $types) {
+    $item_rest = array("url" => rest::url("item", $item),
+                       "entity" => $item->as_restful_array(),
+                       "relationships" => rest::relationships("item", $item));
+    if ($item->type == "album") {
+      $members = array();
+      foreach ($item->viewable()->children() as $child) {
+        if (empty($types) || in_array($child->type, $types)) {
+          $members[] = rest::url("item", $child);
+        }
+      }
+      $item_rest["members"] = $members;
+    }
+
+    return $item_rest;
+  }
+}
diff --git a/modules/gallery/helpers/json.php b/modules/gallery/helpers/json.php
new file mode 100644
index 0000000..b56f269
--- /dev/null
+++ b/modules/gallery/helpers/json.php
@@ -0,0 +1,31 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class json_Core {
+  /**
+   * JSON Encode a reply to the browser and set the content type to specify that it's a JSON
+   * payload.
+   *
+   * @param  mixed $message string or object to json encode and print
+   */
+  static function reply($message) {
+    header("Content-Type: application/json; charset=" . Kohana::CHARSET);
+    print json_encode($message);
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/l10n_client.php b/modules/gallery/helpers/l10n_client.php
new file mode 100644
index 0000000..2a1be2f
--- /dev/null
+++ b/modules/gallery/helpers/l10n_client.php
@@ -0,0 +1,323 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class l10n_client_Core {
+
+  private static function _server_url($path) {
+    return "http://galleryproject.org/translations/$path";
+  }
+
+  static function server_api_key_url() {
+    return self::_server_url("userkey/" . self::client_token());
+  }
+
+  static function client_token() {
+    return md5("l10n_client_client_token" . access::private_key());
+  }
+
+  static function api_key($api_key=null) {
+    if ($api_key !== null) {
+      module::set_var("gallery", "l10n_client_key", $api_key);
+    }
+    return module::get_var("gallery", "l10n_client_key", "");
+  }
+
+  static function server_uid($api_key=null) {
+    $api_key = $api_key == null ? l10n_client::api_key() : $api_key;
+    $parts = explode(":", $api_key);
+    return empty($parts) ? 0 : $parts[0];
+  }
+
+  private static function _sign($payload, $api_key=null) {
+    $api_key = $api_key == null ? l10n_client::api_key() : $api_key;
+    return md5($api_key . $payload . l10n_client::client_token());
+  }
+
+  static function validate_api_key($api_key) {
+    $version = "1.0";
+    $url = self::_server_url("status");
+    $signature = self::_sign($version, $api_key);
+
+    try {
+      list ($response_data, $response_status) = remote::post(
+        $url, array("version" => $version,
+                    "client_token" => l10n_client::client_token(),
+                    "signature" => $signature,
+                    "uid" => l10n_client::server_uid($api_key)));
+    } catch (ErrorException $e) {
+      // Log the error, but then return a "can't make connection" error
+      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+    }
+    if (!isset($response_data) && !isset($response_status)) {
+      return array(false, false);
+    }
+
+    if (!remote::success($response_status)) {
+      return array(true, false);
+    }
+    return array(true, true);
+  }
+
+  /**
+   * Fetches translations for l10n messages. Must be called repeatedly
+   * until 0 is returned (which is a countdown indicating progress).
+   *
+   * @param $num_fetched in/out parameter to specify which batch of
+   *     messages to fetch translations for.
+   * @return The number of messages for which we didn't fetch
+   *     translations for.
+   */
+  static function fetch_updates(&$num_fetched) {
+    $request = new stdClass();
+    $request->locales = array();
+    $request->messages = new stdClass();
+
+    $locales = locales::installed();
+    foreach ($locales as $locale => $locale_data) {
+      $request->locales[] = $locale;
+    }
+
+    // See the server side code for how we arrive at this
+    // number as a good limit for #locales * #messages.
+    $max_messages = 2000 / count($locales);
+    $num_messages = 0;
+    $rows = db::build()
+        ->select("key", "locale", "revision", "translation")
+        ->from("incoming_translations")
+        ->order_by("key")
+        ->limit(1000000)  // ignore, just there to satisfy SQL syntax
+        ->offset($num_fetched)
+        ->execute();
+    $num_remaining = $rows->count();
+    foreach ($rows as $row) {
+      if (!isset($request->messages->{$row->key})) {
+        if ($num_messages >= $max_messages) {
+          break;
+        }
+        $request->messages->{$row->key} = 1;
+        $num_messages++;
+      }
+      if (!empty($row->revision) && !empty($row->translation) &&
+          isset($locales[$row->locale])) {
+        if (!is_object($request->messages->{$row->key})) {
+          $request->messages->{$row->key} = new stdClass();
+        }
+        $request->messages->{$row->key}->{$row->locale} = (int) $row->revision;
+      }
+      $num_fetched++;
+      $num_remaining--;
+    }
+    // @todo Include messages from outgoing_translations?
+
+    if (!$num_messages) {
+      return $num_remaining;
+    }
+
+    $request_data = json_encode($request);
+    $url = self::_server_url("fetch");
+    list ($response_data, $response_status) = remote::post($url, array("data" => $request_data));
+    if (!remote::success($response_status)) {
+      throw new Exception("@todo TRANSLATIONS_FETCH_REQUEST_FAILED " . $response_status);
+    }
+    if (empty($response_data)) {
+      return $num_remaining;
+    }
+
+    $response = json_decode($response_data);
+
+    // Response format (JSON payload):
+    //   [{key:<key_1>, translation: <JSON encoded translation>, rev:<rev>, locale:<locale>},
+    //    {key:<key_2>, ...}
+    //   ]
+    foreach ($response as $message_data) {
+      // @todo Better input validation
+      if (empty($message_data->key) || empty($message_data->translation) ||
+          empty($message_data->locale) || empty($message_data->rev)) {
+        throw new Exception("@todo TRANSLATIONS_FETCH_REQUEST_FAILED: Invalid response data");
+      }
+      $key = $message_data->key;
+      $locale = $message_data->locale;
+      $revision = $message_data->rev;
+      $translation = json_decode($message_data->translation);
+      if (!is_string($translation)) {
+        // Normalize stdclass to array
+        $translation = (array) $translation;
+      }
+      $translation = serialize($translation);
+
+      // @todo Should we normalize the incoming_translations table into messages(id, key, message)
+      // and incoming_translations(id, translation, locale, revision)? Or just allow
+      // incoming_translations.message to be NULL?
+      $locale = $message_data->locale;
+      $entry = ORM::factory("incoming_translation")
+        ->where("key", "=", $key)
+        ->where("locale", "=", $locale)
+        ->find();
+      if (!$entry->loaded()) {
+        // @todo Load a message key -> message (text) dict into memory outside of this loop
+        $root_entry = ORM::factory("incoming_translation")
+          ->where("key", "=", $key)
+          ->where("locale", "=", "root")
+          ->find();
+        $entry->key = $key;
+        $entry->message = $root_entry->message;
+        $entry->locale = $locale;
+      }
+      $entry->revision = $revision;
+      $entry->translation = $translation;
+      $entry->save();
+    }
+
+    return $num_remaining;
+  }
+
+  static function submit_translations() {
+    // Request format (HTTP POST):
+    //   client_token = <client_token>
+    //   uid = <l10n server user id>
+    //   signature = md5(user_api_key($uid, $client_token) . $data . $client_token))
+    //   data = // JSON payload
+    //
+    //     {<key_1>: {message: <JSON encoded message>
+    //                translations: {<locale_1>: <JSON encoded translation>,
+    //                               <locale_2>: ...}},
+    //      <key_2>: {...}
+    //     }
+
+    // @todo Batch requests (max request size)
+    // @todo include base_revision in submission / how to handle resubmissions / edit fights?
+    $request = new stdClass();
+    foreach (db::build()
+             ->select("key", "message", "locale", "base_revision", "translation")
+             ->from("outgoing_translations")
+             ->execute() as $row) {
+      $key = $row->key;
+      if (!isset($request->{$key})) {
+        $request->{$key} = new stdClass();
+        $request->{$key}->translations = new stdClass();
+        $request->{$key}->message = json_encode(unserialize($row->message));
+      }
+      $request->{$key}->translations->{$row->locale} = json_encode(unserialize($row->translation));
+    }
+
+    // @todo reduce memory consumption, e.g. free $request
+    $request_data = json_encode($request);
+    $url = self::_server_url("submit");
+    $signature = self::_sign($request_data);
+
+    list ($response_data, $response_status) = remote::post(
+      $url, array("data" => $request_data,
+                  "client_token" => l10n_client::client_token(),
+                  "signature" => $signature,
+                  "uid" => l10n_client::server_uid()));
+
+    if (!remote::success($response_status)) {
+      throw new Exception("@todo TRANSLATIONS_SUBMISSION_FAILED " . $response_status);
+    }
+    if (empty($response_data)) {
+      return;
+    }
+
+    $response = json_decode($response_data);
+    // Response format (JSON payload):
+    //   [{key:<key_1>, locale:<locale_1>, rev:<rev_1>, status:<rejected|accepted|pending>},
+    //    {key:<key_2>, ...}
+    //   ]
+
+    // @todo Move messages out of outgoing into incoming, using new rev?
+    // @todo show which messages have been rejected / are pending?
+  }
+
+  /**
+   * Plural forms.
+   */
+  static function plural_forms($locale) {
+    $parts = explode('_', $locale);
+    $language = $parts[0];
+
+    // Data from CLDR 1.6 (http://unicode.org/cldr/data/common/supplemental/plurals.xml).
+    // Docs: http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html
+    switch ($language) {
+      case 'az':
+      case 'fa':
+      case 'hu':
+      case 'ja':
+      case 'ko':
+      case 'my':
+      case 'to':
+      case 'tr':
+      case 'vi':
+      case 'yo':
+      case 'zh':
+      case 'bo':
+      case 'dz':
+      case 'id':
+      case 'jv':
+      case 'ka':
+      case 'km':
+      case 'kn':
+      case 'ms':
+      case 'th':
+        return array('other');
+
+      case 'ar':
+        return array('zero', 'one', 'two', 'few', 'many', 'other');
+
+      case 'lv':
+        return array('zero', 'one', 'other');
+
+      case 'ga':
+      case 'se':
+      case 'sma':
+      case 'smi':
+      case 'smj':
+      case 'smn':
+      case 'sms':
+        return array('one', 'two', 'other');
+
+      case 'ro':
+      case 'mo':
+      case 'lt':
+      case 'cs':
+      case 'sk':
+      case 'pl':
+        return array('one', 'few', 'other');
+
+      case 'hr':
+      case 'ru':
+      case 'sr':
+      case 'uk':
+      case 'be':
+      case 'bs':
+      case 'sh':
+      case 'mt':
+        return array('one', 'few', 'many', 'other');
+
+      case 'sl':
+        return array('one', 'two', 'few', 'other');
+
+      case 'cy':
+        return array('one', 'two', 'many', 'other');
+
+      default: // en, de, etc.
+        return array('one', 'other');
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/l10n_scanner.php b/modules/gallery/helpers/l10n_scanner.php
new file mode 100644
index 0000000..5980ebe
--- /dev/null
+++ b/modules/gallery/helpers/l10n_scanner.php
@@ -0,0 +1,178 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * Scans all source code for messages that need to be localized.
+ */
+class l10n_scanner_Core {
+  // Based on Drupal's potx module, originally written by:
+  // Gbor Hojtsy http://drupal.org/user/4166
+  public static $cache;
+
+  static function process_message($message, &$cache) {
+    if (empty($cache)) {
+      foreach (db::build()
+               ->select("key")
+               ->from("incoming_translations")
+               ->where("locale", "=", "root")
+               ->execute() as $row) {
+        $cache[$row->key] = true;
+      }
+    }
+
+    $key = Gallery_I18n::get_message_key($message);
+    if (array_key_exists($key, $cache)) {
+      return $cache[$key];
+    }
+
+    $entry = ORM::factory("incoming_translation")->where("key", "=", $key)->find();
+    if (!$entry->loaded()) {
+      $entry->key = $key;
+      $entry->message = serialize($message);
+      $entry->locale = "root";
+      $entry->save();
+    }
+  }
+
+  static function scan_php_file($file, &$cache) {
+    $code = file_get_contents($file);
+    $raw_tokens = token_get_all($code);
+    unset($code);
+
+    $tokens = array();
+    $func_token_list = array("t" => array(), "t2" => array());
+    $token_number = 0;
+    // Filter out HTML / whitespace, and build a lookup for global function calls.
+    foreach ($raw_tokens as $token) {
+      if ((!is_array($token)) || (($token[0] != T_WHITESPACE) && ($token[0] != T_INLINE_HTML))) {
+        if (is_array($token)) {
+          if ($token[0] == T_STRING && in_array($token[1], array("t", "t2"))) {
+            $func_token_list[$token[1]][] = $token_number;
+          }
+        }
+        $tokens[] = $token;
+        $token_number++;
+      }
+    }
+    unset($raw_tokens);
+
+    if (!empty($func_token_list["t"])) {
+      $errors = l10n_scanner::_parse_t_calls($tokens, $func_token_list["t"], $cache);
+      foreach ($errors as $line => $error) {
+        Kohana_Log::add(
+          "error", "Translation scanner error.  " .
+          "file: " . substr($file, strlen(DOCROOT)) . ", line: $line, context: $error");
+      }
+    }
+
+    if (!empty($func_token_list["t2"])) {
+      $errors = l10n_scanner::_parse_plural_calls($tokens, $func_token_list["t2"], $cache);
+      foreach ($errors as $line => $error) {
+        Kohana_Log::add(
+          "error", "Translation scanner error.  " .
+          "file: " . substr($file, strlen(DOCROOT)) . ", line: $line, context: $error");
+      }
+    }
+  }
+
+  static function scan_info_file($file, &$cache) {
+    $info = new ArrayObject(parse_ini_file($file), ArrayObject::ARRAY_AS_PROPS);
+    foreach (array('name', 'description') as $property) {
+      if (isset($info->$property)) {
+        l10n_scanner::process_message($info->$property, $cache);
+      }
+    }
+  }
+
+  private static function _parse_t_calls(&$tokens, &$call_list, &$cache) {
+    $errors = array();
+    foreach ($call_list as $index) {
+      $function_name = $tokens[$index++];
+      $parens = $tokens[$index++];
+      $first_param = $tokens[$index++];
+      $next_token = $tokens[$index];
+
+      if ($parens == "(") {
+        if (in_array($next_token, array(")", ","))
+            && (is_array($first_param) && ($first_param[0] == T_CONSTANT_ENCAPSED_STRING))) {
+          $message = self::_escape_quoted_string($first_param[1]);
+          l10n_scanner::process_message($message, $cache);
+        } else {
+          if (is_array($first_param) && ($first_param[0] == T_CONSTANT_ENCAPSED_STRING)) {
+            // Malformed string literals; escalate this
+            $errors[$first_param[2]] =
+              var_export(array($function_name, $parens, $first_param, $next_token), 1);
+          } else {
+            // t() found, but inside is something which is not a string literal.  That's fine.
+          }
+        }
+      }
+    }
+    return $errors;
+  }
+
+  private static function _parse_plural_calls(&$tokens, &$call_list, &$cache) {
+    $errors = array();
+    foreach ($call_list as $index) {
+      $function_name = $tokens[$index++];
+      $parens = $tokens[$index++];
+      $first_param = $tokens[$index++];
+      $first_separator = $tokens[$index++];
+      $second_param = $tokens[$index++];
+      $next_token = $tokens[$index];
+
+      if ($parens == "(") {
+        if ($first_separator == "," && $next_token == ","
+            && is_array($first_param) && $first_param[0] == T_CONSTANT_ENCAPSED_STRING
+            && is_array($second_param) && $second_param[0] == T_CONSTANT_ENCAPSED_STRING) {
+          $singular = self::_escape_quoted_string($first_param[1]);
+          $plural = self::_escape_quoted_string($second_param[1]);
+          l10n_scanner::process_message(array("one" => $singular, "other" => $plural), $cache);
+        } else {
+          if (is_array($first_param) && $first_param[0] == T_CONSTANT_ENCAPSED_STRING) {
+            $errors[$first_param[2]] = var_export(
+              array($function_name, $parens, $first_param,
+                    $first_separator, $second_param, $next_token), 1);
+          } else {
+            // t2() found, but inside is something which is not a string literal.  That's fine.
+          }
+        }
+      }
+    }
+    return $errors;
+  }
+
+  /**
+   * Escape quotes in a strings depending on the surrounding
+   * quote type used.
+   *
+   * @param $str The strings to escape
+   */
+  private static function _escape_quoted_string($str) {
+    $quo = substr($str, 0, 1);
+    $str = substr($str, 1, -1);
+    if ($quo == '"') {
+      $str = stripcslashes($str);
+    } else {
+      $str = strtr($str, array("\\'" => "'", "\\\\" => "\\"));
+    }
+    return $str;
+  }
+}
diff --git a/modules/gallery/helpers/legal_file.php b/modules/gallery/helpers/legal_file.php
new file mode 100644
index 0000000..eb9c25d
--- /dev/null
+++ b/modules/gallery/helpers/legal_file.php
@@ -0,0 +1,310 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class legal_file_Core {
+  private static $photo_types_by_extension;
+  private static $movie_types_by_extension;
+  private static $photo_extensions;
+  private static $movie_extensions;
+  private static $photo_types;
+  private static $movie_types;
+  private static $blacklist = array("php", "php3", "php4", "php5", "phtml", "phtm", "shtml", "shtm",
+                                    "pl", "cgi", "asp", "sh", "py", "c", "js");
+
+  /**
+   * Create a default list of allowed photo MIME types paired with their extensions and then let
+   * modules modify it.  This is an ordered map, mapping extensions to their MIME types.
+   * Extensions cannot be duplicated, but MIMEs can (e.g. jpeg and jpg both map to image/jpeg).
+   *
+   * @param string $extension (opt.) - return MIME of extension; if not given, return complete array
+   */
+  static function get_photo_types_by_extension($extension=null) {
+    if (empty(self::$photo_types_by_extension)) {
+      $types_by_extension_wrapper = new stdClass();
+      $types_by_extension_wrapper->types_by_extension = array(
+        "jpg" => "image/jpeg", "jpeg" => "image/jpeg", "gif" => "image/gif", "png" => "image/png");
+      module::event("photo_types_by_extension", $types_by_extension_wrapper);
+      foreach (self::$blacklist as $key) {
+        unset($types_by_extension_wrapper->types_by_extension[$key]);
+      }
+      self::$photo_types_by_extension = $types_by_extension_wrapper->types_by_extension;
+    }
+    if ($extension) {
+      // return matching MIME type
+      $extension = strtolower($extension);
+      if (isset(self::$photo_types_by_extension[$extension])) {
+        return self::$photo_types_by_extension[$extension];
+      } else {
+        return null;
+      }
+    } else {
+      // return complete array
+      return self::$photo_types_by_extension;
+    }
+  }
+
+  /**
+   * Create a default list of allowed movie MIME types paired with their extensions and then let
+   * modules modify it.  This is an ordered map, mapping extensions to their MIME types.
+   * Extensions cannot be duplicated, but MIMEs can (e.g. jpeg and jpg both map to image/jpeg).
+   *
+   * @param string $extension (opt.) - return MIME of extension; if not given, return complete array
+   */
+  static function get_movie_types_by_extension($extension=null) {
+    if (empty(self::$movie_types_by_extension)) {
+      $types_by_extension_wrapper = new stdClass();
+      $types_by_extension_wrapper->types_by_extension = array(
+        "flv" => "video/x-flv", "mp4" => "video/mp4", "m4v" => "video/x-m4v");
+      module::event("movie_types_by_extension", $types_by_extension_wrapper);
+      foreach (self::$blacklist as $key) {
+        unset($types_by_extension_wrapper->types_by_extension[$key]);
+      }
+      self::$movie_types_by_extension = $types_by_extension_wrapper->types_by_extension;
+    }
+    if ($extension) {
+      // return matching MIME type
+      $extension = strtolower($extension);
+      if (isset(self::$movie_types_by_extension[$extension])) {
+        return self::$movie_types_by_extension[$extension];
+      } else {
+        return null;
+      }
+    } else {
+      // return complete array
+      return self::$movie_types_by_extension;
+    }
+  }
+
+  /**
+   * Create a merged list of all allowed photo and movie MIME types paired with their extensions.
+   *
+   * @param string $extension (opt.) - return MIME of extension; if not given, return complete array
+   */
+  static function get_types_by_extension($extension=null) {
+    $types_by_extension = legal_file::get_photo_types_by_extension();
+    if (movie::allow_uploads()) {
+      $types_by_extension = array_merge($types_by_extension,
+                                        legal_file::get_movie_types_by_extension());
+    }
+    if ($extension) {
+      // return matching MIME type
+      $extension = strtolower($extension);
+      if (isset($types_by_extension[$extension])) {
+        return $types_by_extension[$extension];
+      } else {
+        return null;
+      }
+    } else {
+      // return complete array
+      return $types_by_extension;
+    }
+  }
+
+  /**
+   * Create a default list of allowed photo extensions and then let modules modify it.
+   *
+   * @param string $extension (opt.) - return true if allowed; if not given, return complete array
+   */
+  static function get_photo_extensions($extension=null) {
+    if (empty(self::$photo_extensions)) {
+      $extensions_wrapper = new stdClass();
+      $extensions_wrapper->extensions = array_keys(legal_file::get_photo_types_by_extension());
+      module::event("legal_photo_extensions", $extensions_wrapper);
+      self::$photo_extensions = array_diff($extensions_wrapper->extensions, self::$blacklist);
+    }
+    if ($extension) {
+      // return true if in array, false if not
+      return in_array(strtolower($extension), self::$photo_extensions);
+    } else {
+      // return complete array
+      return self::$photo_extensions;
+    }
+  }
+
+  /**
+   * Create a default list of allowed movie extensions and then let modules modify it.
+   *
+   * @param string $extension (opt.) - return true if allowed; if not given, return complete array
+   */
+  static function get_movie_extensions($extension=null) {
+    if (empty(self::$movie_extensions)) {
+      $extensions_wrapper = new stdClass();
+      $extensions_wrapper->extensions = array_keys(legal_file::get_movie_types_by_extension());
+      module::event("legal_movie_extensions", $extensions_wrapper);
+      self::$movie_extensions = array_diff($extensions_wrapper->extensions, self::$blacklist);
+    }
+    if ($extension) {
+      // return true if in array, false if not
+      return in_array(strtolower($extension), self::$movie_extensions);
+    } else {
+      // return complete array
+      return self::$movie_extensions;
+    }
+  }
+
+  /**
+   * Create a merged list of all allowed photo and movie extensions.
+   *
+   * @param string $extension (opt.) - return true if allowed; if not given, return complete array
+   */
+  static function get_extensions($extension=null) {
+    $extensions = legal_file::get_photo_extensions();
+    if (movie::allow_uploads()) {
+      $extensions = array_merge($extensions, legal_file::get_movie_extensions());
+    }
+    if ($extension) {
+      // return true if in array, false if not
+      return in_array(strtolower($extension), $extensions);
+    } else {
+      // return complete array
+      return $extensions;
+    }
+  }
+
+  /**
+   * Create a merged list of all photo and movie filename filters,
+   * (e.g. "*.gif"), based on allowed extensions.
+   */
+  static function get_filters() {
+    $filters = array();
+    foreach (legal_file::get_extensions() as $extension) {
+      array_push($filters, "*." . $extension, "*." . strtoupper($extension));
+    }
+    return $filters;
+  }
+
+  /**
+   * Create a default list of allowed photo MIME types and then let modules modify it.
+   * Can be used to add legal alternatives for default MIME types.
+   * (e.g. flv maps to video/x-flv by default, but video/flv is still legal).
+   */
+  static function get_photo_types() {
+    if (empty(self::$photo_types)) {
+      $types_wrapper = new stdClass();
+      // Need array_unique since types_by_extension can be many-to-one (e.g. jpeg and jpg).
+      $types_wrapper->types = array_unique(array_values(legal_file::get_photo_types_by_extension()));
+      module::event("legal_photo_types", $types_wrapper);
+      self::$photo_types = $types_wrapper->types;
+    }
+    return self::$photo_types;
+  }
+
+  /**
+   * Create a default list of allowed movie MIME types and then let modules modify it.
+   * Can be used to add legal alternatives for default MIME types.
+   * (e.g. flv maps to video/x-flv by default, but video/flv is still legal).
+   */
+  static function get_movie_types() {
+    if (empty(self::$movie_types)) {
+      $types_wrapper = new stdClass();
+      // Need array_unique since types_by_extension can be many-to-one (e.g. jpeg and jpg).
+      $types_wrapper->types = array_unique(array_values(legal_file::get_movie_types_by_extension()));
+      $types_wrapper->types[] = "video/flv";
+      module::event("legal_movie_types", $types_wrapper);
+      self::$movie_types = $types_wrapper->types;
+    }
+    return self::$movie_types;
+  }
+
+  /**
+   * Change the extension of a filename.  If the original filename has no
+   * extension, add the new one to the end.
+   */
+  static function change_extension($filename, $new_ext) {
+    $filename_no_ext = preg_replace("/\.[^\.\/]*?$/", "", $filename);
+    return "{$filename_no_ext}.{$new_ext}";
+  }
+
+  /**
+   * Reduce the given file to having a single extension.
+   */
+  static function smash_extensions($filename) {
+    if (!$filename) {
+      // It's harmless, so return it before it causes issues with pathinfo.
+      return $filename;
+    }
+    $parts = pathinfo($filename);
+    $result = "";
+    if ($parts["dirname"] != ".") {
+      $result .= $parts["dirname"] . "/";
+    }
+    $parts["filename"] = str_replace(".", "_", $parts["filename"]);
+    $parts["filename"] = preg_replace("/[_]+/", "_", $parts["filename"]);
+    $parts["filename"] = trim($parts["filename"], "_");
+    $result .= isset($parts["extension"]) ? "{$parts['filename']}.{$parts['extension']}" : $parts["filename"];
+    return $result;
+  }
+
+  /**
+   * Sanitize a filename for a given type (given as "photo" or "movie") and a target file format
+   * (given as an extension).  This returns a completely legal and valid filename,
+   * or throws an exception if the type or extension given is invalid or illegal.  It tries to
+   * maintain the filename's original extension even if it's not identical to the given extension
+   * (e.g. don't change "JPG" or "jpeg" to "jpg").
+   *
+   * Note: it is not okay if the extension given is legal but does not match the type (e.g. if
+   * extension is "mp4" and type is "photo", it will throw an exception)
+   *
+   * @param  string $filename  (with no directory)
+   * @param  string $extension (can be uppercase or lowercase)
+   * @param  string $type      (as "photo" or "movie")
+   * @return string sanitized filename (or null if bad extension argument)
+   */
+  static function sanitize_filename($filename, $extension, $type) {
+    // Check if the type is valid - if so, get the mime types of the
+    // original and target extensions; if not, throw an exception.
+    $original_extension = pathinfo($filename, PATHINFO_EXTENSION);
+    switch ($type) {
+      case "photo":
+        $mime_type = legal_file::get_photo_types_by_extension($extension);
+        $original_mime_type = legal_file::get_photo_types_by_extension($original_extension);
+        break;
+      case "movie":
+        $mime_type = legal_file::get_movie_types_by_extension($extension);
+        $original_mime_type = legal_file::get_movie_types_by_extension($original_extension);
+        break;
+      default:
+        throw new Exception("@todo INVALID_TYPE");
+    }
+
+    // Check if the target extension is blank or invalid - if so, throw an exception.
+    if (!$extension || !$mime_type) {
+      throw new Exception("@todo ILLEGAL_EXTENSION");
+    }
+
+    // Check if the mime types of the original and target extensions match - if not, fix it.
+    if (!$original_extension || ($mime_type != $original_mime_type)) {
+      $filename = legal_file::change_extension($filename, $extension);
+    }
+
+    // It should be a filename without a directory - remove all slashes (and backslashes).
+    $filename = str_replace("/", "_", $filename);
+    $filename = str_replace("\\", "_", $filename);
+
+    // Remove extra dots from the filename.  This will also remove extraneous underscores.
+    $filename = legal_file::smash_extensions($filename);
+
+    // It's possible that the filename has no base (e.g. ".jpg") - if so, give it a generic one.
+    if (empty($filename) || (substr($filename, 0, 1) == ".")) {
+      $filename = $type . $filename;  // e.g. "photo.jpg" or "movie.mp4"
+    }
+
+    return $filename;
+  }
+}
diff --git a/modules/gallery/helpers/locales.php b/modules/gallery/helpers/locales.php
new file mode 100644
index 0000000..8ca25c3
--- /dev/null
+++ b/modules/gallery/helpers/locales.php
@@ -0,0 +1,264 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling locales.
+ */
+class locales_Core {
+  private static $locales;
+  private static $language_subtag_to_locale;
+
+  /**
+   * Return the list of available locales.
+   */
+  static function available() {
+    if (empty(self::$locales)) {
+      self::_init_language_data();
+    }
+
+    return self::$locales;
+  }
+
+  static function installed() {
+    $available = self::available();
+    $default = module::get_var("gallery", "default_locale");
+    $codes = explode("|", module::get_var("gallery", "installed_locales", $default));
+    foreach ($codes as $code) {
+      if (isset($available[$code])) {
+        $installed[$code] = $available[$code];
+      }
+    }
+    return $installed;
+  }
+
+  static function update_installed($locales) {
+    // Ensure that the default is included...
+    $default = module::get_var("gallery", "default_locale");
+    $locales = in_array($default, $locales)
+      ? $locales
+      : array_merge($locales, array($default));
+
+    module::set_var("gallery", "installed_locales", join("|", $locales));
+
+    // Clear the cache
+    self::$locales = null;
+  }
+
+  // @todo Might want to add a localizable language name as well.
+  // ref: http://cldr.unicode.org/
+  // ref: http://cldr.unicode.org/index/cldr-spec/picking-the-right-language-code
+  // ref: http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/likely_subtags.html
+  private static function _init_language_data() {
+    $l["af_ZA"] = "Afrikaans";                // Afrikaans
+    $l["ar_SA"] = "العربية";                   // Arabic
+    $l["be_BY"] = "Беларускі";           // Belarusian
+    $l["bg_BG"] = "български";           // Bulgarian
+    $l["bn_BD"] = "বাংলা";               // Bengali
+    $l["ca_ES"] = "Catalan";                  // Catalan
+    $l["cs_CZ"] = "čeština";                  // Czech
+    $l["da_DK"] = "Dansk";                    // Danish
+    $l["de_DE"] = "Deutsch";                  // German
+    $l["el_GR"] = "Greek";                    // Greek
+    $l["en_GB"] = "English (UK)";             // English (UK)
+    $l["en_US"] = "English (US)";             // English (US)
+    $l["es_AR"] = "Español (AR)";             // Spanish (AR)
+    $l["es_ES"] = "Español";                  // Spanish (ES)
+    $l["es_MX"] = "Español (MX)";             // Spanish (MX)
+    $l["et_EE"] = "Eesti";                    // Estonian
+    $l["eu_ES"] = "Euskara";                  // Basque
+    $l["fa_IR"] = "فارس";                     // Farsi
+    $l["fi_FI"] = "Suomi";                    // Finnish
+    $l["fo_FO"] = "Føroyskt";                    // Faroese
+    $l["fr_FR"] = "Français";                 // French
+    $l["ga_IE"] = "Gaeilge";                  // Irish
+    $l["he_IL"] = "עברית";                    // Hebrew
+    $l["hr_HR"] = "hr̀vātskī";                 // Croatian
+    $l["hu_HU"] = "Magyar";                   // Hungarian
+    $l["is_IS"] = "Icelandic";                // Icelandic
+    $l["it_IT"] = "Italiano";                 // Italian
+    $l["ja_JP"] = "日本語";                    // Japanese
+    $l["ko_KR"] = "한국어";                    // Korean
+    $l["lt_LT"] = "Lietuvių";                 // Lithuanian
+    $l["lv_LV"] = "Latviešu";                 // Latvian
+    $l["ms_MY"] = "Bahasa Melayu";            // Malay
+    $l["mk_MK"] = "Македонски јазик";         // Macedonian
+    $l["nl_NL"] = "Nederlands";               // Dutch
+    $l["no_NO"] = "Norsk bokmål";             // Norwegian
+    $l["pl_PL"] = "Polski";                   // Polish
+    $l["pt_BR"] = "Português do Brasil";      // Portuguese (BR)
+    $l["pt_PT"] = "Português ibérico";        // Portuguese (PT)
+    $l["ro_RO"] = "Română";                   // Romanian
+    $l["ru_RU"] = "Русский";              // Russian
+    $l["sk_SK"] = "Slovenčina";               // Slovak
+    $l["sl_SI"] = "Slovenščina";              // Slovenian
+    $l["sr_CS"] = "Srpski";                   // Serbian
+    $l["sv_SE"] = "Svenska";                  // Swedish
+    $l["th_TH"] = "ภาษาไทย";                     // Thai
+    $l["tn_ZA"] = "Setswana";                 // Setswana
+    $l["tr_TR"] = "Türkçe";                   // Turkish
+    $l["uk_UA"] = "українська";         // Ukrainian
+    $l["vi_VN"] = "Tiếng Việt";               // Vietnamese
+    $l["zh_CN"] = "简体中文";                  // Chinese (CN)
+    $l["zh_TW"] = "繁體中文";                  // Chinese (TW)
+    asort($l, SORT_LOCALE_STRING);
+    self::$locales = $l;
+
+    // Language subtag to (default) locale mapping
+    foreach ($l as $locale => $name) {
+      list ($language) = explode("_", $locale . "_");
+      // The first one mentioned is the default
+      if (!isset($d[$language])) {
+        $d[$language] = $locale;
+      }
+    }
+    self::$language_subtag_to_locale = $d;
+  }
+
+  static function display_name($locale=null) {
+    if (empty(self::$locales)) {
+      self::_init_language_data();
+    }
+    $locale or $locale = Gallery_I18n::instance()->locale();
+
+    return self::$locales[$locale];
+  }
+
+  static function is_rtl($locale=null) {
+    return Gallery_I18n::instance()->is_rtl($locale);
+  }
+
+  /**
+   * Returns the best match comparing the HTTP accept-language header
+   * with the installed locales.
+   * @todo replace this with request::accepts_language() when we upgrade to Kohana 2.4
+   */
+  static function locale_from_http_request() {
+    $http_accept_language = Input::instance()->server("HTTP_ACCEPT_LANGUAGE");
+    if ($http_accept_language) {
+      // Parse the HTTP header and build a preference list
+      // Example value: "de,en-us;q=0.7,en-uk,fr-fr;q=0.2"
+      $locale_preferences = array();
+      foreach (explode(",", $http_accept_language) as $code) {
+        list ($requested_locale, $qvalue) = explode(";", $code . ";");
+        $requested_locale = trim($requested_locale);
+        $qvalue = trim($qvalue);
+        if (preg_match("/^([a-z]{2,3})(?:[_-]([a-zA-Z]{2}))?/", $requested_locale, $matches)) {
+          $requested_locale = strtolower($matches[1]);
+          if (!empty($matches[2])) {
+            $requested_locale .= "_" . strtoupper($matches[2]);
+          }
+          $requested_locale = trim(str_replace("-", "_", $requested_locale));
+          if (!strlen($qvalue)) {
+            // If not specified, default to 1.
+            $qvalue = 1;
+          } else {
+            // qvalue is expected to be something like "q=0.7"
+            list ($ignored, $qvalue) = explode("=", $qvalue . "==");
+            $qvalue = floatval($qvalue);
+          }
+          // Group by language to boost inexact same-language matches
+          list ($language) = explode("_", $requested_locale . "_");
+          if (!isset($locale_preferences[$language])) {
+            $locale_preferences[$language] = array();
+          }
+          $locale_preferences[$language][$requested_locale] = $qvalue;
+        }
+      }
+
+      // Compare and score requested locales with installed ones
+      $scored_locales = array();
+      foreach ($locale_preferences as $language => $requested_locales) {
+        // Inexact match adjustment (same language, different region)
+        $fallback_adjustment_factor = 0.95;
+        if (count($requested_locales) > 1) {
+          // Sort by qvalue, descending
+          $qvalues = array_values($requested_locales);
+          rsort($qvalues);
+          // Ensure inexact match scores worse than 2nd preference in same language.
+          $fallback_adjustment_factor *= $qvalues[1];
+        }
+        foreach ($requested_locales as $requested_locale => $qvalue) {
+          list ($matched_locale, $match_score) =
+              self::_locale_match_score($requested_locale, $qvalue, $fallback_adjustment_factor);
+          if ($matched_locale &&
+              (!isset($scored_locales[$matched_locale]) ||
+               $match_score > $scored_locales[$matched_locale])) {
+            $scored_locales[$matched_locale] = $match_score;
+          }
+        }
+      }
+
+      arsort($scored_locales);
+
+      list ($locale) = each($scored_locales);
+      return $locale;
+    }
+
+    return null;
+  }
+
+  private static function _locale_match_score($requested_locale, $qvalue, $adjustment_factor) {
+    $installed = locales::installed();
+    if (isset($installed[$requested_locale])) {
+      return array($requested_locale, $qvalue);
+    }
+    list ($language) = explode("_", $requested_locale . "_");
+    if (isset(self::$language_subtag_to_locale[$language]) &&
+        isset($installed[self::$language_subtag_to_locale[$language]])) {
+      $score = $adjustment_factor * $qvalue;
+      return array(self::$language_subtag_to_locale[$language], $score);
+    }
+    return array(null, 0);
+  }
+
+  static function set_request_locale() {
+    // 1. Check the session specific preference (cookie)
+    $locale = locales::cookie_locale();
+    // 2. Check the user's preference
+    if (!$locale) {
+      $locale = identity::active_user()->locale;
+    }
+    // 3. Check the browser's / OS' preference
+    if (!$locale) {
+      $locale = locales::locale_from_http_request();
+    }
+    // If we have any preference, override the site's default locale
+    if ($locale) {
+      Gallery_I18n::instance()->locale($locale);
+    }
+  }
+
+  static function cookie_locale() {
+    // Can't use Input framework for client side cookies since
+    // they're not signed.
+    $cookie_data = isset($_COOKIE["g_locale"]) ? $_COOKIE["g_locale"] : null;
+    $locale = null;
+    if ($cookie_data) {
+      if (preg_match("/^([a-z]{2,3}(?:_[A-Z]{2})?)$/", trim($cookie_data), $matches)) {
+        $requested_locale = $matches[1];
+        $installed_locales = locales::installed();
+        if (isset($installed_locales[$requested_locale])) {
+          $locale = $requested_locale;
+        }
+      }
+    }
+    return $locale;
+  }
+}
diff --git a/modules/gallery/helpers/log.php b/modules/gallery/helpers/log.php
new file mode 100644
index 0000000..cd554b5
--- /dev/null
+++ b/modules/gallery/helpers/log.php
@@ -0,0 +1,108 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class log_Core {
+  const SUCCESS = 1;
+  const INFO    = 2;
+  const WARNING = 3;
+  const ERROR   = 4;
+
+  /**
+   * Report a successful event.
+   * @param string  $category  an arbitrary category we can use to filter log messages
+   * @param string  $message   a detailed log message
+   * @param string  $html      an html snippet presented alongside the log message to aid the admin
+   */
+  static function success($category, $message, $html="") {
+    self::_add($category, $message, $html, log::SUCCESS);
+  }
+
+  /**
+   * Report an informational event.
+   * @param string  $category  an arbitrary category we can use to filter log messages
+   * @param string  $message   a detailed log message
+   * @param string  $html      an html snippet presented alongside the log message to aid the admin
+   */
+  static function info($category, $message, $html="") {
+    self::_add($category, $message, $html, log::INFO);
+  }
+
+  /**
+   * Report that something went wrong, not fatal, but worth investigation.
+   * @param string  $category  an arbitrary category we can use to filter log messages
+   * @param string  $message   a detailed log message
+   * @param string  $html      an html snippet presented alongside the log message to aid the admin
+   */
+  static function warning($category, $message, $html="") {
+    self::_add($category, $message, $html, log::WARNING);
+  }
+
+  /**
+   * Report that something went wrong that should be fixed.
+   * @param string  $category  an arbitrary category we can use to filter log messages
+   * @param string  $message   a detailed log message
+   * @param string  $html      an html snippet presented alongside the log message to aid the admin
+   */
+  static function error($category, $message, $html="") {
+    self::_add($category, $message, $html, log::ERROR);
+  }
+
+  /**
+   * Add a log entry.
+   *
+   * @param string  $category  an arbitrary category we can use to filter log messages
+   * @param string  $message   a detailed log message
+   * @param integer $severity  INFO, WARNING or ERROR
+   * @param string  $html      an html snippet presented alongside the log message to aid the admin
+   */
+  private static function _add($category, $message, $html, $severity) {
+    $log = ORM::factory("log");
+    $log->category = $category;
+    $log->message = $message;
+    $log->severity = $severity;
+    $log->html = $html;
+    $log->url = substr(url::abs_current(true), 0, 255);
+    $log->referer = request::referrer(null);
+    $log->timestamp = time();
+    $log->user_id = identity::active_user()->id;
+    $log->save();
+  }
+
+
+  /**
+   * Convert a message severity to a CSS class
+   * @param  integer $severity
+   * @return string
+   */
+  static function severity_class($severity) {
+    switch($severity) {
+    case log::SUCCESS:
+      return "g-success";
+
+    case log::INFO:
+      return "g-info";
+
+    case log::WARNING:
+      return "g-warning";
+
+    case log::ERROR:
+      return "g-error";
+    }
+  }
+}
diff --git a/modules/gallery/helpers/message.php b/modules/gallery/helpers/message.php
new file mode 100644
index 0000000..d109995
--- /dev/null
+++ b/modules/gallery/helpers/message.php
@@ -0,0 +1,109 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class message_Core {
+  const SUCCESS = 1;
+  const INFO    = 2;
+  const WARNING = 3;
+  const ERROR   = 4;
+
+  /**
+   * Report a successful event.
+   * @param string  $msg           a detailed message
+   */
+  static function success($msg) {
+    self::_add($msg, message::SUCCESS);
+  }
+
+  /**
+   * Report an informational event.
+   * @param string  $msg           a detailed message
+   */
+  static function info($msg) {
+    self::_add($msg, message::INFO);
+  }
+
+  /**
+   * Report that something went wrong, not fatal, but worth investigation.
+   * @param string  $msg           a detailed message
+   */
+  static function warning($msg) {
+    self::_add($msg, message::WARNING);
+  }
+
+  /**
+   * Report that something went wrong that should be fixed.
+   * @param string  $msg           a detailed message
+   */
+  static function error($msg) {
+    self::_add($msg, message::ERROR);
+  }
+
+  /**
+   * Save a message in the session for our next page load.
+   * @param string  $msg           a detailed message
+   * @param integer $severity      one of the severity constants
+   */
+  private static function _add($msg, $severity) {
+    $session = Session::instance();
+    $status = $session->get("messages");
+    $status[] = array($msg, $severity);
+    $session->set("messages", $status);
+  }
+
+  /**
+   * Get any pending messages.  There are two types of messages, transient and permanent.
+   * Permanent messages are used to let the admin know that there are pending administrative
+   * issues that need to be resolved.  Transient ones are only displayed once.
+   * @return html text
+   */
+  static function get() {
+    $buf = array();
+
+    $messages = Session::instance()->get_once("messages", array());
+    foreach ($messages as $msg) {
+      $msg[0] = str_replace("__CSRF__", access::csrf_token(), $msg[0]);
+      $buf[] = "<li class=\"" . message::severity_class($msg[1]) . "\">$msg[0]</li>";
+    }
+    if ($buf) {
+      return "<ul id=\"g-action-status\" class=\"g-message-block\">" . implode("", $buf) . "</ul>";
+    }
+  }
+
+  /**
+   * Convert a message severity to a CSS class
+   * @param  integer $severity
+   * @return string
+   */
+  static function severity_class($severity) {
+    switch($severity) {
+    case message::SUCCESS:
+      return "g-success";
+
+    case message::INFO:
+      return "g-info";
+
+    case message::WARNING:
+      return "g-warning";
+
+    case message::ERROR:
+      return "g-error";
+    }
+  }
+}
diff --git a/modules/gallery/helpers/model_cache.php b/modules/gallery/helpers/model_cache.php
new file mode 100644
index 0000000..7cff68d
--- /dev/null
+++ b/modules/gallery/helpers/model_cache.php
@@ -0,0 +1,42 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class model_cache_Core {
+  private static $cache = array();
+
+  static function get($model_name, $id, $field_name="id") {
+    if (TEST_MODE || empty(self::$cache[$model_name][$field_name][$id])) {
+      $model = ORM::factory($model_name)->where($field_name, "=", $id)->find();
+      if (!$model->loaded()) {
+        throw new Exception("@todo MISSING_MODEL $model_name:$id");
+      }
+      self::$cache[$model_name][$field_name][$id] = $model;
+    }
+
+    return self::$cache[$model_name][$field_name][$id];
+  }
+
+  static function clear() {
+    self::$cache = array();
+  }
+
+  static function set($model) {
+    self::$cache[$model->object_name][$model->primary_key][$model->{$model->primary_key}] = $model;
+  }
+}
diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php
new file mode 100644
index 0000000..1b6c8d1
--- /dev/null
+++ b/modules/gallery/helpers/module.php
@@ -0,0 +1,594 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling modules.
+ *
+ * Note: by design, this class does not do any permission checking.
+ */
+class module_Core {
+  public static $active = array();
+  public static $modules = array();
+  public static $var_cache = null;
+  public static $available = array();
+
+  /**
+   * Set the version of the corresponding Module_Model
+   * @param string  $module_name
+   * @param integer $version
+   */
+  static function set_version($module_name, $version) {
+    $module = module::get($module_name);
+    if (!$module->loaded()) {
+      $module->name = $module_name;
+      $module->active = $module_name == "gallery";  // only gallery is active by default
+    }
+    $module->version = $version;
+    $module->save();
+    Kohana_Log::add("debug", "$module_name: version is now $version");
+  }
+
+  /**
+   * Load the corresponding Module_Model
+   * @param string $module_name
+   */
+  static function get($module_name) {
+    if (empty(self::$modules[$module_name])) {
+      return ORM::factory("module")->where("name", "=", $module_name)->find();
+    }
+    return self::$modules[$module_name];
+  }
+
+  /**
+   * Get the information about a module
+   * @returns ArrayObject containing the module information from the module.info file or false if
+   *                      not found
+   */
+  static function info($module_name) {
+    $module_list = module::available();
+    return isset($module_list->$module_name) ? $module_list->$module_name : false;
+  }
+
+  /**
+   * Check to see if a module is installed
+   * @param string $module_name
+   */
+  static function is_installed($module_name) {
+    return array_key_exists($module_name, self::$modules);
+  }
+
+  /**
+   * Check to see if a module is active
+   * @param string $module_name
+   */
+  static function is_active($module_name) {
+    return array_key_exists($module_name, self::$modules) &&
+      self::$modules[$module_name]->active;
+  }
+
+  /**
+   * Return the list of available modules, including uninstalled modules.
+   */
+  static function available() {
+    if (empty(self::$available)) {
+      $modules = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS);
+      foreach (glob(MODPATH . "*/module.info") as $file) {
+        $module_name = basename(dirname($file));
+        $modules->$module_name =
+          new ArrayObject(parse_ini_file($file), ArrayObject::ARRAY_AS_PROPS);
+        $m =& $modules->$module_name;
+        $m->installed = module::is_installed($module_name);
+        $m->active = module::is_active($module_name);
+        $m->code_version = $m->version;
+        $m->version = module::get_version($module_name);
+        $m->locked = false;
+
+        if ($m->active && $m->version != $m->code_version) {
+          site_status::warning(t("Some of your modules are out of date.  <a href=\"%upgrader_url\">Upgrade now!</a>", array("upgrader_url" => url::abs_site("upgrader"))), "upgrade_now");
+        }
+      }
+
+      // Lock certain modules
+      $modules->gallery->locked = true;
+      $identity_module = module::get_var("gallery", "identity_provider", "user");
+      $modules->$identity_module->locked = true;
+
+      $modules->uasort(array("module", "module_comparator"));
+      self::$available = $modules;
+    }
+
+    return self::$available;
+  }
+
+  /**
+   * Natural name sort comparator
+   */
+  static function module_comparator($a, $b) {
+    return strnatcasecmp($a->name, $b->name);
+  }
+
+  /**
+   * Return a list of all the active modules in no particular order.
+   */
+  static function active() {
+    return self::$active;
+  }
+
+  /**
+   * Check that the module can be activated. (i.e. all the prerequistes exist)
+   * @param string $module_name
+   * @return array an array of warning or error messages to be displayed
+   */
+  static function can_activate($module_name) {
+    module::_add_to_path($module_name);
+    $messages = array();
+
+    $installer_class = "{$module_name}_installer";
+    if (class_exists($installer_class) && method_exists($installer_class, "can_activate")) {
+      $messages = call_user_func(array($installer_class, "can_activate"));
+    }
+
+    // Remove it from the active path
+    module::_remove_from_path($module_name);
+    return $messages;
+  }
+
+  /**
+   * Allow modules to indicate the impact of deactivating the specified module
+   * @param string $module_name
+   * @return array an array of warning or error messages to be displayed
+   */
+  static function can_deactivate($module_name) {
+    $data = (object)array("module" => $module_name, "messages" => array());
+
+    module::event("pre_deactivate", $data);
+
+    return $data->messages;
+  }
+
+  /**
+   * Install a module.  This will call <module>_installer::install(), which is responsible for
+   * creating database tables, setting module variables and calling module::set_version().
+   * Note that after installing, the module must be activated before it is available for use.
+   * @param string $module_name
+   */
+  static function install($module_name) {
+    module::_add_to_path($module_name);
+
+    $installer_class = "{$module_name}_installer";
+    if (class_exists($installer_class) && method_exists($installer_class, "install")) {
+      call_user_func_array(array($installer_class, "install"), array());
+    }
+    module::set_version($module_name, module::available()->$module_name->code_version);
+
+    // Set the weight of the new module, which controls the order in which the modules are
+    // loaded. By default, new modules are installed at the end of the priority list.  Since the
+    // id field is monotonically increasing, the easiest way to guarantee that is to set the weight
+    // the same as the id.  We don't know that until we save it for the first time
+    $module = ORM::factory("module")->where("name", "=", $module_name)->find();
+    if ($module->loaded()) {
+      $module->weight = $module->id;
+      $module->save();
+    }
+    module::load_modules();
+
+    // Now the module is installed but inactive, so don't leave it in the active path
+    module::_remove_from_path($module_name);
+
+    log::success(
+      "module", t("Installed module %module_name", array("module_name" => $module_name)));
+  }
+
+  private static function _add_to_path($module_name) {
+    $config = Kohana_Config::instance();
+    $kohana_modules = $config->get("core.modules");
+    array_unshift($kohana_modules, MODPATH . $module_name);
+    $config->set("core.modules",  $kohana_modules);
+    // Rebuild the include path so the module installer can benefit from auto loading
+    Kohana::include_paths(true);
+  }
+
+  private static function _remove_from_path($module_name) {
+    $config = Kohana_Config::instance();
+    $kohana_modules = $config->get("core.modules");
+    if (($key = array_search(MODPATH . $module_name, $kohana_modules)) !== false) {
+      unset($kohana_modules[$key]);
+      $kohana_modules = array_values($kohana_modules); // reindex
+    }
+    $config->set("core.modules",  $kohana_modules);
+    Kohana::include_paths(true);
+  }
+
+  /**
+   * Upgrade a module.  This will call <module>_installer::upgrade(), which is responsible for
+   * modifying database tables, changing module variables and calling module::set_version().
+   * Note that after upgrading, the module must be activated before it is available for use.
+   * @param string $module_name
+   */
+  static function upgrade($module_name) {
+    $version_before = module::get_version($module_name);
+    $installer_class = "{$module_name}_installer";
+    $available = module::available();
+    if (class_exists($installer_class) && method_exists($installer_class, "upgrade")) {
+      call_user_func_array(array($installer_class, "upgrade"), array($version_before));
+    } else {
+      if (isset($available->$module_name->code_version)) {
+        module::set_version($module_name, $available->$module_name->code_version);
+      } else {
+        throw new Exception("@todo UNKNOWN_MODULE");
+      }
+    }
+    module::load_modules();
+
+    $version_after = module::get_version($module_name);
+    if ($version_before != $version_after) {
+      log::success(
+        "module", t("Upgraded module %module_name from %version_before to %version_after",
+                    array("module_name" => $module_name,
+                          "version_before" => $version_before,
+                          "version_after" => $version_after)));
+    }
+
+    if ($version_after != $available->$module_name->code_version) {
+      throw new Exception("@todo MODULE_FAILED_TO_UPGRADE");
+    }
+  }
+
+  /**
+   * Activate an installed module.  This will call <module>_installer::activate() which should take
+   * any steps to make sure that the module is ready for use.  This will also activate any
+   * existing graphics rules for this module.
+   * @param string $module_name
+   */
+  static function activate($module_name) {
+    module::_add_to_path($module_name);
+
+    $installer_class = "{$module_name}_installer";
+    if (class_exists($installer_class) && method_exists($installer_class, "activate")) {
+      call_user_func_array(array($installer_class, "activate"), array());
+    }
+
+    $module = module::get($module_name);
+    if ($module->loaded()) {
+      $module->active = true;
+      $module->save();
+    }
+    module::load_modules();
+
+    graphics::activate_rules($module_name);
+
+    block_manager::activate_blocks($module_name);
+
+    log::success(
+      "module", t("Activated module %module_name", array("module_name" => $module_name)));
+  }
+
+  /**
+   * Deactivate an installed module.  This will call <module>_installer::deactivate() which should
+   * take any cleanup steps to make sure that the module isn't visible in any way.  Note that the
+   * module remains available in Kohana's cascading file system until the end of the request!
+   * @param string $module_name
+   */
+  static function deactivate($module_name) {
+    $installer_class = "{$module_name}_installer";
+    if (class_exists($installer_class) && method_exists($installer_class, "deactivate")) {
+      call_user_func_array(array($installer_class, "deactivate"), array());
+    }
+
+    $module = module::get($module_name);
+    if ($module->loaded()) {
+      $module->active = false;
+      $module->save();
+    }
+    module::load_modules();
+
+    graphics::deactivate_rules($module_name);
+
+    block_manager::deactivate_blocks($module_name);
+
+    if (module::info($module_name)) {
+      log::success(
+        "module", t("Deactivated module %module_name", array("module_name" => $module_name)));
+    } else {
+      log::success(
+        "module", t("Deactivated missing module %module_name", array("module_name" => $module_name)));
+    }
+  }
+
+  /**
+   * Deactivate modules that are unavailable or missing, yet still active.
+   * This happens when a user deletes a module without deactivating it.
+   */
+  static function deactivate_missing_modules() {
+    foreach (self::$modules as $module_name => $module) {
+      if (module::is_active($module_name) && !module::info($module_name)) {
+        module::deactivate($module_name);
+      }
+    }
+  }
+
+  /**
+   * Uninstall a deactivated module.  This will call <module>_installer::uninstall() which should
+   * take whatever steps necessary to make sure that all traces of a module are gone.
+   * @param string $module_name
+   */
+  static function uninstall($module_name) {
+    $installer_class = "{$module_name}_installer";
+    if (class_exists($installer_class) && method_exists($installer_class, "uninstall")) {
+      call_user_func(array($installer_class, "uninstall"));
+    }
+
+    graphics::remove_rules($module_name);
+    $module = module::get($module_name);
+    if ($module->loaded()) {
+      $module->delete();
+    }
+    module::load_modules();
+
+    // We could delete the module vars here too, but it's nice to leave them around
+    // in case the module gets reinstalled.
+
+    log::success(
+      "module", t("Uninstalled module %module_name", array("module_name" => $module_name)));
+  }
+
+  /**
+   * Load the active modules.  This is called at bootstrap time.
+   */
+  static function load_modules() {
+    self::$modules = array();
+    self::$active = array();
+    $kohana_modules = array();
+
+    // In version 32 we introduced a weight column so we can specify the module order
+    // If we try to use that blindly, we'll break earlier versions before they can even
+    // run the upgrader.
+    $modules = module::get_version("gallery") < 32 ?
+      ORM::factory("module")->find_all():
+      ORM::factory("module")->order_by("weight")->find_all();
+
+    foreach ($modules as $module) {
+      self::$modules[$module->name] = $module;
+      if (!$module->active) {
+        continue;
+      }
+
+      if ($module->name == "gallery") {
+        $gallery = $module;
+      } else {
+        self::$active[] = $module;
+        $kohana_modules[] = MODPATH . $module->name;
+      }
+    }
+    self::$active[] = $gallery;  // put gallery last in the module list to match core.modules
+    $config = Kohana_Config::instance();
+    $config->set(
+      "core.modules", array_merge($kohana_modules, $config->get("core.modules")));
+  }
+
+  /**
+   * Run a specific event on all active modules.
+   * @param string $name the event name
+   * @param mixed  $data data to pass to each event handler
+   */
+  static function event($name, &$data=null) {
+    $args = func_get_args();
+    array_shift($args);
+    $function = str_replace(".", "_", $name);
+
+    if (method_exists("gallery_event", $function)) {
+      switch (count($args)) {
+      case 0:
+        gallery_event::$function();
+        break;
+      case 1:
+        gallery_event::$function($args[0]);
+        break;
+      case 2:
+        gallery_event::$function($args[0], $args[1]);
+        break;
+      case 3:
+        gallery_event::$function($args[0], $args[1], $args[2]);
+        break;
+      case 4:      // Context menu events have 4 arguments so lets optimize them
+        gallery_event::$function($args[0], $args[1], $args[2], $args[3]);
+        break;
+      default:
+        call_user_func_array(array("gallery_event", $function), $args);
+      }
+    }
+
+    foreach (self::$active as $module) {
+      if ($module->name == "gallery") {
+        continue;
+      }
+      $class = "{$module->name}_event";
+      if (class_exists($class) && method_exists($class, $function)) {
+        call_user_func_array(array($class, $function), $args);
+      }
+    }
+
+    // Give the admin theme a chance to respond, if we're in admin mode.
+    if (theme::$is_admin) {
+      $class = theme::$admin_theme_name . "_event";
+      if (class_exists($class) && method_exists($class, $function)) {
+        call_user_func_array(array($class, $function), $args);
+      }
+    }
+
+    // Give the site theme a chance to respond as well.  It gets a chance even in admin mode, as
+    // long as the theme has an admin subdir.
+    $class = theme::$site_theme_name . "_event";
+    if (class_exists($class) && method_exists($class, $function)) {
+      call_user_func_array(array($class, $function), $args);
+    }
+  }
+
+  /**
+   * Get a variable from this module
+   * @param string $module_name
+   * @param string $name
+   * @param string $default_value
+   * @return the value
+   */
+  static function get_var($module_name, $name, $default_value=null) {
+    // We cache vars so we can load them all at once for performance.
+    if (empty(self::$var_cache)) {
+      self::$var_cache = Cache::instance()->get("var_cache");
+      if (empty(self::$var_cache)) {
+        // Cache doesn't exist, create it now.
+        foreach (db::build()
+                 ->select("module_name", "name", "value")
+                 ->from("vars")
+                 ->order_by("module_name")
+                 ->order_by("name")
+                 ->execute() as $row) {
+          // Mute the "Creating default object from empty value" warning below
+          @self::$var_cache->{$row->module_name}->{$row->name} = $row->value;
+        }
+        Cache::instance()->set("var_cache", self::$var_cache, array("vars"));
+      }
+    }
+
+    if (isset(self::$var_cache->$module_name->$name)) {
+      return self::$var_cache->$module_name->$name;
+    } else {
+      return $default_value;
+    }
+  }
+
+  /**
+   * Store a variable for this module
+   * @param string $module_name
+   * @param string $name
+   * @param string $value
+   */
+  static function set_var($module_name, $name, $value) {
+    $var = ORM::factory("var")
+      ->where("module_name", "=", $module_name)
+      ->where("name", "=", $name)
+      ->find();
+    if (!$var->loaded()) {
+      $var->module_name = $module_name;
+      $var->name = $name;
+    }
+    $var->value = $value;
+    $var->save();
+
+    Cache::instance()->delete("var_cache");
+    self::$var_cache = null;
+ }
+
+  /**
+   * Increment the value of a variable for this module
+   *
+   * Note: Frequently updating counters is very inefficient because it invalidates the cache value
+   * which has to be rebuilt every time we make a change.
+   *
+   * @todo Get rid of this and find an alternate approach for all callers (currently only Akismet)
+   *
+   * @deprecated
+   * @param string $module_name
+   * @param string $name
+   * @param string $increment (optional, default is 1)
+   */
+  static function incr_var($module_name, $name, $increment=1) {
+    db::build()
+      ->update("vars")
+      ->set("value", db::expr("`value` + $increment"))
+      ->where("module_name", "=", $module_name)
+      ->where("name", "=", $name)
+      ->execute();
+
+    Cache::instance()->delete("var_cache");
+    self::$var_cache = null;
+  }
+
+ /**
+   * Remove a variable for this module.
+   * @param string $module_name
+   * @param string $name
+   */
+  static function clear_var($module_name, $name) {
+    db::build()
+      ->delete("vars")
+      ->where("module_name", "=", $module_name)
+      ->where("name", "=", $name)
+      ->execute();
+
+    Cache::instance()->delete("var_cache");
+    self::$var_cache = null;
+  }
+
+ /**
+   * Remove all variables for this module.
+   * @param string $module_name
+   */
+  static function clear_all_vars($module_name) {
+    db::build()
+      ->delete("vars")
+      ->where("module_name", "=", $module_name)
+      ->execute();
+
+    Cache::instance()->delete("var_cache");
+    self::$var_cache = null;
+  }
+
+  /**
+   * Return the version of the installed module.
+   * @param string $module_name
+   */
+  static function get_version($module_name) {
+    return module::get($module_name)->version;
+  }
+
+  /**
+   * Check if obsolete modules are active and, if so, return a warning message.
+   * If none are found, return null.
+   */
+  static function get_obsolete_modules_message() {
+    // This is the obsolete modules list.  Any active module that's on the list
+    // with version number at or below the one given will be considered obsolete.
+    // It is hard-coded here, and may be updated with future releases of Gallery.
+    $obsolete_modules = array("videos" => 4, "noffmpeg" => 1, "videodimensions" => 1,
+                              "digibug" => 2);
+
+    // Before we check the active modules, deactivate any that are missing.
+    module::deactivate_missing_modules();
+
+    $modules_found = array();
+    foreach ($obsolete_modules as $module => $version) {
+      if (module::is_active($module) && (module::get_version($module) <= $version)) {
+        $modules_found[] = $module;
+      }
+    }
+
+    if ($modules_found) {
+      // Need this to be on one super-long line or else the localization scanner may not work.
+      // (ref: http://sourceforge.net/apps/trac/gallery/ticket/1321)
+      return t("Recent upgrades to Gallery have made the following modules obsolete: %modules. We recommend that you <a href=\"%url_mod\">deactivate</a> the module(s). For more information, please see the <a href=\"%url_doc\">documentation page</a>.",
+               array("modules" => implode(", ", $modules_found),
+                     "url_mod" => url::site("admin/modules"),
+                     "url_doc" => "http://codex.galleryproject.org/Gallery3:User_guide:Obsolete_modules"));
+    }
+
+    return null;
+  }
+}
diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php
new file mode 100644
index 0000000..2f19088
--- /dev/null
+++ b/modules/gallery/helpers/movie.php
@@ -0,0 +1,282 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling movies.
+ *
+ * Note: by design, this class does not do any permission checking.
+ */
+class movie_Core {
+  private static $allow_uploads;
+
+  static function get_edit_form($movie) {
+    $form = new Forge("movies/update/$movie->id", "", "post", array("id" => "g-edit-movie-form"));
+    $form->hidden("from_id")->value($movie->id);
+    $group = $form->group("edit_item")->label(t("Edit Movie"));
+    $group->input("title")->label(t("Title"))->value($movie->title)
+      ->error_messages("required", t("You must provide a title"))
+      ->error_messages("length", t("Your title is too long"));
+    $group->textarea("description")->label(t("Description"))->value($movie->description);
+    $group->input("name")->label(t("Filename"))->value($movie->name)
+      ->error_messages(
+        "conflict", t("There is already a movie, photo or album with this name"))
+      ->error_messages("no_slashes", t("The movie name can't contain a \"/\""))
+      ->error_messages("no_trailing_period", t("The movie name can't end in \".\""))
+      ->error_messages("illegal_data_file_extension", t("You cannot change the movie file extension"))
+      ->error_messages("required", t("You must provide a movie file name"))
+      ->error_messages("length", t("Your movie file name is too long"));
+    $group->input("slug")->label(t("Internet Address"))->value($movie->slug)
+      ->error_messages(
+        "conflict", t("There is already a movie, photo or album with this internet address"))
+      ->error_messages(
+        "not_url_safe",
+        t("The internet address should contain only letters, numbers, hyphens and underscores"))
+      ->error_messages("required", t("You must provide an internet address"))
+      ->error_messages("length", t("Your internet address is too long"));
+
+    module::event("item_edit_form", $movie, $form);
+
+    $group = $form->group("buttons")->label("");
+    $group->submit("")->value(t("Modify"));
+
+    return $form;
+  }
+
+  /**
+   * Extract a frame from a movie file.  Valid movie_options are start_time (in seconds),
+   * input_args (extra ffmpeg input args) and output_args (extra ffmpeg output args).  Extra args
+   * are added at the end of the list, so they can override any prior args.
+   *
+   * @param string     $input_file
+   * @param string     $output_file
+   * @param array      $movie_options (optional)
+   */
+  static function extract_frame($input_file, $output_file, $movie_options=null) {
+    $ffmpeg = movie::find_ffmpeg();
+    if (empty($ffmpeg)) {
+      throw new Exception("@todo MISSING_FFMPEG");
+    }
+
+    list($width, $height, $mime_type, $extension, $duration) = movie::get_file_metadata($input_file);
+
+    if (isset($movie_options["start_time"]) && is_numeric($movie_options["start_time"])) {
+      $start_time = max(0, $movie_options["start_time"]); // ensure it's non-negative
+    } else {
+      $start_time = module::get_var("gallery", "movie_extract_frame_time", 3); // use default
+    }
+    // extract frame at start_time, unless movie is too short
+    $start_time_arg = ($duration >= $start_time + 0.1) ?
+      "-ss " . movie::seconds_to_hhmmssdd($start_time) : "";
+
+    $input_args = isset($movie_options["input_args"]) ? $movie_options["input_args"] : "";
+    $output_args = isset($movie_options["output_args"]) ? $movie_options["output_args"] : "";
+
+    $cmd = escapeshellcmd($ffmpeg) . " $input_args -i " . escapeshellarg($input_file) .
+      " -an $start_time_arg -an -r 1 -vframes 1" .
+      " -s {$width}x{$height}" .
+      " -y -f mjpeg $output_args " . escapeshellarg($output_file) . " 2>&1";
+    exec($cmd, $exec_output, $exec_return);
+
+    clearstatcache();  // use $filename parameter when PHP_version is 5.3+
+    if (filesize($output_file) == 0 || $exec_return) {
+      // Maybe the movie needs the "-threads 1" argument added
+      // (see http://sourceforge.net/apps/trac/gallery/ticket/1924)
+      $cmd = escapeshellcmd($ffmpeg) . " -threads 1 $input_args -i " . escapeshellarg($input_file) .
+        " -an $start_time_arg -an -r 1 -vframes 1" .
+        " -s {$width}x{$height}" .
+        " -y -f mjpeg $output_args " . escapeshellarg($output_file) . " 2>&1";
+      exec($cmd, $exec_output, $exec_return);
+
+      clearstatcache();
+      if (filesize($output_file) == 0 || $exec_return) {
+        throw new Exception("@todo FFMPEG_FAILED");
+      }
+    }
+  }
+
+  /**
+   * Return true if movie uploads are allowed, false if not.  This is based on the
+   * "movie_allow_uploads" Gallery variable as well as whether or not ffmpeg is found.
+   */
+  static function allow_uploads() {
+    if (empty(self::$allow_uploads)) {
+      // Refresh ffmpeg settings
+      $ffmpeg = movie::find_ffmpeg();
+      switch (module::get_var("gallery", "movie_allow_uploads", "autodetect")) {
+        case "always":
+          self::$allow_uploads = true;
+          break;
+        case "never":
+          self::$allow_uploads = false;
+          break;
+        default:
+          self::$allow_uploads = !empty($ffmpeg);
+          break;
+      }
+    }
+    return self::$allow_uploads;
+  }
+
+  /**
+   * Return the path to the ffmpeg binary if one exists and is executable, or null.
+   */
+  static function find_ffmpeg() {
+    if (!($ffmpeg_path = module::get_var("gallery", "ffmpeg_path")) ||
+        !@is_executable($ffmpeg_path)) {
+      $ffmpeg_path = system::find_binary(
+        "ffmpeg", module::get_var("gallery", "graphics_toolkit_path"));
+      module::set_var("gallery", "ffmpeg_path", $ffmpeg_path);
+    }
+    return $ffmpeg_path;
+  }
+
+  /**
+   * Return version number and build date of ffmpeg if found, empty string(s) if not.  When using
+   * static builds that aren't official releases, the version numbers are strange, hence why the
+   * date can be useful.
+   */
+  static function get_ffmpeg_version() {
+    $ffmpeg = movie::find_ffmpeg();
+    if (empty($ffmpeg)) {
+      return array("", "");
+    }
+
+    // Find version using -h argument since -version wasn't available in early versions.
+    // To keep the preg_match searches quick, we'll trim the (otherwise long) result.
+    $cmd = escapeshellcmd($ffmpeg) . " -h 2>&1";
+    $result = substr(`$cmd`, 0, 1000);
+    if (preg_match("/ffmpeg version (\S+)/i", $result, $matches_version)) {
+      // Version number found - see if we can get the build date or copyright year as well.
+      if (preg_match("/built on (\S+\s\S+\s\S+)/i", $result, $matches_build_date)) {
+        return array(trim($matches_version[1], ","), trim($matches_build_date[1], ","));
+      } else if (preg_match("/copyright \S*\s?2000-(\d{4})/i", $result, $matches_copyright_date)) {
+        return array(trim($matches_version[1], ","), $matches_copyright_date[1]);
+      } else {
+        return array(trim($matches_version[1], ","), "");
+      }
+    }
+    return array("", "");
+  }
+
+  /**
+   * Return the width, height, mime_type, extension and duration of the given movie file.
+   * Metadata is first generated using ffmpeg (or set to defaults if it fails),
+   * then can be modified by other modules using movie_get_file_metadata events.
+   *
+   * This function and its use cases are symmetric to those of photo::get_file_metadata.
+   *
+   * @param  string $file_path
+   * @return array  array($width, $height, $mime_type, $extension, $duration)
+   *
+   * Use cases in detail:
+   *   Input is standard movie type (flv/mp4/m4v)
+   *     -> return metadata from ffmpeg
+   *   Input is *not* standard movie type that is supported by ffmpeg (e.g. avi, mts...)
+   *     -> return metadata from ffmpeg
+   *   Input is *not* standard movie type that is *not* supported by ffmpeg but is legal
+   *     -> return zero width, height, and duration; mime type and extension according to legal_file
+   *   Input is illegal, unidentifiable, unreadable, or does not exist
+   *     -> throw exception
+   * Note: movie_get_file_metadata events can change any of the above cases (except the last one).
+   */
+  static function get_file_metadata($file_path) {
+    if (!is_readable($file_path)) {
+      throw new Exception("@todo UNREADABLE_FILE");
+    }
+
+    $metadata = new stdClass();
+    $ffmpeg = movie::find_ffmpeg();
+    if (!empty($ffmpeg)) {
+      // ffmpeg found - use it to get width, height, and duration.
+      $cmd = escapeshellcmd($ffmpeg) . " -i " . escapeshellarg($file_path) . " 2>&1";
+      $result = `$cmd`;
+      if (preg_match("/Stream.*?Video:.*?, (\d+)x(\d+)/", $result, $matches_res)) {
+        if (preg_match("/Stream.*?Video:.*? \[.*?DAR (\d+):(\d+).*?\]/", $result, $matches_dar) &&
+            $matches_dar[1] >= 1 && $matches_dar[2] >= 1) {
+          // DAR is defined - determine width based on height and DAR
+          // (should always be int, but adding round to be sure)
+          $matches_res[1] = round($matches_res[2] * $matches_dar[1] / $matches_dar[2]);
+        }
+        list ($metadata->width, $metadata->height) = array($matches_res[1], $matches_res[2]);
+      } else {
+        list ($metadata->width, $metadata->height) = array(0, 0);
+      }
+
+      if (preg_match("/Duration: (\d+:\d+:\d+\.\d+)/", $result, $matches)) {
+        $metadata->duration = movie::hhmmssdd_to_seconds($matches[1]);
+      } else if (preg_match("/duration.*?:.*?(\d+)/", $result, $matches)) {
+        $metadata->duration = $matches[1];
+      } else {
+        $metadata->duration = 0;
+      }
+    } else {
+      // ffmpeg not found - set width, height, and duration to zero.
+      $metadata->width = 0;
+      $metadata->height = 0;
+      $metadata->duration = 0;
+    }
+
+    $extension = pathinfo($file_path, PATHINFO_EXTENSION);
+    if (!$extension ||
+        (!$metadata->mime_type = legal_file::get_movie_types_by_extension($extension))) {
+        // Extension is empty or illegal.
+        $metadata->extension = null;
+        $metadata->mime_type = null;
+    } else {
+      // Extension is legal (and mime is already set above).
+      $metadata->extension = strtolower($extension);
+    }
+
+    // Run movie_get_file_metadata events which can modify the class.
+    module::event("movie_get_file_metadata", $file_path, $metadata);
+
+    // If the post-events results are invalid, throw an exception.  Note that, unlike photos, having
+    // zero width and height isn't considered invalid (as is the case when FFmpeg isn't installed).
+    if (!$metadata->mime_type || !$metadata->extension ||
+        ($metadata->mime_type != legal_file::get_movie_types_by_extension($metadata->extension))) {
+      throw new Exception("@todo ILLEGAL_OR_UNINDENTIFIABLE_FILE");
+    }
+
+    return array($metadata->width, $metadata->height, $metadata->mime_type,
+                 $metadata->extension, $metadata->duration);
+  }
+
+  /**
+   * Return the time/duration formatted in hh:mm:ss.dd from a number of seconds.
+   * Useful for inputs to ffmpeg.
+   *
+   * Note that this is similar to date("H:i:s", mktime(0,0,$seconds,0,0,0,0)), but unlike this
+   * approach avoids potential issues with time zone and DST mismatch and/or using deprecated
+   * features (the last argument of mkdate above, which disables DST, is deprecated as of PHP 5.3).
+   */
+  static function seconds_to_hhmmssdd($seconds) {
+    return sprintf("%02d:%02d:%05.2f", floor($seconds / 3600), floor(($seconds % 3600) / 60),
+                   floor(100 * $seconds % 6000) / 100);
+  }
+
+  /**
+   * Return the number of seconds from a time/duration formatted in hh:mm:ss.dd.
+   * Useful for outputs from ffmpeg.
+   */
+  static function hhmmssdd_to_seconds($hhmmssdd) {
+    preg_match("/(\d+):(\d+):(\d+\.\d+)/", $hhmmssdd, $matches);
+    return 3600 * $matches[1] + 60 * $matches[2] + $matches[3];
+  }
+}
diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php
new file mode 100644
index 0000000..004cc7c
--- /dev/null
+++ b/modules/gallery/helpers/photo.php
@@ -0,0 +1,145 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling photos.
+ *
+ * Note: by design, this class does not do any permission checking.
+ */
+class photo_Core {
+  static function get_edit_form($photo) {
+    $form = new Forge("photos/update/$photo->id", "", "post", array("id" => "g-edit-photo-form"));
+    $form->hidden("from_id")->value($photo->id);
+    $group = $form->group("edit_item")->label(t("Edit Photo"));
+    $group->input("title")->label(t("Title"))->value($photo->title)
+      ->error_messages("required", t("You must provide a title"))
+      ->error_messages("length", t("Your title is too long"));
+    $group->textarea("description")->label(t("Description"))->value($photo->description);
+    $group->input("name")->label(t("Filename"))->value($photo->name)
+      ->error_messages("conflict", t("There is already a movie, photo or album with this name"))
+      ->error_messages("no_slashes", t("The photo name can't contain a \"/\""))
+      ->error_messages("no_trailing_period", t("The photo name can't end in \".\""))
+      ->error_messages("illegal_data_file_extension", t("You cannot change the photo file extension"))
+      ->error_messages("required", t("You must provide a photo file name"))
+      ->error_messages("length", t("Your photo file name is too long"));
+    $group->input("slug")->label(t("Internet Address"))->value($photo->slug)
+      ->error_messages(
+        "conflict", t("There is already a movie, photo or album with this internet address"))
+      ->error_messages(
+        "not_url_safe",
+        t("The internet address should contain only letters, numbers, hyphens and underscores"))
+      ->error_messages("required", t("You must provide an internet address"))
+      ->error_messages("length", t("Your internet address is too long"));
+
+    module::event("item_edit_form", $photo, $form);
+
+    $group = $form->group("buttons")->label("");
+    $group->submit("")->value(t("Modify"));
+    return $form;
+  }
+
+  /**
+   * Return scaled width and height.
+   *
+   * @param integer $width
+   * @param integer $height
+   * @param integer $max    the target size for the largest dimension
+   * @param string  $format the output format using %d placeholders for width and height
+   */
+  static function img_dimensions($width, $height, $max, $format="width=\"%d\" height=\"%d\"") {
+    if (!$width || !$height) {
+      return "";
+    }
+
+    if ($width > $height) {
+      $new_width = $max;
+      $new_height = (int)$max * ($height / $width);
+    } else {
+      $new_height = $max;
+      $new_width = (int)$max * ($width / $height);
+    }
+    return sprintf($format, $new_width, $new_height);
+  }
+
+  /**
+   * Return the width, height, mime_type and extension of the given image file.
+   * Metadata is first generated using getimagesize (or the legal_file mapping if it fails),
+   * then can be modified by other modules using photo_get_file_metadata events.
+   *
+   * This function and its use cases are symmetric to those of photo::get_file_metadata.
+   *
+   * @param  string $file_path
+   * @return array  array($width, $height, $mime_type, $extension)
+   *
+   * Use cases in detail:
+   *   Input is standard photo type (jpg/png/gif)
+   *     -> return metadata from getimagesize()
+   *   Input is *not* standard photo type that is supported by getimagesize (e.g. tif, bmp...)
+   *     -> return metadata from getimagesize()
+   *   Input is *not* standard photo type that is *not* supported by getimagesize but is legal
+   *     -> return metadata if found by photo_get_file_metadata events
+   *   Input is illegal, unidentifiable, unreadable, or does not exist
+   *     -> throw exception
+   * Note: photo_get_file_metadata events can change any of the above cases (except the last one).
+   */
+  static function get_file_metadata($file_path) {
+    if (!is_readable($file_path)) {
+      throw new Exception("@todo UNREADABLE_FILE");
+    }
+
+    $metadata = new stdClass();
+    if ($image_info = getimagesize($file_path)) {
+      // getimagesize worked - use its results.
+      $metadata->width = $image_info[0];
+      $metadata->height = $image_info[1];
+      $metadata->mime_type = $image_info["mime"];
+      $metadata->extension = image_type_to_extension($image_info[2], false);
+      // We prefer jpg instead of jpeg (which is returned by image_type_to_extension).
+      if ($metadata->extension == "jpeg") {
+        $metadata->extension = "jpg";
+      }
+    } else {
+      // getimagesize failed - try to use legal_file mapping instead.
+      $extension = pathinfo($file_path, PATHINFO_EXTENSION);
+      if (!$extension ||
+          (!$metadata->mime_type = legal_file::get_photo_types_by_extension($extension))) {
+        // Extension is empty or illegal.
+        $metadata->extension = null;
+        $metadata->mime_type = null;
+      } else {
+        // Extension is legal (and mime is already set above).
+        $metadata->extension = strtolower($extension);
+      }
+      $metadata->width = 0;
+      $metadata->height = 0;
+    }
+
+    // Run photo_get_file_metadata events which can modify the class.
+    module::event("photo_get_file_metadata", $file_path, $metadata);
+
+    // If the post-events results are invalid, throw an exception.
+    if (!$metadata->width || !$metadata->height || !$metadata->mime_type || !$metadata->extension ||
+        ($metadata->mime_type != legal_file::get_photo_types_by_extension($metadata->extension))) {
+      throw new Exception("@todo ILLEGAL_OR_UNINDENTIFIABLE_FILE");
+    }
+
+    return array($metadata->width, $metadata->height, $metadata->mime_type, $metadata->extension);
+  }
+}
diff --git a/modules/gallery/helpers/random.php b/modules/gallery/helpers/random.php
new file mode 100644
index 0000000..d40bfb5
--- /dev/null
+++ b/modules/gallery/helpers/random.php
@@ -0,0 +1,48 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class random_Core {
+  /**
+   * Return a random 32 byte hash value.
+   * @param string extra entropy data
+   */
+  static function hash($length=32) {
+    require_once(MODPATH . "gallery/vendor/joomla/crypt.php");
+    return md5(JCrypt::genRandomBytes($length));
+  }
+
+  /**
+   * Return a random floating point number between 0 and 1
+   */
+  static function percent() {
+    return ((float)mt_rand()) / (float)mt_getrandmax();
+  }
+
+  /**
+   * Return a random number between $min and $max.  If $min and $max are not specified,
+   * return a random number between 0 and mt_getrandmax()
+   */
+  static function int($min=null, $max=null) {
+    if ($min || $max) {
+      return mt_rand($min, $max);
+    }
+    return mt_rand();
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/site_status.php b/modules/gallery/helpers/site_status.php
new file mode 100644
index 0000000..e1a8163
--- /dev/null
+++ b/modules/gallery/helpers/site_status.php
@@ -0,0 +1,132 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class site_status_Core {
+  const SUCCESS = 1;
+  const INFO    = 2;
+  const WARNING = 3;
+  const ERROR   = 4;
+
+  /**
+   * Report a successful event.
+   * @param string  $msg           a detailed message
+   * @param string  $permanent_key make this message permanent and store it under this key
+   */
+  static function success($msg, $permanent_key) {
+    self::_add($msg, self::SUCCESS, $permanent_key);
+  }
+
+  /**
+   * Report an informational event.
+   * @param string  $msg           a detailed message
+   * @param string  $permanent_key make this message permanent and store it under this key
+   */
+  static function info($msg, $permanent_key) {
+    self::_add($msg, self::INFO, $permanent_key);
+  }
+
+  /**
+   * Report that something went wrong, not fatal, but worth investigation.
+   * @param string  $msg           a detailed message
+   * @param string  $permanent_key make this message permanent and store it under this key
+   */
+  static function warning($msg, $permanent_key) {
+    self::_add($msg, self::WARNING, $permanent_key);
+  }
+
+  /**
+   * Report that something went wrong that should be fixed.
+   * @param string  $msg           a detailed message
+   * @param string  $permanent_key make this message permanent and store it under this key
+   */
+  static function error($msg, $permanent_key) {
+    self::_add($msg, self::ERROR, $permanent_key);
+  }
+
+  /**
+   * Save a message in the session for our next page load.
+   * @param string  $msg           a detailed message
+   * @param integer $severity      one of the severity constants
+   * @param string  $permanent_key make this message permanent and store it under this key
+   */
+  private static function _add($msg, $severity, $permanent_key) {
+    $message = ORM::factory("message")
+      ->where("key", "=", $permanent_key)
+      ->find();
+    if (!$message->loaded()) {
+      $message->key = $permanent_key;
+    }
+    $message->severity = $severity;
+    $message->value = $msg;
+    $message->save();
+  }
+
+  /**
+   * Remove any permanent message by key.
+   * @param string $permanent_key
+   */
+  static function clear($permanent_key) {
+    $message = ORM::factory("message")->where("key", "=", $permanent_key)->find();
+    if ($message->loaded()) {
+      $message->delete();
+    }
+  }
+
+  /**
+   * Get any pending messages.  There are two types of messages, transient and permanent.
+   * Permanent messages are used to let the admin know that there are pending administrative
+   * issues that need to be resolved.  Transient ones are only displayed once.
+   * @return html text
+   */
+  static function get() {
+    if (!identity::active_user()->admin) {
+      return;
+    }
+    $buf = array();
+    foreach (ORM::factory("message")->find_all() as $msg) {
+      $value = str_replace("__CSRF__", access::csrf_token(), $msg->value);
+      $buf[] = "<li class=\"" . site_status::severity_class($msg->severity) . "\">$value</li>";
+    }
+
+    if ($buf) {
+      return "<ul id=\"g-site-status\">" . implode("", $buf) . "</ul>";
+    }
+  }
+
+  /**
+   * Convert a message severity to a CSS class
+   * @param  integer $severity
+   * @return string
+   */
+  static function severity_class($severity) {
+    switch($severity) {
+    case site_status::SUCCESS:
+      return "g-success";
+
+    case site_status::INFO:
+      return "g-info";
+
+    case site_status::WARNING:
+      return "g-warning";
+
+    case site_status::ERROR:
+      return "g-error";
+    }
+  }
+}
diff --git a/modules/gallery/helpers/system.php b/modules/gallery/helpers/system.php
new file mode 100644
index 0000000..f0879d6
--- /dev/null
+++ b/modules/gallery/helpers/system.php
@@ -0,0 +1,113 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class system_Core {
+  private static $files_marked_for_deletion = array();
+
+  /**
+   * Return the path to an executable version of the named binary, or null.
+   * The paths are traversed in the following order:
+   *   1. $priority_path (if specified)
+   *   2. Gallery's own bin directory (DOCROOT . "bin")
+   *   3. PATH environment variable
+   *   4. extra_binary_paths Gallery variable (if specified)
+   * In addition, if the file is found inside Gallery's bin directory but
+   * it's not executable, we try to change its permissions to 0755.
+   *
+   * @param  string $binary
+   * @param  string $priority_path (optional)
+   * @return string path to binary if found; null if not found
+   */
+  static function find_binary($binary, $priority_path=null) {
+    $bin_path = DOCROOT . "bin";
+
+    if ($priority_path) {
+      $paths = array($priority_path, $bin_path);
+    } else {
+      $paths = array($bin_path);
+    }
+    $paths = array_merge($paths,
+      explode(":", getenv("PATH")),
+      explode(":", module::get_var("gallery", "extra_binary_paths")));
+
+    foreach ($paths as $path) {
+      $path = rtrim($path, "/");
+      $candidate = "$path/$binary";
+      // @suppress errors below to avoid open_basedir issues
+      if (@file_exists($candidate)) {
+        if (!@is_executable($candidate) &&
+            (substr_compare($bin_path, $candidate, 0, strlen($bin_path)) == 0)) {
+          // Binary isn't executable but is in Gallery's bin directory - try fixing permissions.
+          @chmod($candidate, 0755);
+        }
+        if (@is_executable($candidate)) {
+          return $candidate;
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Create a file with a unique file name.
+   * This helper is similar to the built-in tempnam.
+   * It allows the caller to specify a prefix and an extension.
+   * It always places the file in TMPPATH.
+   * Unless specified with the $delete_later argument, it will be marked
+   * for deletion at shutdown using system::delete_later.
+   */
+  static function temp_filename($prefix="", $extension="", $delete_later=true) {
+    do {
+      $basename = tempnam(TMPPATH, $prefix);
+      if (!$basename) {
+        return false;
+      }
+      $filename = "$basename.$extension";
+      $success = !file_exists($filename) && @rename($basename, $filename);
+      if (!$success) {
+        @unlink($basename);
+      }
+    } while (!$success);
+
+    if ($delete_later) {
+      system::delete_later($filename);
+    }
+
+    return $filename;
+  }
+
+  /**
+   * Mark a file for deletion at shutdown time.  This is useful for temp files, where we can delay
+   * the deletion time until shutdown to keep page load time quick.
+   */
+  static function delete_later($filename) {
+    self::$files_marked_for_deletion[] = $filename;
+  }
+
+  /**
+   * Delete all files marked using system::delete_later.  This is called at gallery shutdown.
+   */
+  static function delete_marked_files() {
+    foreach (self::$files_marked_for_deletion as $filename) {
+      // We want to suppress all errors, as it's possible that some of these
+      // files may have been deleted/moved before we got here.
+      @unlink($filename);
+    }
+  }
+}
diff --git a/modules/gallery/helpers/task.php b/modules/gallery/helpers/task.php
new file mode 100644
index 0000000..5638faf
--- /dev/null
+++ b/modules/gallery/helpers/task.php
@@ -0,0 +1,113 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class task_Core {
+  /**
+   * Get all available tasks
+   */
+  static function get_definitions() {
+    $tasks = array();
+    foreach (module::active() as $module) {
+      $class_name = "{$module->name}_task";
+      if (class_exists($class_name) && method_exists($class_name, "available_tasks")) {
+        foreach (call_user_func(array($class_name, "available_tasks")) as $task) {
+          $tasks[$task->callback] = $task;
+        }
+      }
+    }
+
+    return $tasks;
+  }
+
+  static function start($task_callback, $context=array()) {
+    $tasks = task::get_definitions();
+    $task = task::create($tasks[$task_callback], array());
+
+    $task->log(t("Task %task_name started (task id %task_id)",
+                 array("task_name" => $task->name, "task_id" => $task->id)));
+    return $task;
+  }
+
+  static function create($task_def, $context) {
+    $task = ORM::factory("task");
+    $task->callback = $task_def->callback;
+    $task->name = $task_def->name;
+    $task->percent_complete = 0;
+    $task->status = "";
+    $task->state = "started";
+    $task->owner_id = identity::active_user()->id;
+    $task->context = serialize($context);
+    $task->save();
+
+    return $task;
+  }
+
+  static function cancel($task_id) {
+    $task = ORM::factory("task", $task_id);
+    if (!$task->loaded()) {
+      throw new Exception("@todo MISSING_TASK");
+    }
+    $task->done = 1;
+    $task->state = "cancelled";
+    $task->log(t("Task %task_name cancelled (task id %task_id)",
+                 array("task_name" => $task->name, "task_id" => $task->id)));
+    $task->save();
+
+    return $task;
+  }
+
+  static function remove($task_id) {
+    $task = ORM::factory("task", $task_id);
+    if ($task->loaded()) {
+      $task->delete();
+    }
+  }
+
+  static function run($task_id) {
+    $task = ORM::factory("task", $task_id);
+    if (!$task->loaded()) {
+      throw new Exception("@todo MISSING_TASK");
+    }
+
+    try {
+      $task->state = "running";
+      call_user_func_array($task->callback, array(&$task));
+      if ($task->done) {
+        $task->log($task->status);
+      }
+      $task->save();
+    } catch (Exception $e) {
+      Kohana_Log::add("error", (string)$e);
+
+      // Ugh.  I hate to use instanceof, But this beats catching the exception separately since
+      // we mostly want to treat it the same way as all other exceptions
+      if ($e instanceof ORM_Validation_Exception) {
+        Kohana_Log::add("error", "Validation errors: " . print_r($e->validation->errors(), 1));
+      }
+
+      $task->log((string)$e);
+      $task->state = "error";
+      $task->done = true;
+      $task->status = substr($e->getMessage(), 0, 255);
+      $task->save();
+    }
+
+    return $task;
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/helpers/theme.php b/modules/gallery/helpers/theme.php
new file mode 100644
index 0000000..072f98a
--- /dev/null
+++ b/modules/gallery/helpers/theme.php
@@ -0,0 +1,113 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling themes.
+ *
+ * Note: by design, this class does not do any permission checking.
+ */
+class theme_Core {
+  public static $admin_theme_name;
+  public static $site_theme_name;
+  public static $is_admin;
+
+  /**
+   * Load the active theme.  This is called at bootstrap time.  We will only ever have one theme
+   * active for any given request.
+   */
+  static function load_themes() {
+    $input = Input::instance();
+    $path = $input->server("PATH_INFO");
+    if (empty($path)) {
+      $path = "/" . $input->get("kohana_uri");
+    }
+
+    $config = Kohana_Config::instance();
+    $modules = $config->get("core.modules");
+
+    // Normally Router::find_uri() strips off the url suffix for us, but we're working off of the
+    // PATH_INFO here so we need to strip it off manually
+    if ($suffix = Kohana::config("core.url_suffix")) {
+      $path = preg_replace("#" . preg_quote($suffix) . "$#u", "", $path);
+    }
+
+    self::$is_admin = $path == "/admin" || !strncmp($path, "/admin/", 7);
+    self::$site_theme_name = module::get_var("gallery", "active_site_theme");
+
+    // If the site theme doesn't exist, fall back to wind.
+    if (!file_exists(THEMEPATH . self::$site_theme_name . "/theme.info")) {
+      site_status::error(t("Theme '%name' is missing.  Falling back to the Wind theme.",
+                           array("name" => self::$site_theme_name)), "missing_site_theme");
+      module::set_var("gallery", "active_site_theme", self::$site_theme_name = "wind");
+    }
+
+    if (self::$is_admin) {
+      // Load the admin theme
+      self::$admin_theme_name = module::get_var("gallery", "active_admin_theme");
+
+      // If the admin theme doesn't exist, fall back to admin_wind.
+      if (!file_exists(THEMEPATH . self::$admin_theme_name . "/theme.info")) {
+        site_status::error(t("Admin theme '%name' is missing!  Falling back to the Wind theme.",
+                             array("name" => self::$admin_theme_name)), "missing_admin_theme");
+        module::set_var("gallery", "active_admin_theme", self::$admin_theme_name = "admin_wind");
+      }
+
+      array_unshift($modules, THEMEPATH . self::$admin_theme_name);
+
+      // If the site theme has an admin subdir, load that as a module so that
+      // themes can provide their own code.
+      if (file_exists(THEMEPATH . self::$site_theme_name . "/admin")) {
+        array_unshift($modules, THEMEPATH . self::$site_theme_name . "/admin");
+      }
+      // Admins can override the site theme, temporarily.  This lets us preview themes.
+      if (identity::active_user()->admin && $override = $input->get("theme")) {
+        if (file_exists(THEMEPATH . $override)) {
+          self::$admin_theme_name = $override;
+          array_unshift($modules, THEMEPATH . self::$admin_theme_name);
+        } else {
+          Kohana_Log::add("error", "Missing override admin theme: '$override'");
+        }
+      }
+    } else {
+      // Admins can override the site theme, temporarily.  This lets us preview themes.
+      if (identity::active_user()->admin && $override = $input->get("theme")) {
+        if (file_exists(THEMEPATH . $override)) {
+          self::$site_theme_name = $override;
+        } else {
+          Kohana_Log::add("error", "Missing override site theme: '$override'");
+        }
+      }
+      array_unshift($modules, THEMEPATH . self::$site_theme_name);
+    }
+
+    $config->set("core.modules", $modules);
+  }
+
+  static function get_info($theme_name) {
+    $theme_name = preg_replace("/[^a-zA-Z0-9\._-]/", "", $theme_name);
+    $file = THEMEPATH . "$theme_name/theme.info";
+    $theme_info = new ArrayObject(parse_ini_file($file), ArrayObject::ARRAY_AS_PROPS);
+    $theme_info->description = t($theme_info->description);
+    $theme_info->name = t($theme_info->name);
+
+    return $theme_info;
+  }
+}
+
diff --git a/modules/gallery/helpers/tree_rest.php b/modules/gallery/helpers/tree_rest.php
new file mode 100644
index 0000000..5186cf0
--- /dev/null
+++ b/modules/gallery/helpers/tree_rest.php
@@ -0,0 +1,92 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class tree_rest_Core {
+  /**
+   * The tree is rooted in a single item and can have modifiers which adjust what data is shown
+   * for items inside the given tree, up to the depth that you want.  The entity for this resource
+   * is a series of items.
+   *
+   *  depth=<number>
+   *    Only traverse this far down into the tree.  If there are more albums
+   *    below this depth, provide RESTful urls to other tree resources in
+   *    the members section.  Default is infinite.
+   *
+   *  type=<album|photo|movie>
+   *    Restrict the items displayed to the given type.  Default is all types.
+   *
+   *  fields=<comma separated list of field names>
+   *    In the entity section only return these fields for each item.
+   *    Default is all fields.
+   */
+  static function get($request) {
+    $item = rest::resolve($request->url);
+    access::required("view", $item);
+
+    $query_params = array();
+    $p = $request->params;
+    $where = array();
+    if (isset($p->type)) {
+      $where[] = array("type", "=", $p->type);
+      $query_params[] = "type={$p->type}";
+    }
+
+    if (isset($p->depth)) {
+      $lowest_depth = $item->level + $p->depth;
+      $where[] = array("level", "<=", $lowest_depth);
+      $query_params[] = "depth={$p->depth}";
+    }
+
+    $fields = array();
+    if (isset($p->fields)) {
+      $fields = explode(",", $p->fields);
+      $query_params[] = "fields={$p->fields}";
+    }
+
+    $entity = array(array("url" => rest::url("item", $item),
+                           "entity" => $item->as_restful_array($fields)));
+    $members = array();
+    foreach ($item->viewable()->descendants(null, null, $where) as $child) {
+      $entity[] = array("url" => rest::url("item", $child),
+                        "entity" => $child->as_restful_array($fields));
+      if (isset($lowest_depth) && $child->level == $lowest_depth) {
+        $members[] = url::merge_querystring(rest::url("tree", $child), $query_params);
+      }
+    }
+
+    $result = array(
+      "url" => $request->url,
+      "entity" => $entity,
+      "members" => $members,
+      "relationships" => rest::relationships("tree", $item));
+    return $result;
+  }
+
+  static function resolve($id) {
+    $item = ORM::factory("item", $id);
+    if (!access::can("view", $item)) {
+      throw new Kohana_404_Exception();
+    }
+    return $item;
+  }
+
+  static function url($item) {
+    return url::abs_site("rest/tree/{$item->id}");
+  }
+}
diff --git a/modules/gallery/helpers/upgrade_checker.php b/modules/gallery/helpers/upgrade_checker.php
new file mode 100644
index 0000000..492f72e
--- /dev/null
+++ b/modules/gallery/helpers/upgrade_checker.php
@@ -0,0 +1,105 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class upgrade_checker_Core {
+  const CHECK_URL = "http://galleryproject.org/versioncheck/gallery3";
+  const AUTO_CHECK_INTERVAL = 604800;  // 7 days in seconds
+
+  /**
+   * Return the last version info blob retrieved from the Gallery website or
+   * null if no checks have been performed.
+   */
+  static function version_info() {
+    return unserialize(Cache::instance()->get("upgrade_checker_version_info"));
+  }
+
+  /**
+   * Return true if auto checking is enabled.
+   */
+  static function auto_check_enabled() {
+    return (bool)module::get_var("gallery", "upgrade_checker_auto_enabled");
+  }
+
+  /**
+   * Return true if it's time to auto check.
+   */
+  static function should_auto_check() {
+    if (upgrade_checker::auto_check_enabled() && random::int(1, 100) == 1) {
+      $version_info = upgrade_checker::version_info();
+      return (!$version_info ||
+              (time() - $version_info->timestamp) > upgrade_checker::AUTO_CHECK_INTERVAL);
+    }
+    return false;
+  }
+
+  /**
+   * Fech version info from the Gallery website.
+   */
+  static function fetch_version_info() {
+    $result = new stdClass();
+    try {
+      list ($status, $headers, $body) = remote::do_request(upgrade_checker::CHECK_URL);
+      if ($status == "HTTP/1.1 200 OK") {
+        $result->status = "success";
+        foreach (explode("\n", $body) as $line) {
+          if ($line) {
+            list($key, $val) = explode("=", $line, 2);
+            $result->data[$key] = $val;
+          }
+        }
+      } else {
+        $result->status = "error";
+      }
+    } catch (Exception $e) {
+      Kohana_Log::add("error",
+                      sprintf("%s in %s at line %s:\n%s", $e->getMessage(), $e->getFile(),
+                              $e->getLine(), $e->getTraceAsString()));
+    }
+    $result->timestamp = time();
+    Cache::instance()->set("upgrade_checker_version_info", serialize($result),
+                           array("upgrade"), 86400 * 365);
+  }
+
+  /**
+   * Check the latest version info blob to see if it's time for an upgrade.
+   */
+  static function get_upgrade_message() {
+    $version_info = upgrade_checker::version_info();
+    if ($version_info) {
+      if (gallery::RELEASE_CHANNEL == "release") {
+        if (version_compare($version_info->data["release_version"], gallery::VERSION, ">")) {
+          return t("A newer version of Gallery is available! <a href=\"%upgrade-url\">Upgrade now</a> to version %version",
+                   array("version" => $version_info->data["release_version"],
+                         "upgrade-url" => $version_info->data["release_upgrade_url"]));
+        }
+      } else {
+        $branch = gallery::RELEASE_BRANCH;
+        if (isset($version_info->data["branch_{$branch}_build_number"]) &&
+            version_compare($version_info->data["branch_{$branch}_build_number"],
+                            gallery::build_number(), ">")) {
+          return t("A newer version of Gallery is available! <a href=\"%upgrade-url\">Upgrade now</a> to version %version (build %build on branch %branch)",
+                   array("version" => $version_info->data["branch_{$branch}_version"],
+                         "upgrade-url" => $version_info->data["branch_{$branch}_upgrade_url"],
+                         "build" => $version_info->data["branch_{$branch}_build_number"],
+                         "branch" => $branch));
+        }
+      }
+    }
+  }
+}
diff --git a/modules/gallery/helpers/user_profile.php b/modules/gallery/helpers/user_profile.php
new file mode 100644
index 0000000..222d2f5
--- /dev/null
+++ b/modules/gallery/helpers/user_profile.php
@@ -0,0 +1,55 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class user_profile_Core {
+  /**
+   * Generate the url to display the profile
+   * @return url for the profile display
+   */
+  static function url($user_id) {
+    return url::site("user_profile/show/{$user_id}");
+  }
+
+  static function get_contact_form($user) {
+    $form = new Forge("user_profile/send/{$user->id}", "", "post",
+                      array("id" => "g-user-profile-contact-form"));
+    $group = $form->group("message")
+      ->label(t("Compose message to %name", array("name" => $user->display_name())));
+    $group->input("reply_to")
+      ->label(t("From:"))
+      ->rules("required|length[1, 256]|valid_email")
+      ->error_messages("required", t("You must enter a valid email address"))
+      ->error_messages("max_length", t("Your email address is too long"))
+      ->error_messages("valid_email", t("You must enter a valid email address"));
+    $group->input("subject")
+      ->label(t("Subject:"))
+      ->rules("required|length[1, 256]")
+      ->error_messages("required", t("Your message must have a subject"))
+      ->error_messages("max_length", t("Your subject is too long"));
+    $group->textarea("message")
+      ->label(t("Message:"))
+      ->rules("required")
+      ->error_messages("required", t("You must enter a message"));
+    module::event("user_profile_contact_form", $form);
+    module::event("captcha_protect_form", $form);
+    $group->submit("")->value(t("Send"));
+    return $form;
+  }
+}
diff --git a/modules/gallery/helpers/xml.php b/modules/gallery/helpers/xml.php
new file mode 100644
index 0000000..e20beb1
--- /dev/null
+++ b/modules/gallery/helpers/xml.php
@@ -0,0 +1,35 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class xml_Core {
+  static function to_xml($array, $element_names) {
+    $xml = "<$element_names[0]>\n";
+    foreach ($array as $key => $value) {
+      if (is_array($value)) {
+        $xml .= xml::to_xml($value, array_slice($element_names, 1));
+      } else if (is_object($value)) {
+        $xml .= xml::to_xml($value->as_array(), array_slice($element_names, 1));
+      } else {
+        $xml .= "<$key>$value</$key>\n";
+      }
+    }
+    $xml .= "</$element_names[0]>\n";
+    return $xml;
+  }
+}
diff --git a/modules/gallery/hooks/init_gallery.php b/modules/gallery/hooks/init_gallery.php
new file mode 100644
index 0000000..fa4f816
--- /dev/null
+++ b/modules/gallery/hooks/init_gallery.php
@@ -0,0 +1,56 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+// If var/database.php doesn't exist, then we assume that the Gallery is not properly installed
+// and send users to the installer.
+if (!file_exists(VARPATH . "database.php")) {
+  url::redirect(url::abs_file("installer"));
+}
+
+// Simple and cheap test to make sure that the database config is ok.  Do this before we do
+// anything else database related.
+try {
+  Database::instance()->connect();
+} catch (Kohana_PHP_Exception $e) {
+  print "Database configuration error.  Please check var/database.php";
+  exit;
+}
+
+Event::add("system.ready", array("Gallery_I18n", "instance"));
+Event::add("system.ready", array("module", "load_modules"));
+Event::add("system.ready", array("gallery", "ready"));
+Event::add("system.post_routing", array("url", "parse_url"));
+Event::add("system.post_routing", array("gallery", "maintenance_mode"));
+Event::add("system.post_routing", array("gallery", "private_gallery"));
+Event::add("system.shutdown", array("gallery", "shutdown"));
+
+// @todo once we convert to Kohana 2.4 this doesn't have to be here
+set_error_handler(array("gallery_error", "error_handler"));
+
+// Override the cookie if we have a session id in the URL.
+// @todo This should probably be an event callback
+$input = Input::instance();
+if ($g3sid = $input->post("g3sid", $input->get("g3sid"))) {
+  $_COOKIE["g3sid"] = $g3sid;
+}
+
+if ($user_agent = $input->post("user_agent", $input->get("user_agent"))) {
+  $_SERVER["HTTP_USER_AGENT"] = $user_agent;
+}
diff --git a/modules/gallery/images/ffmpeg.png b/modules/gallery/images/ffmpeg.png
new file mode 100644
index 0000000..6be8b62
Binary files /dev/null and b/modules/gallery/images/ffmpeg.png differ
diff --git a/modules/gallery/images/gallery.png b/modules/gallery/images/gallery.png
new file mode 100644
index 0000000..ca8e0e9
Binary files /dev/null and b/modules/gallery/images/gallery.png differ
diff --git a/modules/gallery/images/gd.png b/modules/gallery/images/gd.png
new file mode 100644
index 0000000..b341d71
Binary files /dev/null and b/modules/gallery/images/gd.png differ
diff --git a/modules/gallery/images/graphicsmagick.png b/modules/gallery/images/graphicsmagick.png
new file mode 100644
index 0000000..3d1d77e
Binary files /dev/null and b/modules/gallery/images/graphicsmagick.png differ
diff --git a/modules/gallery/images/imagemagick.jpg b/modules/gallery/images/imagemagick.jpg
new file mode 100644
index 0000000..d83c450
Binary files /dev/null and b/modules/gallery/images/imagemagick.jpg differ
diff --git a/modules/gallery/images/missing_album_cover.jpg b/modules/gallery/images/missing_album_cover.jpg
new file mode 100644
index 0000000..bdddeec
Binary files /dev/null and b/modules/gallery/images/missing_album_cover.jpg differ
diff --git a/modules/gallery/images/missing_movie.jpg b/modules/gallery/images/missing_movie.jpg
new file mode 100644
index 0000000..452db22
Binary files /dev/null and b/modules/gallery/images/missing_movie.jpg differ
diff --git a/modules/gallery/images/missing_photo.jpg b/modules/gallery/images/missing_photo.jpg
new file mode 100644
index 0000000..a9d176d
Binary files /dev/null and b/modules/gallery/images/missing_photo.jpg differ
diff --git a/modules/gallery/js/albums_form_add.js b/modules/gallery/js/albums_form_add.js
new file mode 100644
index 0000000..4e22760
--- /dev/null
+++ b/modules/gallery/js/albums_form_add.js
@@ -0,0 +1,25 @@
+$("#g-add-album-form input[name=title]").change(
+  function() {
+    console.log("changing title");
+    $("#g-add-album-form input[name=name]").attr(
+      "value", $("#g-add-album-form input[name=title]").attr("value")
+        .replace(/[\s\/]+/g, "-").replace(/\.+$/, ""));
+    $("#g-add-album-form input[name=slug]").attr(
+      "value", $("#g-add-album-form input[name=title]").attr("value")
+        .replace(/[^A-Za-z0-9-_]+/g, "-")
+	.replace(/^-+/, "")
+	.replace(/-+$/, ""));
+  });
+$("#g-add-album-form input[name=title]").keyup(
+  function() {
+    console.log("key up");
+    $("#g-add-album-form input[name=name]").attr(
+      "value", $("#g-add-album-form input[name=title]").attr("value")
+        .replace(/[\s\/]+/g, "-")
+	.replace(/\.+$/, ""));
+    $("#g-add-album-form input[name=slug]").attr(
+      "value", $("#g-add-album-form input[name=title]").attr("value")
+        .replace(/[^A-Za-z0-9-_]+/g, "-")
+	.replace(/^-+/, "")
+	.replace(/-+$/, ""));
+  });
diff --git a/modules/gallery/js/item_form_delete.js b/modules/gallery/js/item_form_delete.js
new file mode 100644
index 0000000..fa3f24a
--- /dev/null
+++ b/modules/gallery/js/item_form_delete.js
@@ -0,0 +1,5 @@
+$("#g-confirm-delete").submit(
+  function() {
+    $("#g-confirm-delete input[type=submit]").gallery_show_loading();
+  }
+);
diff --git a/modules/gallery/js/l10n_client.js b/modules/gallery/js/l10n_client.js
new file mode 100644
index 0000000..6d919c2
--- /dev/null
+++ b/modules/gallery/js/l10n_client.js
@@ -0,0 +1,315 @@
+// Fork from Drupal's l10n_client module, originally written by:
+// Gbor Hojtsy http://drupal.org/user/4166 (original author)
+// Young Hahn / Development Seed - http://developmentseed.org/ (friendly user interface)
+
+var Gallery = Gallery || { 'behaviors': {} };
+
+Gallery.attachBehaviors = function(context) {
+  context = context || document;
+  // Execute all of them.
+  jQuery.each(Gallery.behaviors,
+              function() {
+                  this(context);
+              });
+};
+
+$(document).ready(function() {
+  Gallery.attachBehaviors(this);
+});
+
+// Store all l10n_client related data + methods in its own object
+jQuery.extend(Gallery, {
+  l10nClient: new (function() {
+    // Set "selected" string to unselected, i.e. -1
+    this.selected = -1;
+    // Keybindings
+    this.keys = {'toggle':'ctrl+shift+s', 'clear': 'esc'}; // Keybindings
+    // Keybinding functions
+    this.key = function(pressed) {
+      switch(pressed) {
+        case 'toggle':
+          // Grab user-hilighted text & send it into the search filter
+          userSelection = window.getSelection ? window.getSelection() : document.getSelection ? document.getSelection() : document.selection.createRange().text;
+          userSelection = String(userSelection);
+          if(userSelection.length > 0) {
+            Gallery.l10nClient.filter(userSelection);
+            Gallery.l10nClient.toggle(1);
+            $('#l10n-client #g-l10n-search').focus();
+          } else {
+            if($('#l10n-client').is('.hidden')) {
+              Gallery.l10nClient.toggle(1);
+              if(!$.browser.safari) {
+                $('#l10n-client #g-l10n-search').focus();
+              }
+            } else {
+              Gallery.l10nClient.toggle(0);
+            }
+          }
+        break;
+        case 'clear':
+          this.filter(false);
+        break;
+      }
+    };
+
+    // Toggle the l10nclient
+    this.toggle = function(state) {
+      switch(state) {
+        case 1:
+          $('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label').show();
+          $('#l10n-client').height('22em').removeClass('hidden');
+					//$('#l10n-client').slideUp();
+					$('#g-minimize-l10n').text("_");
+	  // This CSS clashes with Gallery's CSS, probably due to
+	  // YUI's grid / floats.
+	  // if(!$.browser.msie) {
+	  //     $('body').css('border-bottom', '22em solid #fff');
+	  // }
+          $.cookie('Gallery_l10n_client', '1', {expires: 7, path: '/'});
+        break;
+        case 0:
+          $('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label').hide();
+          $('#l10n-client').height('2em').addClass('hidden');
+          // TODO: Localize this message
+          $('#g-minimize-l10n').text(MSG_TRANSLATE_TEXT);
+          // if(!$.browser.msie) {
+          //   $('body').css('border-bottom', '0px');
+          // }
+          $.cookie('Gallery_l10n_client', '0', {expires: 7, path: '/'});
+        break;
+      }
+    };
+
+    // Get a string from the DOM tree
+    this.getString = function(index, type) {
+      if (index < l10n_client_data.length) {
+        return l10n_client_data[index][type];
+      }
+      return "";
+    };
+
+    // Set a string in the DOM tree
+    this.setString = function(index, data) {
+      l10n_client_data[index]['translation'] = data;
+    };
+
+    // Display the source message
+    this.showSourceMessage = function(source, is_plural) {
+      if (is_plural) {
+        var pretty_source = $('#source-text-tmp-space').text('[one] - ' + source['one']).html();
+        pretty_source += '<br/>';
+        pretty_source += $('#source-text-tmp-space').text('[other] - ' + source['other']).html();
+      } else {
+        var pretty_source = $('#source-text-tmp-space').text(source).html();
+      }
+      $('#l10n-client-string-editor .source-text').html(pretty_source);
+    };
+    this.isPluralMessage = function(message) {
+      return typeof(message) == 'object';
+    };
+
+    this.updateTranslationForm = function(translation, is_plural) {
+      $('.translationField').addClass('hidden');
+      if (is_plural) {
+        if (typeof(translation) != 'object') {
+          translation = {};
+        }
+        var num_plural_forms = plural_forms.length;
+        for (var i = 0; i < num_plural_forms; i++) {
+          var form = plural_forms[i];
+          if (translation[form] == undefined) {
+            translation[form] = '';
+          }
+          $("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']")
+              .attr('value', translation[form]);
+          $('#plural-' + form).removeClass('hidden');
+        }
+      } else {
+        $('#l10n-edit-translation').attr('value', translation);
+        $('#l10n-edit-translation').removeClass('hidden');
+      }
+    };
+
+    // Filter the string list by a search string
+    this.filter = function(search) {
+      if(search == false || search == '') {
+        $('#l10n-client #l10n-search-filter-clear').focus();
+        $('#l10n-client-string-select li').show();
+        $('#l10n-client #g-l10n-search').val('');
+        $('#l10n-client #g-l10n-search').focus();
+      } else {
+        if(search.length > 0) {
+          $('#l10n-client-string-select li').hide();
+          $('#l10n-client-string-select li').each(function() {
+            if ($(this).val().indexOf(search) != -1) {
+		$(this).show();
+	    }
+          });
+          $('#l10n-client #g-l10n-search').val(search);
+        }
+      }
+    };
+
+    this.copySourceText = function() {
+      var index  = Gallery.l10nClient.selected;
+      if (index >= 0) {
+        var source = Gallery.l10nClient.getString(index, 'source');
+        var is_plural = Gallery.l10nClient.isPluralMessage(source);
+        if (is_plural) {
+          if (typeof(translation) != 'object') {
+            translation = {};
+          }
+          var num_plural_forms = plural_forms.length;
+          for (var i = 0; i < num_plural_forms; i++) {
+            var form = plural_forms[i];
+            var text = source['other'];
+            if (form == 'one') {
+              text = source['one'];
+            }
+            $("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']")
+                .attr('value', text);
+          }
+        } else {
+          $('#l10n-edit-translation').attr('value', source);
+        }
+
+      }
+    };
+  })
+});
+
+// Attaches the localization editor behavior to all required fields.
+Gallery.behaviors.l10nClient = function(context) {
+
+  switch($.cookie('Gallery_l10n_client')) {
+    case '1':
+      Gallery.l10nClient.toggle(1);
+    break;
+    default:
+      Gallery.l10nClient.toggle(0);
+    break;
+  }
+
+  // If the selection changes, copy string values to the source and target fields.
+  // Add class to indicate selected string in list widget.
+  $('#l10n-client-string-select li').click(function() {
+    $('#l10n-client-string-select li').removeClass('active');
+    $(this).addClass('active');
+    var index = $('#l10n-client-string-select li').index(this);
+    var source = Gallery.l10nClient.getString(index, 'source');
+    var key = Gallery.l10nClient.getString(index, 'key');
+    var is_plural = Gallery.l10nClient.isPluralMessage(source);
+    Gallery.l10nClient.showSourceMessage(source, is_plural);
+    Gallery.l10nClient.updateTranslationForm(Gallery.l10nClient.getString(index, 'translation'), is_plural);
+    $("#g-l10n-client-save-form input[name='l10n-message-key']").val(key);
+    Gallery.l10nClient.selected = index;
+  });
+
+  // When l10n_client window is clicked, toggle based on current state.
+  $('#g-minimize-l10n').click(function() {
+    if($('#l10n-client').is('.hidden')) {
+      Gallery.l10nClient.toggle(1);
+    } else {
+      Gallery.l10nClient.toggle(0);
+    }
+  });
+
+  // Close the l10n client using an AJAX call and refreshing the page
+  $('#g-close-l10n').click(function(event) {
+		$.ajax({
+      type: "GET",
+      url: toggle_l10n_mode_url,
+      data: "csrf=" + csrf,
+      success: function() {
+        window.location.reload(true);
+      }
+    });
+		event.preventDefault();
+  });
+
+  // Register keybindings using jQuery hotkeys
+  // TODO: Either remove hotkeys code or add query.hotkeys.js.
+  if($.hotkeys) {
+    $.hotkeys.add(Gallery.l10nClient.keys['toggle'], function(){Gallery.l10nClient.key('toggle');});
+    $.hotkeys.add(Gallery.l10nClient.keys['clear'], {target:'#l10n-client #g-l10n-search', type:'keyup'}, function(){Gallery.l10nClient.key('clear');});
+  }
+
+  // never actually submit the form as the search is done in the browser
+  $('#g-l10n-search-form').submit(function() {
+    return false;
+  });
+
+  // Custom listener for l10n_client livesearch
+  $('#l10n-client #g-l10n-search').keyup(function(key) {
+    Gallery.l10nClient.filter($('#l10n-client #g-l10n-search').val());
+  });
+
+  // Clear search
+  $('#l10n-client #l10n-search-filter-clear').click(function() {
+    Gallery.l10nClient.filter(false);
+    return false;
+  });
+
+  // Send AJAX POST data on form submit.
+  $('#g-l10n-client-save-form').ajaxForm({
+      dataType: "json",
+      success: function(data) {
+              var source = Gallery.l10nClient.getString(Gallery.l10nClient.selected, 'source');
+              var is_plural = Gallery.l10nClient.isPluralMessage(source);
+              var num_plural_forms = plural_forms.length;
+
+              // Store translation in local js
+              var translation = {};
+              var is_non_empty = false;
+              if (is_plural) {
+                   for (var i = 0; i < num_plural_forms; i++) {
+                      var form = plural_forms[i];
+                      translation[form] = $("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']").attr('value');
+                      is_non_empty = is_non_empty || translation[form];
+                  }
+              } else {
+                  translation = $('#l10n-edit-translation').attr('value');
+                  is_non_empty = translation;
+              }
+              Gallery.l10nClient.setString(Gallery.l10nClient.selected, translation);
+
+              // Mark message as translated / untranslated.
+              var source_element = $('#l10n-client-string-select li').eq(Gallery.l10nClient.selected);
+              if (is_non_empty) {
+                  source_element.removeClass('untranslated').removeClass('active').addClass('translated');
+              } else {
+                  source_element.removeClass('active').removeClass('translated').addClass('untranslated');
+              }
+
+              // Clear the translation form fields
+              Gallery.l10nClient.showSourceMessage('', false);
+              $('#g-l10n-client-save-form #l10n-edit-translation').val('');
+
+              for (var i = 0; i < num_plural_forms; i++) {
+                  var form = plural_forms[i];
+                  $("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']").val('');
+              }
+              $("#g-l10n-client-save-form input[name='l10n-message-key']").val('');
+          },
+              error: function(xmlhttp) {
+              // TODO: Localize this message
+              alert('An HTTP error @status occured (or empty response).'.replace('@status', xmlhttp.status));
+          }
+      });
+
+  // TODO: Add copy/clear buttons (without ajax behavior)
+  /*         <input type="submit" name="l10n-edit-copy" value="<?= t("Copy source") ?>"/>
+        <input type="submit" name="l10n-edit-clear" value="<?= t("Clear") ?>"/>
+  */
+  // TODO: Handle plurals in copy button
+
+  // Copy source text to translation field on button click.
+  $('#g-l10n-client-save-form #l10n-edit-copy').click(function() {
+    $('#g-l10n-client-save-form #l10n-edit-target').val($('#l10n-client-string-editor .source-text').text());
+  });
+
+  // Clear translation field on button click.
+  $('#g-l10n-client-save-form #l10n-edit-clear').click(function() {
+    $('#g-l10n-client-save-form #l10n-edit-target').val('');
+  });
+};
diff --git a/modules/gallery/libraries/Admin_View.php b/modules/gallery/libraries/Admin_View.php
new file mode 100644
index 0000000..62645d1
--- /dev/null
+++ b/modules/gallery/libraries/Admin_View.php
@@ -0,0 +1,120 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_View_Core extends Gallery_View {
+  /**
+   * Attempts to load a view and pre-load view data.
+   *
+   * @throws  Kohana_Exception  if the requested view cannot be found
+   * @param   string  $name view name
+   * @param   string  $theme_name view name
+   * @return  void
+   */
+  public function __construct($name) {
+    parent::__construct($name);
+
+    $this->theme_name = module::get_var("gallery", "active_admin_theme");
+    if (identity::active_user()->admin) {
+      $theme_name = Input::instance()->get("theme");
+      if ($theme_name &&
+          file_exists(THEMEPATH . $theme_name) &&
+          strpos(realpath(THEMEPATH . $theme_name), THEMEPATH) == 0) {
+        $this->theme_name = $theme_name;
+      }
+    }
+    $this->sidebar = "";
+    $this->set_global(array("theme" => $this,
+                            "user" => identity::active_user(),
+                            "page_type" => "admin",
+                            "page_subtype" => $name,
+                            "page_title" => null));
+  }
+
+  public function admin_menu() {
+    $menu = Menu::factory("root");
+    module::event("admin_menu", $menu, $this);
+
+    $settings_menu = $menu->get("settings_menu");
+    uasort($settings_menu->elements, array("Menu", "title_comparator"));
+
+    return $menu->render();
+  }
+
+  public function user_menu() {
+    $menu = Menu::factory("root")
+      ->css_id("g-login-menu")
+      ->css_class("g-inline ui-helper-clear-fix");
+    module::event("user_menu", $menu, $this);
+    return $menu->render();
+  }
+
+  /**
+   * Print out any site wide status information.
+   */
+  public function site_status() {
+    return site_status::get();
+  }
+
+  /**
+   * Print out any messages waiting for this user.
+   */
+  public function messages() {
+    return message::get();
+  }
+
+ /**
+   * Handle all theme functions that insert module content.
+   */
+  public function __call($function, $args) {
+    switch ($function) {
+    case "admin_credits";
+    case "admin_footer":
+    case "admin_header_top":
+    case "admin_header_bottom":
+    case "admin_page_bottom":
+    case "admin_page_top":
+    case "admin_head":
+    case "body_attributes":
+    case "html_attributes":
+      $blocks = array();
+      foreach (module::active() as $module) {
+        $helper_class = "{$module->name}_theme";
+        if (class_exists($helper_class) && method_exists($helper_class, $function)) {
+          $blocks[] = call_user_func_array(
+            array($helper_class, $function),
+            array_merge(array($this), $args));
+        }
+      }
+
+      if (Session::instance()->get("debug")) {
+        if ($function != "admin_head") {
+          array_unshift(
+            $blocks, "<div class=\"g-annotated-theme-block g-annotated-theme-block_$function\">" .
+            "<div class=\"title\">$function</div>");
+          $blocks[] = "</div>";
+        }
+      }
+
+      return implode("\n", $blocks);
+
+    default:
+      throw new Exception("@todo UNKNOWN_THEME_FUNCTION: $function");
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/Block.php b/modules/gallery/libraries/Block.php
new file mode 100644
index 0000000..818af9c
--- /dev/null
+++ b/modules/gallery/libraries/Block.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Block_Core {
+  public $content = null;
+  public $css_id = null;
+  public $id = null;
+  public $title = null;
+  public $anchor = null;
+
+  public function __toString() {
+    return View::factory("block.html", get_object_vars($this))->__toString();
+  }
+}
diff --git a/modules/gallery/libraries/Breadcrumb.php b/modules/gallery/libraries/Breadcrumb.php
new file mode 100644
index 0000000..3805c5d
--- /dev/null
+++ b/modules/gallery/libraries/Breadcrumb.php
@@ -0,0 +1,70 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Breadcrumb_Core {
+  public $title;
+  public $url;
+  public $first;
+  public $last;
+
+  static function instance($title, $url) {
+    return new Breadcrumb($title, $url);
+  }
+
+  public function __construct($title, $url) {
+    $this->title = $title;
+    $this->url = $url;
+    $this->first = false;
+    $this->last = false;
+  }
+
+  /**
+   * Return an array of Breadcrumb instances build from the parents of a given item.
+   * The first and last Breadcrumb instances will be marked first/last as appropriate.
+   * Each breadcrumb will have a ?show= query parameter that refers to the id of the next
+   * item in line.
+   *
+   * @return array Breadcrumb instances
+   */
+  static function array_from_item_parents($item) {
+    if ($item->id == item::root()->id) {
+      return array();
+    }
+
+    $bc = array_merge($item->parents()->as_array(), array($item));
+    for ($i = 0; $i < count($bc) - 1; $i++) {
+      $bc[$i] = new Breadcrumb($bc[$i]->title, $bc[$i]->url("show={$bc[$i+1]->id}"));
+    }
+    $bc[$i] = new Breadcrumb($item->title, $item->url());
+
+    $bc[0]->set_first();
+    end($bc)->set_last();
+    return $bc;
+  }
+
+  public function set_first() {
+    $this->first = true;
+    return $this;
+  }
+
+  public function set_last() {
+    $this->last = true;
+    return $this;
+  }
+}
diff --git a/modules/gallery/libraries/Form_Script.php b/modules/gallery/libraries/Form_Script.php
new file mode 100644
index 0000000..2b5ec3e
--- /dev/null
+++ b/modules/gallery/libraries/Form_Script.php
@@ -0,0 +1,66 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Form_Script_Core extends Forge {
+  protected $data = array(
+    "name" => false,
+    "type"  => "script",
+    "url" => "",
+    "text" => "");
+
+  public function __construct($name) {
+    // Set dummy data so we don"t get errors
+    $this->attr["action"] = "";
+    $this->attr["method"] = "post";
+    $this->data["name"] = $name;
+  }
+
+  public function __get($key) {
+    return isset($this->data[$key]) ? $this->data[$key] : null;
+  }
+
+  /**
+   * Sets url attribute
+   */
+  public function url($url) {
+    $this->data["url"] = $url;
+
+    return $this;
+  }
+
+  public function text($script_text) {
+    $this->data["text"] = $script_text;
+
+    return $this;
+  }
+
+  public function render($template="forge_template", $custom=false) {
+    $script = array();
+    if (!empty($this->data["url"])) {
+      $script[] = html::script($this->data["url"]);
+    }
+
+    if (!empty($this->data["text"])) {
+      $script[] = "<script type=\"text/javascript\">\n{$this->data['text']}\n</script>\n";
+    }
+
+    return implode("\n", $script);
+  }
+
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/Form_Uploadify.php b/modules/gallery/libraries/Form_Uploadify.php
new file mode 100644
index 0000000..1e58018
--- /dev/null
+++ b/modules/gallery/libraries/Form_Uploadify.php
@@ -0,0 +1,72 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Form_Uploadify_Core extends Form_Input {
+  protected $data = array(
+    "name" => false,
+    "type"  => "UNKNOWN",
+    "url" => "",
+    "text" => "");
+
+  public function __construct($name) {
+    parent::__construct($name);
+    $this->data["script_data"] = array(
+      "g3sid" => Session::instance()->id(),
+      "user_agent" => Input::instance()->server("HTTP_USER_AGENT"),
+      "csrf" => access::csrf_token());
+  }
+
+  public function album(Item_Model $album) {
+    $this->data["album"] = $album;
+    return $this;
+  }
+
+  public function script_data($key, $value) {
+    $this->data["script_data"][$key] = $value;
+  }
+
+  public function render() {
+    $v = new View("form_uploadify.html");
+    $v->album = $this->data["album"];
+    $v->script_data = $this->data["script_data"];
+    $v->simultaneous_upload_limit = module::get_var("gallery", "simultaneous_upload_limit");
+    $v->movies_allowed = movie::allow_uploads();
+    $v->extensions = legal_file::get_filters();
+    $v->suhosin_session_encrypt = (bool) ini_get("suhosin.session.encrypt");
+
+    list ($toolkit_max_filesize_bytes, $toolkit_max_filesize) = graphics::max_filesize();
+
+    $upload_max_filesize = trim(ini_get("upload_max_filesize"));
+    $upload_max_filesize_bytes = num::convert_to_bytes($upload_max_filesize);
+
+    if ($upload_max_filesize_bytes < $toolkit_max_filesize_bytes) {
+      $v->size_limit_bytes = $upload_max_filesize_bytes;
+      $v->size_limit = $upload_max_filesize;
+    } else {
+      $v->size_limit_bytes = $toolkit_max_filesize_bytes;
+      $v->size_limit = $toolkit_max_filesize;
+    }
+
+    return $v;
+  }
+
+  public function validate() {
+    return true;
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/Form_Uploadify_buttons.php b/modules/gallery/libraries/Form_Uploadify_buttons.php
new file mode 100644
index 0000000..2e0327e
--- /dev/null
+++ b/modules/gallery/libraries/Form_Uploadify_buttons.php
@@ -0,0 +1,25 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Form_Uploadify_buttons_Core extends Form_Input {
+  public function render() {
+    $v = new View("form_uploadify_buttons.html");
+    return $v;
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/Gallery_I18n.php b/modules/gallery/libraries/Gallery_I18n.php
new file mode 100644
index 0000000..6b216a2
--- /dev/null
+++ b/modules/gallery/libraries/Gallery_I18n.php
@@ -0,0 +1,472 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * Translates a localizable message.
+ * @param $message String The message to be translated. E.g. "Hello world"
+ * @param $options array (optional) Options array for key value pairs which are used
+ *        for pluralization and interpolation. Special key: "locale" to override the
+ *        currently configured locale.
+ * @return String The translated message string.
+ */
+function t($message, $options=array()) {
+  return Gallery_I18n::instance()->translate($message, $options);
+}
+
+/**
+ * Translates a localizable message with plural forms.
+ * @param $singular String The message to be translated. E.g. "There is one album."
+ * @param $plural String The plural message to be translated. E.g.
+ *        "There are %count albums."
+ * @param $count Number The number which is inserted for the %count placeholder and
+ *        which is used to select the proper plural form ($singular or $plural).
+ * @param $options array (optional) Options array for key value pairs which are used
+ *        for pluralization and interpolation. Special key: "locale" to override the
+ *        currently configured locale.
+ * @return String The translated message string.
+ */
+function t2($singular, $plural, $count, $options=array()) {
+  return Gallery_I18n::instance()->translate(array("one" => $singular, "other" => $plural),
+                                             array_merge($options, array("count" => $count)));
+}
+
+class Gallery_I18n_Core {
+  private static $_instance;
+  private $_config = array();
+  private $_call_log = array();
+  private $_cache = array();
+
+  private function __construct($config) {
+    $this->_config = $config;
+    $this->locale($config['default_locale']);
+  }
+
+  public static function instance($config=null) {
+    if (self::$_instance == NULL || isset($config)) {
+      $config = isset($config) ? $config : Kohana::config('locale');
+      if (empty($config['default_locale'])) {
+        $config['default_locale'] = module::get_var('gallery', 'default_locale');
+      }
+      self::$_instance = new Gallery_I18n_Core($config);
+    }
+
+    return self::$_instance;
+  }
+
+  public function locale($locale=null) {
+    if ($locale) {
+      $this->_config['default_locale'] = $locale;
+      $php_locale = setlocale(LC_ALL, 0);
+      list ($php_locale, $unused) = explode('.', $php_locale . '.');
+      if ($php_locale != $locale) {
+        // Attempt to set PHP's locale as well (for number formatting, collation, etc.)
+        $locale_prefs = array($locale);
+        // Try appending some character set names; some systems (like FreeBSD) need this.
+        // Some systems require a format with hyphen (eg. Gentoo) and others without (eg. FreeBSD).
+        $charsets = array('utf8', 'UTF-8', 'UTF8', 'ISO8859-1', 'ISO-8859-1');
+        if (substr($locale, 0, 2) != 'en') {
+          $charsets = array_merge($charsets, array(
+              'EUC', 'Big5', 'euc', 'ISO8859-2', 'ISO8859-5', 'ISO8859-7',
+              'ISO8859-9', 'ISO-8859-2', 'ISO-8859-5', 'ISO-8859-7', 'ISO-8859-9'));
+        }
+        foreach ($charsets as $charset) {
+          $locale_prefs[] = $locale . '.' . $charset;
+        }
+        $locale_prefs[] = 'en_US';
+        $php_locale = setlocale(LC_ALL, $locale_prefs);
+      }
+      if (is_string($php_locale) && substr($php_locale, 0, 2) == 'tr') {
+        // Make PHP 5 work with Turkish (the localization results are mixed though).
+        // Hack for http://bugs.php.net/18556
+        setlocale(LC_CTYPE, 'C');
+      }
+    }
+    return $this->_config['default_locale'];
+  }
+
+  public function is_rtl($locale=null) {
+    $is_rtl = !empty($this->_config["force_rtl"]);
+    if (empty($is_rtl)) {
+      $locale or $locale = $this->locale();
+      list ($language, $territory) = explode('_', $locale . "_");
+      $is_rtl = in_array($language, array("he", "fa", "ar"));
+    }
+    return $is_rtl;
+  }
+
+  /**
+   * Translates a localizable message.
+   *
+   * Security:
+   * The returned string is safe for use in HTML (it contains a safe subset of HTML and
+   * interpolation parameters are converted to HTML entities).
+   * For use in JavaScript, please call ->for_js() on it.
+   *
+   * @param $message String|array The message to be translated. E.g. "Hello world"
+   *                 or array("one" => "One album", "other" => "%count albums")
+   * @param $options array (optional) Options array for key value pairs which are used
+   *        for pluralization and interpolation. Special keys are "count" and "locale",
+   *        the latter to override the currently configured locale.
+   * @return String The translated message string.
+   */
+  public function translate($message, $options=array()) {
+    $locale = empty($options['locale']) ? $this->_config['default_locale'] : $options['locale'];
+    $count = isset($options['count']) ? $options['count'] : null;
+    $values = $options;
+    unset($values['locale']);
+    $this->log($message, $options);
+
+    $entry = $this->lookup($locale, $message);
+
+    if (null === $entry) {
+      // Default to the root locale.
+      $entry = $message;
+      $locale = $this->_config['root_locale'];
+    }
+
+    $entry = $this->pluralize($locale, $entry, $count);
+
+    $entry = $this->interpolate($locale, $entry, $values);
+
+    return SafeString::of_safe_html($entry);
+  }
+
+  private function lookup($locale, $message) {
+    if (!isset($this->_cache[$locale])) {
+      $this->_cache[$locale] = self::load_translations($locale);
+    }
+
+    $key = self::get_message_key($message);
+
+    if (isset($this->_cache[$locale][$key])) {
+      return $this->_cache[$locale][$key];
+    } else {
+      return null;
+    }
+  }
+
+  private static function load_translations($locale) {
+    $cache_key = "translation|" . $locale;
+    $cache = Cache::instance();
+    $translations = $cache->get($cache_key);
+    if (!isset($translations) || !is_array($translations)) {
+      $translations = array();
+      foreach (db::build()
+               ->select("key", "translation")
+               ->from("incoming_translations")
+               ->where("locale", "=", $locale)
+               ->execute() as $row) {
+        $translations[$row->key] = unserialize($row->translation);
+      }
+
+      // Override incoming with outgoing...
+      foreach (db::build()
+               ->select("key", "translation")
+               ->from("outgoing_translations")
+               ->where("locale", "=", $locale)
+               ->execute() as $row) {
+        $translations[$row->key] = unserialize($row->translation);
+      }
+
+      $cache->set($cache_key, $translations, array("translation"), 0);
+    }
+    return $translations;
+  }
+
+  public function has_translation($message, $options=null) {
+    $locale = empty($options['locale']) ? $this->_config['default_locale'] : $options['locale'];
+
+    $entry = $this->lookup($locale, $message);
+
+    if (null === $entry) {
+      return false;
+    } else if (!is_array($message)) {
+      return $entry !== '';
+    } else {
+      if (!is_array($entry) || empty($entry)) {
+        return false;
+      }
+      // It would be better to verify that all the locale's plural forms have a non-empty
+      // translation, but this is fine for now.
+      foreach ($entry as $value) {
+        if ($value === '') {
+          return false;
+        }
+      }
+      return true;
+    }
+  }
+
+  static function get_message_key($message) {
+    $as_string = is_array($message) ? implode('|', $message) : $message;
+    return md5($as_string);
+  }
+
+  static function is_plural_message($message) {
+    return is_array($message);
+  }
+
+  private function interpolate($locale, $string, $key_values) {
+    // TODO: Handle locale specific number formatting.
+
+    // Replace x_y before replacing x.
+    krsort($key_values, SORT_STRING);
+
+    $keys = array();
+    $values = array();
+    foreach ($key_values as $key => $value) {
+      $keys[] = "%$key";
+      $values[] = new SafeString($value);
+    }
+    return str_replace($keys, $values, $string);
+  }
+
+  private function pluralize($locale, $entry, $count) {
+    if (!is_array($entry)) {
+      return $entry;
+    }
+
+    $plural_key = self::get_plural_key($locale, $count);
+    if (!isset($entry[$plural_key])) {
+      // Fallback to the default plural form.
+      $plural_key = 'other';
+    }
+
+    if (isset($entry[$plural_key])) {
+      return $entry[$plural_key];
+    } else {
+      // Fallback to just any plural form.
+      list ($plural_key, $string) = each($entry);
+      return $string;
+    }
+  }
+
+  private function log($message, $options) {
+    $key = self::get_message_key($message);
+    isset($this->_call_log[$key]) or $this->_call_log[$key] = array($message, $options);
+  }
+
+  public function call_log() {
+    return $this->_call_log;
+  }
+
+  public static function clear_cache($locale=null) {
+    $cache = Cache::instance();
+    if ($locale) {
+      $cache->delete("translation|" . $locale);
+    } else {
+      $cache->delete_tag("translation");
+    }
+  }
+
+  private static function get_plural_key($locale, $count) {
+    $parts = explode('_', $locale);
+    $language = $parts[0];
+
+    // Data from CLDR 1.6 (http://unicode.org/cldr/data/common/supplemental/plurals.xml).
+    // Docs: http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html
+    switch ($language) {
+      case 'az':
+      case 'fa':
+      case 'hu':
+      case 'ja':
+      case 'ko':
+      case 'my':
+      case 'to':
+      case 'tr':
+      case 'vi':
+      case 'yo':
+      case 'zh':
+      case 'bo':
+      case 'dz':
+      case 'id':
+      case 'jv':
+      case 'ka':
+      case 'km':
+      case 'kn':
+      case 'ms':
+      case 'th':
+        return 'other';
+
+      case 'ar':
+        if ($count == 0) {
+          return 'zero';
+        } else if ($count == 1) {
+          return 'one';
+        } else if ($count == 2) {
+          return 'two';
+        } else if (is_int($count) && ($i = $count % 100) >= 3 && $i <= 10) {
+          return 'few';
+        } else if (is_int($count) && ($i = $count % 100) >= 11 && $i <= 99) {
+          return 'many';
+        } else {
+          return 'other';
+        }
+
+      case 'pt':
+      case 'am':
+      case 'bh':
+      case 'fil':
+      case 'tl':
+      case 'guw':
+      case 'hi':
+      case 'ln':
+      case 'mg':
+      case 'nso':
+      case 'ti':
+      case 'wa':
+        if ($count == 0 || $count == 1) {
+          return 'one';
+        } else {
+          return 'other';
+        }
+
+      case 'fr':
+        if ($count >= 0 and $count < 2) {
+          return 'one';
+        } else {
+          return 'other';
+        }
+
+      case 'lv':
+        if ($count == 0) {
+          return 'zero';
+        } else if ($count % 10 == 1 && $count % 100 != 11) {
+          return 'one';
+        } else {
+          return 'other';
+        }
+
+      case 'ga':
+      case 'se':
+      case 'sma':
+      case 'smi':
+      case 'smj':
+      case 'smn':
+      case 'sms':
+        if ($count == 1) {
+          return 'one';
+        } else if ($count == 2) {
+          return 'two';
+        } else {
+          return 'other';
+        }
+
+      case 'ro':
+      case 'mo':
+        if ($count == 1) {
+          return 'one';
+        } else if (is_int($count) && $count == 0 && ($i = $count % 100) >= 1 && $i <= 19) {
+          return 'few';
+        } else {
+          return 'other';
+        }
+
+      case 'lt':
+        if (is_int($count) && $count % 10 == 1 && $count % 100 != 11) {
+          return 'one';
+        } else if (is_int($count) && ($i = $count % 10) >= 2 && $i <= 9 && ($i = $count % 100) < 11 && $i > 19) {
+          return 'few';
+        } else {
+          return 'other';
+        }
+
+      case 'hr':
+      case 'ru':
+      case 'sr':
+      case 'uk':
+      case 'be':
+      case 'bs':
+      case 'sh':
+        if (is_int($count) && $count % 10 == 1 && $count % 100 != 11) {
+          return 'one';
+        } else if (is_int($count) && ($i = $count % 10) >= 2 && $i <= 4 && ($i = $count % 100) < 12 && $i > 14) {
+          return 'few';
+        } else if (is_int($count) && ($count % 10 == 0 || (($i = $count % 10) >= 5 && $i <= 9) || (($i = $count % 100) >= 11 && $i <= 14))) {
+          return 'many';
+        } else {
+          return 'other';
+        }
+
+      case 'cs':
+      case 'sk':
+        if ($count == 1) {
+          return 'one';
+        } else if (is_int($count) && $count >= 2 && $count <= 4) {
+          return 'few';
+        } else {
+          return 'other';
+        }
+
+      case 'pl':
+        if ($count == 1) {
+          return 'one';
+        } else if (is_int($count) && ($i = $count % 10) >= 2 && $i <= 4 &&
+                   ($i = $count % 100) < 12 && $i > 14 && ($i = $count % 100) < 22 && $i > 24) {
+          return 'few';
+        } else {
+          return 'other';
+        }
+
+      case 'sl':
+        if ($count % 100 == 1) {
+          return 'one';
+        } else if ($count % 100 == 2) {
+          return 'two';
+        } else if (is_int($count) && ($i = $count % 100) >= 3 && $i <= 4) {
+          return 'few';
+        } else {
+          return 'other';
+        }
+
+      case 'mt':
+        if ($count == 1) {
+          return 'one';
+        } else if ($count == 0 || is_int($count) && ($i = $count % 100) >= 2 && $i <= 10) {
+          return 'few';
+        } else if (is_int($count) && ($i = $count % 100) >= 11 && $i <= 19) {
+          return 'many';
+        } else {
+          return 'other';
+        }
+
+      case 'mk':
+        if ($count % 10 == 1) {
+          return 'one';
+        } else {
+          return 'other';
+        }
+
+      case 'cy':
+        if ($count == 1) {
+          return 'one';
+        } else if ($count == 2) {
+          return 'two';
+        } else if ($count == 8 || $count == 11) {
+          return 'many';
+        } else {
+          return 'other';
+        }
+
+      default: // en, de, etc.
+        return $count == 1 ? 'one' : 'other';
+    }
+  }
+}
diff --git a/modules/gallery/libraries/Gallery_View.php b/modules/gallery/libraries/Gallery_View.php
new file mode 100644
index 0000000..8f02b53
--- /dev/null
+++ b/modules/gallery/libraries/Gallery_View.php
@@ -0,0 +1,243 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Gallery_View_Core extends View {
+  protected $theme_name = null;
+  protected $combine_queue = array();
+
+  /**
+   * Provide a url to a resource within the current theme.  This allows us to refer to theme
+   * resources without naming the theme itself which makes themes easier to copy.
+   */
+  public function url($path, $absolute_url=false) {
+    $arg = "themes/{$this->theme_name}/$path";
+    return $absolute_url ? url::abs_file($arg) : url::file($arg);
+  }
+
+  /**
+   * Set up the data and render a pager.
+   *
+   * See themes/wind/views/pager.html for documentation on the variables generated here.
+   */
+  public function paginator() {
+    $v = new View("paginator.html");
+    $v->page_type = $this->page_type;
+    $v->page_subtype = $this->page_subtype;
+    $v->first_page_url = null;
+    $v->previous_page_url = null;
+    $v->next_page_url = null;
+    $v->last_page_url = null;
+
+    if ($this->page_type == "collection") {
+      $v->page = $this->page;
+      $v->max_pages = $this->max_pages;
+      $v->total = $this->children_count;
+
+      if ($this->page != 1) {
+        $v->first_page_url = url::site(url::merge(array("page" => 1)));
+        $v->previous_page_url = url::site(url::merge(array("page" => $this->page - 1)));
+      }
+
+      if ($this->page != $this->max_pages) {
+        $v->next_page_url = url::site(url::merge(array("page" => $this->page + 1)));
+        $v->last_page_url = url::site(url::merge(array("page" => $this->max_pages)));
+      }
+
+      $v->first_visible_position = ($this->page - 1) * $this->page_size + 1;
+      $v->last_visible_position = min($this->page * $this->page_size, $v->total);
+    } else if ($this->page_type == "item") {
+      $v->position = $this->position;
+      $v->total = $this->sibling_count;
+      if ($this->previous_item) {
+        $v->previous_page_url = $this->previous_item->url();
+      }
+
+      if ($this->next_item) {
+        $v->next_page_url = $this->next_item->url();
+      }
+    }
+
+    return $v;
+  }
+
+  /**
+   * Begin gather up scripts or css files so that they can be combined into a single request.
+   *
+   * @param $types  a comma separated list of types to combine, eg "script,css"
+   */
+  public function start_combining($types) {
+    if (gallery::allow_css_and_js_combining()) {
+      foreach (explode(",", $types) as $type) {
+        $this->combine_queue[$type] = array();
+      }
+    }
+  }
+
+  /**
+   * If script combining is enabled, add this script to the list of scripts that will be
+   * combined into a single script element.  When combined, the order of scripts is preserved.
+   *
+   * @param $file  the file name or path of the script to include. If a path is specified then
+   *               it needs to be relative to DOCROOT. Just specifying a file name will result
+   *               in searching Kohana's cascading file system.
+   * @param $group the group of scripts to combine this with.  defaults to "core"
+   */
+  public function script($file, $group="core") {
+    if (($path = gallery::find_file("js", $file, false))) {
+      if (isset($this->combine_queue["script"])) {
+        $this->combine_queue["script"][$group][$path] = 1;
+      } else {
+        return html::script($path);
+      }
+    } else {
+      Kohana_Log::add("error", "Can't find script file: $file");
+    }
+  }
+
+  /**
+   * If css combining is enabled, add this css to the list of css that will be
+   * combined into a single style element.  When combined, the order of style elements
+   * is preserved.
+   *
+   * @param $file  the file name or path of the css to include. If a path is specified then
+   *               it needs to be relative to DOCROOT. Just specifying a file name will result
+   *               in searching Kohana's cascading file system.
+   * @param $group the group of css to combine this with.  defaults to "core"
+   */
+  public function css($file, $group="core") {
+    if (($path = gallery::find_file("css", $file, false))) {
+      if (isset($this->combine_queue["css"])) {
+        $this->combine_queue["css"][$group][$path] = 1;
+      } else {
+        return html::stylesheet($path);
+      }
+    } else {
+      Kohana_Log::add("error", "Can't find css file: $file");
+    }
+  }
+
+  /**
+   * Combine a series of files into a single one and cache it in the database.
+   * @param $type  the data type (script or css)
+   * @param $group the group of scripts or css we want
+   */
+  public function get_combined($type, $group="core") {
+    $links = array();
+
+    if (empty($this->combine_queue[$type][$group])) {
+      return;
+    }
+
+    // Include the url in the cache key so that if the Gallery moves, we don't use old cached
+    // entries.
+    $key = array(url::abs_file(""));
+
+    foreach (array_keys($this->combine_queue[$type][$group]) as $path) {
+      $stats = stat($path);
+      // 7 == size, 9 == mtime, see http://php.net/stat
+      $key[] = "$path $stats[7] $stats[9]";
+    }
+
+    $key = md5(join(" ", $key));
+    $cache = Cache::instance();
+    $contents = $cache->get($key);
+
+    if (empty($contents)) {
+      $combine_data = new stdClass();
+      $combine_data->type = $type;
+      $combine_data->contents = $this->combine_queue[$type][$group];
+      module::event("before_combine", $combine_data);
+
+      $contents = "";
+      foreach (array_keys($this->combine_queue[$type][$group]) as $path) {
+        if ($type == "css") {
+          $contents .= "/* $path */\n" . $this->process_css($path) . "\n";
+        } else {
+          $contents .= "/* $path */\n" . file_get_contents($path) . "\n";
+        }
+      }
+
+      $combine_data = new stdClass();
+      $combine_data->type = $type;
+      $combine_data->contents = $contents;
+      module::event("after_combine", $combine_data);
+
+      $cache->set($key, $combine_data->contents, array($type), 30 * 84600);
+
+      $use_gzip = function_exists("gzencode") &&
+        (int) ini_get("zlib.output_compression") === 0;
+      if ($use_gzip) {
+        $cache->set("{$key}_gz", gzencode($combine_data->contents, 9, FORCE_GZIP),
+                    array($type, "gzip"), 30 * 84600);
+      }
+
+    }
+
+    unset($this->combine_queue[$type][$group]);
+    if (empty($this->combine_queue[$type])) {
+      unset($this->combine_queue[$type]);
+    }
+
+    if ($type == "css") {
+      return html::stylesheet("combined/css/$key", "screen,print,projection", true);
+    } else {
+      return html::script("combined/javascript/$key", true);
+    }
+  }
+
+  /**
+   * Convert relative references inside a CSS file to absolute ones so that when it's served from
+   * a new location as part of a combined bundle the references are still correct.
+   * @param string  the path to the css file
+   */
+  private function process_css($css_file) {
+    static $PATTERN = "#url\(\s*['|\"]{0,1}(.*?)['|\"]{0,1}\s*\)#";
+    $docroot_length = strlen(DOCROOT);
+
+    $css = file_get_contents($css_file);
+    if (preg_match_all($PATTERN, $css, $matches, PREG_SET_ORDER)) {
+      $search = $replace = array();
+      foreach ($matches as $match) {
+        $relative = dirname($css_file) . "/$match[1]";
+        if (!empty($relative)) {
+          $search[] = $match[0];
+          $replace[] = "url('" . url::abs_file($relative) . "')";
+        } else {
+          Kohana_Log::add("error", "Missing URL reference '{$match[1]}' in CSS file '$css_file'");
+
+        }
+      }
+      $replace = str_replace(DIRECTORY_SEPARATOR, "/", $replace);
+      $css = str_replace($search, $replace, $css);
+    }
+    $imports = preg_match_all("#@import\s*['|\"]{0,1}(.*?)['|\"]{0,1};#",
+                              $css, $matches, PREG_SET_ORDER);
+
+    if ($imports) {
+      $search = $replace = array();
+      foreach ($matches as $match) {
+        $search[] = $match[0];
+        $replace[] = $this->process_css(dirname($css_file) . "/$match[1]");
+      }
+      $css = str_replace($search, $replace, $css);
+    }
+
+    return $css;
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/IdentityProvider.php b/modules/gallery/libraries/IdentityProvider.php
new file mode 100644
index 0000000..525e169
--- /dev/null
+++ b/modules/gallery/libraries/IdentityProvider.php
@@ -0,0 +1,283 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * Provides a driver-based interface for managing users and groups.
+ */
+class IdentityProvider_Core {
+  protected static $instance;
+
+  // Configuration
+  protected $config;
+
+  // Driver object
+  protected $driver;
+
+  /**
+   * Returns a singleton instance of Identity.
+   * There can only be one Identity driver configured at a given point
+   *
+   * @param   string  configuration
+   * @return  Identity_Core
+   */
+  static function &instance() {
+   if (empty(self::$instance)) {
+      // Create a new instance
+      self::$instance = new IdentityProvider();
+    }
+
+    return self::$instance;
+  }
+
+  /**
+   * Frees the current instance of the identity provider so the next call to instance will reload
+   *
+   * @param   string  configuration
+   * @return  Identity_Core
+   */
+  static function reset() {
+    self::$instance = null;
+    Kohana_Config::instance()->clear("identity");
+  }
+
+  /**
+   * Return a commen confirmation message
+   */
+  static function confirmation_message() {
+    return t("Are you sure you want to change your Identity Provider? Continuing will delete all existing users.");
+  }
+
+  static function change_provider($new_provider) {
+    if (!identity::active_user()->admin && PHP_SAPI != "cli") {
+      // Below, the active user is set to the primary admin.
+      access::forbidden();
+    }
+
+    $current_provider = module::get_var("gallery", "identity_provider");
+    if (!empty($current_provider)) {
+      module::uninstall($current_provider);
+    }
+
+    try {
+      IdentityProvider::reset();
+      $provider = new IdentityProvider($new_provider);
+
+      module::set_var("gallery", "identity_provider", $new_provider);
+
+      if (class_exists("{$new_provider}_installer") &&
+          method_exists("{$new_provider}_installer", "initialize")) {
+        call_user_func("{$new_provider}_installer::initialize");
+      }
+
+      if (!$provider->admin_user()) {
+        throw new Exception("IdentityProvider $new_provider: Couldn't find the admin user!");
+      }
+
+      module::event("identity_provider_changed", $current_provider, $new_provider);
+
+      identity::set_active_user($provider->admin_user());
+      Session::instance()->regenerate();
+    } catch (Exception $e) {
+      static $restore_already_running;
+
+      // In case of error, make an attempt to restore the old provider.  Since that's calling into
+      // this function again and can fail, we should be sure not to get into an infinite recursion.
+      if (!$restore_already_running) {
+        $restore_already_running = true;
+
+        // Make sure new provider is not in the database
+        try {
+          module::uninstall($new_provider);
+        } catch (Exception $e2) {
+          Kohana_Log::add("error", "Error uninstalling failed new provider\n" .
+                          $e2->getMessage() . "\n" . $e2->getTraceAsString());
+        }
+
+        try {
+          // Lets reset to the current provider so that the gallery installation is still
+          // working.
+          module::set_var("gallery", "identity_provider", null);
+          IdentityProvider::change_provider($current_provider);
+          module::activate($current_provider);
+        } catch (Exception $e2) {
+          Kohana_Log::add("error", "Error restoring original identity provider\n" .
+                          $e2->getMessage() . "\n" . $e2->getTraceAsString());
+        }
+
+        message::error(
+          t("Error attempting to enable \"%new_provider\" identity provider, reverted to \"%old_provider\" identity provider",
+            array("new_provider" => $new_provider, "old_provider" => $current_provider)));
+
+        $restore_already_running = false;
+      }
+      throw $e;
+    }
+  }
+
+  /**
+   * Loads the configured driver and validates it.
+   *
+   * @return  void
+   */
+  public function __construct($config=null) {
+    if (empty($config)) {
+      $config = module::get_var("gallery", "identity_provider", "user");
+    }
+
+    // Test the config group name
+    if (($this->config = Kohana::config("identity." . $config)) === NULL) {
+      throw new Exception("@todo NO_USER_LIBRARY_CONFIGURATION_FOR: $config");
+    }
+
+    // Set driver name
+    $driver = "IdentityProvider_" . ucfirst($this->config["driver"])  ."_Driver";
+
+    // Load the driver
+    if ( ! Kohana::auto_load($driver)) {
+      throw new Kohana_Exception("core.driver_not_found", $this->config["driver"],
+                                 get_class($this));
+    }
+
+    // Initialize the driver
+    $this->driver = new $driver($this->config["params"]);
+
+    // Validate the driver
+    if ( !($this->driver instanceof IdentityProvider_Driver)) {
+      throw new Kohana_Exception("core.driver_implements", $this->config["driver"],
+                                 get_class($this), "IdentityProvider_Driver");
+    }
+
+    Kohana_Log::add("debug", "Identity Library initialized");
+  }
+
+  /**
+   * Determine if if the current driver supports updates.
+   *
+   * @return boolean true if the driver supports updates; false if read only
+   */
+  public function is_writable() {
+    return !empty($this->config["allow_updates"]);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::guest.
+   */
+  public function guest() {
+    return $this->driver->guest();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::admin_user.
+   */
+  public function admin_user() {
+    return $this->driver->admin_user();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::create_user.
+   */
+  public function create_user($name, $full_name, $password, $email) {
+    return $this->driver->create_user($name, $full_name, $password, $email);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::is_correct_password.
+   */
+  public function is_correct_password($user, $password) {
+    return $this->driver->is_correct_password($user, $password);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_user.
+   */
+  public function lookup_user($id) {
+    return $this->driver->lookup_user($id);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_user_by_name.
+   */
+  public function lookup_user_by_name($name) {
+    return $this->driver->lookup_user_by_name($name);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::create_group.
+   */
+  public function create_group($name) {
+    return $this->driver->create_group($name);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::everybody.
+   */
+  public function everybody() {
+    return $this->driver->everybody();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::registered_users.
+   */
+  public function registered_users() {
+    return $this->driver->registered_users();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_group.
+   */
+  public function lookup_group($id) {
+    return $this->driver->lookup_group($id);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_group_by_name.
+   */
+  public function lookup_group_by_name($name) {
+    return $this->driver->lookup_group_by_name($name);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::get_user_list.
+   */
+  public function get_user_list($ids) {
+    return $this->driver->get_user_list($ids);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::groups.
+   */
+  public function groups() {
+    return $this->driver->groups();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::add_user_to_group.
+   */
+  public function add_user_to_group($user, $group) {
+    return $this->driver->add_user_to_group($user, $group);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::remove_user_to_group.
+   */
+  public function remove_user_from_group($user, $group) {
+    return $this->driver->remove_user_from_group($user, $group);
+  }
+} // End Identity
diff --git a/modules/gallery/libraries/InPlaceEdit.php b/modules/gallery/libraries/InPlaceEdit.php
new file mode 100644
index 0000000..cd177c2
--- /dev/null
+++ b/modules/gallery/libraries/InPlaceEdit.php
@@ -0,0 +1,91 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class InPlaceEdit_Core {
+  private $rules = array();
+  private $messages = array();
+  private $callback = array();
+  private $initial_value;
+  private $action = "";
+  private $errors;
+  private $form;
+
+  static function factory($initial_value) {
+    $instance = new InPlaceEdit();
+    $instance->initial_value = $initial_value;
+    $instance->form = array("input" => $initial_value);
+    $instance->errors = array("input" => "");
+
+    return $instance;
+  }
+
+  public function action($action) {
+    $this->action = $action;
+    return $this;
+  }
+
+  public function rules($rules) {
+    $this->rules += $rules;
+    return $this;
+  }
+
+  public function messages($messages) {
+    $this->messages += $messages;
+    return $this;
+  }
+
+  public function callback($callback) {
+    $this->callback = $callback;
+    return $this;
+  }
+
+  public function validate() {
+    $post = Validation::factory($_POST);
+
+    if (!empty($this->callback)) {
+      $post->add_callbacks("input", $this->callback);
+    }
+
+    foreach ($this->rules as $rule) {
+      $post->add_rules("input", $rule);
+    }
+
+    $valid = $post->validate();
+    $this->form = array_merge($this->form, $post->as_array());
+    $this->errors = array_merge($this->errors, $post->errors());
+    return $valid;
+  }
+
+  public function render() {
+    $v = new View("in_place_edit.html");
+    $v->action = $this->action;
+    $v->form = $this->form;
+    $v->errors = $this->errors;
+    foreach ($v->errors as $key => $error) {
+      if (!empty($error)) {
+        $v->errors[$key] = $this->messages[$error];
+      }
+    }
+    return $v->render();
+  }
+
+  public function value() {
+    return $this->form["input"];
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/MY_Database.php b/modules/gallery/libraries/MY_Database.php
new file mode 100644
index 0000000..33759b6
--- /dev/null
+++ b/modules/gallery/libraries/MY_Database.php
@@ -0,0 +1,101 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+abstract class Database extends Database_Core {
+  protected $_table_names;
+
+  /**
+   * Kohana 2.4 introduces a new connection parameter.  If it's not specified, make sure that we
+   * define it here to avoid an error later on.
+   *
+   * @todo: add an upgrade path to modify var/database.php so that we can avoid doing this at
+   *        runtime.
+   */
+  protected function __construct(array $config) {
+    if (!isset($config["connection"]["params"])) {
+      $config["connection"]["params"] = null;
+    }
+    parent::__construct($config);
+    if (gallery::show_profiler()) {
+      $this->config['benchmark'] = true;
+    }
+  }
+
+  /**
+   * Parse the query string and convert any strings of the form `\([a-zA-Z0-9_]*?)\]
+   * table prefix . $1
+   */
+  public function query($sql) {
+    if (!empty($sql)) {
+      $sql = $this->add_table_prefixes($sql);
+    }
+    return parent::query($sql);
+  }
+
+  public function add_table_prefixes($sql) {
+    $prefix = $this->config["table_prefix"];
+    if (strpos($sql, "SHOW TABLES") === 0) {
+      /*
+       * Don't ignore "show tables", otherwise we could have a infinite
+       * @todo this may have to be changed if we support more than mysql
+       */
+      return $sql;
+    } else if (strpos($sql, "CREATE TABLE") === 0) {
+      // Creating a new table; add it to the table cache.
+      $open_brace = strpos($sql, "{") + 1;
+      $close_brace = strpos($sql, "}", $open_brace);
+      $name = substr($sql, $open_brace, $close_brace - $open_brace);
+      $this->_table_names["{{$name}}"] = "`{$prefix}$name`";
+    } else if (strpos($sql, "RENAME TABLE") === 0) {
+      // Renaming a table; add it to the table cache.
+      // You must use the form "TO {new_table_name}" exactly for this to work.
+      $open_brace = strpos($sql, "TO {") + 4;
+      $close_brace = strpos($sql, "}", $open_brace);
+      $name = substr($sql, $open_brace, $close_brace - $open_brace);
+      $this->_table_names["{{$name}}"] = "`{$prefix}$name`";
+    }
+
+    if (!isset($this->_table_names)) {
+      // This should only run once on the first query
+      $this->_table_names = array();
+      foreach($this->list_tables() as $table_name) {
+        $this->_table_names["{{$table_name}}"] = "`{$prefix}{$table_name}`";
+      }
+    }
+
+    return strtr($sql, $this->_table_names);
+  }
+
+  /**
+   * This is used by the unit test code to switch the active database connection.
+   */
+  static function set_default_instance($db) {
+    self::$instances["default"] = $db;
+  }
+
+  /**
+   * Escape LIKE queries, add wildcards.  In MySQL queries using LIKE, _ and % characters are
+   * treated as wildcards similar to ? and *, respectively.  Therefore, we need to escape _, %,
+   * and \ (the escape character itself).
+   */
+  static function escape_for_like($value) {
+    // backslash must go first to avoid double-escaping
+    return addcslashes($value, '\_%');
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/MY_Forge.php b/modules/gallery/libraries/MY_Forge.php
new file mode 100644
index 0000000..635dc2d
--- /dev/null
+++ b/modules/gallery/libraries/MY_Forge.php
@@ -0,0 +1,45 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class Forge extends Forge_Core {
+  /**
+   * Force a CSRF element into every form.
+   */
+  public function __construct($action=null, $title='', $method=null, $attr=array()) {
+    parent::__construct($action, $title, $method, $attr);
+    $this->hidden("csrf")->value(access::csrf_token());
+  }
+
+  /**
+   * Use our own template
+   */
+  public function render($template="form.html", $custom=false) {
+    return parent::render($template, $custom);
+  }
+
+  /**
+   * Validate our CSRF value as a mandatory part of all form validation.
+   */
+  public function validate() {
+    $status = parent::validate();
+    access::verify_csrf();
+    return $status;
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/MY_Input.php b/modules/gallery/libraries/MY_Input.php
new file mode 100644
index 0000000..2f0a727
--- /dev/null
+++ b/modules/gallery/libraries/MY_Input.php
@@ -0,0 +1,31 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Input extends Input_Core {
+  /**
+   * Modified form of Input::clean_input_keys() that replaces malformed values
+   * instead of dying on bad input.
+   *
+   * @param   string  string to clean
+   * @return  string
+   */
+  public function clean_input_keys($str) {
+    return preg_replace('#[^a-zA-Z0-9:_.-]+#', '_', $str);
+  }
+}
diff --git a/modules/gallery/libraries/MY_Kohana_Exception.php b/modules/gallery/libraries/MY_Kohana_Exception.php
new file mode 100644
index 0000000..51490a6
--- /dev/null
+++ b/modules/gallery/libraries/MY_Kohana_Exception.php
@@ -0,0 +1,101 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Kohana_Exception extends Kohana_Exception_Core {
+  /**
+   * Dump out the full stack trace as part of the text representation of the exception.
+   */
+  public static function text($e) {
+    if ($e instanceof Kohana_404_Exception) {
+      return "File not found: " . rawurlencode(Router::$complete_uri);
+    } else {
+      return sprintf(
+        "%s [ %s ]: %s\n%s [ %s ]\n%s",
+        get_class($e), $e->getCode(), strip_tags($e->getMessage()),
+        $e->getFile(), $e->getLine(),
+        $e->getTraceAsString());
+    }
+  }
+
+  /**
+   * @see Kohana_Exception::dump()
+   */
+  public static function dump($value, $length=128, $max_level=5) {
+    return self::safe_dump($value, null, $length, $max_level);
+  }
+
+  /**
+   * A safer version of dump(), eliding sensitive information in the dumped
+   * data, such as session ids and passwords / hashes.
+   */
+  public static function safe_dump($value, $key, $length=128, $max_level=5) {
+    return parent::dump(self::_sanitize_for_dump($value, $key, $max_level), $length, $max_level);
+  }
+
+  /**
+   * Elides sensitive data which shouldn't be echoed to the client,
+   * such as passwords, and other secrets.
+   */
+  /* Visible for testing*/ static function _sanitize_for_dump($value, $key=null, $max_level) {
+    // Better elide too much than letting something through.
+    // Note: unanchored match is intended.
+    if (!$max_level) {
+      // Too much recursion; give up.  We gave it our best shot.
+      return $value;
+    }
+
+    $sensitive_info_pattern =
+      '/(password|pass|email|hash|private_key|session_id|session|g3sid|csrf|secret)/i';
+    if (preg_match($sensitive_info_pattern, $key) ||
+        (is_string($value) && preg_match('/[a-f0-9]{20,}/i', $value))) {
+      return 'removed for display';
+    } else if (is_object($value)) {
+      if ($value instanceof Database) {
+        // Elide database password, host, name, user, etc.
+        return get_class($value) . ' object - details omitted for display';
+      } else if ($value instanceof User_Model) {
+        return get_class($value) . ' object for "' . $value->name . '" - details omitted for display';
+      }
+      return self::_sanitize_for_dump((array) $value, $key, $max_level - 1);
+    } else if (is_array($value)) {
+      $result = array();
+      foreach ($value as $k => $v) {
+        $actual_key = $k;
+        $key_for_display = $k;
+        if ($k[0] === "\x00") {
+          // Remove the access level from the variable name
+          $actual_key = substr($k, strrpos($k, "\x00") + 1);
+          $access = $k[1] === '*' ? 'protected' : 'private';
+          $key_for_display = "$access: $actual_key";
+        }
+        if (is_object($v)) {
+          $key_for_display .= ' (type: ' . get_class($v) . ')';
+        }
+        $result[$key_for_display] = self::_sanitize_for_dump($v, $actual_key, $max_level - 1);
+      }
+    } else {
+      $result = $value;
+    }
+    return $result;
+  }
+
+  public static function debug_path($file) {
+    return html::clean(parent::debug_path($file));
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/MY_ORM.php b/modules/gallery/libraries/MY_ORM.php
new file mode 100644
index 0000000..6e538d5
--- /dev/null
+++ b/modules/gallery/libraries/MY_ORM.php
@@ -0,0 +1,52 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class ORM extends ORM_Core {
+
+  /**
+   * Make sure that we're only using integer ids.
+   */
+  static function factory($model, $id=null) {
+    if ($id && !is_int($id) && !is_string($id)) {
+      throw new Exception("@todo ORM::factory requires integer ids");
+    }
+    return ORM_Core::factory($model, (int) $id);
+  }
+
+  public function save() {
+    model_cache::clear();
+    return parent::save();
+  }
+}
+
+/**
+ * Slide this in here for convenience.  We won't ever be overloading ORM_Iterator without ORM.
+ */
+class ORM_Iterator extends ORM_Iterator_Core {
+  /**
+   * Cache the result row
+   */
+  public function current() {
+    $row = parent::current();
+    if (is_object($row)) {
+      model_cache::set($row);
+    }
+    return $row;
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/MY_View.php b/modules/gallery/libraries/MY_View.php
new file mode 100644
index 0000000..1e88611
--- /dev/null
+++ b/modules/gallery/libraries/MY_View.php
@@ -0,0 +1,85 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class View extends View_Core {
+  static $global_data = array();
+
+  /**
+   * Reimplement Kohana 2.3's View::set_global() functionality.
+   */
+  public function set_global($key, $value = NULL) {
+    if (is_array($key)) {
+      foreach ($key as $key2 => $value) {
+        View::$global_data[$key2] = $value;
+      }
+    } else {
+      View::$global_data[$key] = $value;
+    }
+  }
+
+  public function is_set($key=null) {
+    return parent::is_set($key) ? true : array_key_exists($key, View::$global_data);
+  }
+
+  /**
+   * Completely replace View_Core::__get() so that local data trumps global data, trumps members.
+   * This simulates the Kohana 2.3 behavior.
+   */
+  public function &__get($key) {
+    if (isset($this->kohana_local_data[$key])) {
+      return $this->kohana_local_data[$key];
+    } else if (isset(View::$global_data[$key])) {
+      return View::$global_data[$key];
+    } else if (isset($this->$key)) {
+      return $this->$key;
+    } else {
+      throw new Kohana_Exception('Undefined view variable: :var', array(':var' => $key));
+    }
+  }
+
+  /**
+   * Override View_Core::__construct so that we can set the csrf value into all views.
+   *
+   * @see View_Core::__construct
+   */
+  public function __construct($name = NULL, $data = NULL, $type = NULL) {
+    parent::__construct($name, $data, $type);
+    $this->set_global("csrf", access::csrf_token());
+  }
+
+  /**
+   * Override View_Core::render so that we trap errors stemming from bad PHP includes and show a
+   * visible stack trace to help developers.
+   *
+   * @see View_Core::render
+   */
+  public function render($print=false, $renderer=false, $modifier=false) {
+    try {
+      $this->kohana_local_data = array_merge(View::$global_data, $this->kohana_local_data);
+      return parent::render($print, $renderer, $modifier);
+    } catch (ORM_Validation_Exception $e) {
+      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+      Kohana_Log::add("error", "Validation errors: " . print_r($e->validation->errors(), 1));
+      return "";
+    } catch (Exception $e) {
+      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+      return "";
+    }
+  }
+}
diff --git a/modules/gallery/libraries/Menu.php b/modules/gallery/libraries/Menu.php
new file mode 100644
index 0000000..24a05cd
--- /dev/null
+++ b/modules/gallery/libraries/Menu.php
@@ -0,0 +1,257 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Menu_Element {
+  public $label;
+  public $url;
+  public $css_id;
+  public $css_class;
+  public $id;
+  public $type;
+
+  public function __construct($type) {
+    $this->type = $type;
+  }
+
+  /**
+   * Set the id
+   * @chainable
+   */
+  public function id($id) {
+    $this->id = $id;
+    return $this;
+  }
+
+  /**
+   * Set the label
+   * @chainable
+   */
+  public function label($label) {
+    // Guard against developers who forget to internationalize label strings
+    if (!($label instanceof SafeString)) {
+      $label = new SafeString($label);
+    }
+
+    $this->label = $label;
+    return $this;
+  }
+
+  /**
+   * Set the url
+   * @chainable
+   */
+  public function url($url) {
+    $this->url = $url;
+    return $this;
+  }
+
+  /**
+   * Set the css id
+   * @chainable
+   */
+  public function css_id($css_id) {
+    $this->css_id = $css_id;
+    return $this;
+  }
+
+  /**
+   * Set the css class
+   * @chainable
+   */
+  public function css_class($css_class) {
+    $this->css_class = $css_class;
+    return $this;
+  }
+
+  /**
+   * Specifiy a view for this menu item
+   * @chainable
+   */
+  public function view($view) {
+    $this->view = $view;
+    return $this;
+  }
+
+}
+
+/**
+ * Menu element that provides a link to a new page.
+ */
+class Menu_Element_Link extends Menu_Element {
+  public function render() {
+    $view = new View(isset($this->view) ? $this->view : "menu_link.html");
+    $view->menu = $this;
+    return $view;
+  }
+}
+
+/**
+ * Menu element that provides an AJAX link.
+ */
+class Menu_Element_Ajax_Link extends Menu_Element {
+  public $ajax_handler;
+
+  /**
+   * Set the AJAX handler
+   * @chainable
+   */
+  public function ajax_handler($ajax_handler) {
+    $this->ajax_handler = $ajax_handler;
+    return $this;
+  }
+
+  public function render() {
+    $view = new View(isset($this->view) ? $this->view : "menu_ajax_link.html");
+    $view->menu = $this;
+    return $view;
+  }
+}
+
+/**
+ * Menu element that provides a pop-up dialog
+ */
+class Menu_Element_Dialog extends Menu_Element {
+  public function render() {
+    $view = new View(isset($this->view) ? $this->view : "menu_dialog.html");
+    $view->menu = $this;
+    return $view;
+  }
+}
+
+/**
+ * Root menu or submenu
+ */
+class Menu_Core extends Menu_Element {
+  public $elements;
+  public $is_root = false;
+
+  /**
+   * Return an instance of a Menu_Element
+   * @chainable
+   */
+  public static function factory($type) {
+    switch($type) {
+    case "link":
+      return new Menu_Element_Link($type);
+
+    case "ajax_link":
+      return new Menu_Element_Ajax_Link($type);
+
+    case "dialog":
+      return new Menu_Element_Dialog($type);
+
+    case "root":
+      $menu = new Menu("root");
+      $menu->css_class("g-menu");
+      return $menu;
+
+    case "submenu":
+      return new Menu("submenu");
+
+    default:
+      throw Exception("@todo UNKNOWN_MENU_TYPE");
+    }
+  }
+
+  public function __construct($type) {
+    parent::__construct($type);
+    $this->elements = array();
+    $this->is_root = $type == "root";
+  }
+
+  /**
+   * Add a new element to this menu
+   */
+  public function append($menu_element) {
+    $this->elements[$menu_element->id] = $menu_element;
+    return $this;
+  }
+
+  /**
+   * Add a new element to this menu, after the specific element
+   */
+  public function add_after($target_id, $new_menu_element) {
+    $copy = array();
+    foreach ($this->elements as $id => $menu_element) {
+      $copy[$id] = $menu_element;
+      if ($id == $target_id) {
+        $copy[$new_menu_element->id] = $new_menu_element;
+      }
+    }
+    $this->elements = $copy;
+    return $this;
+  }
+
+  /**
+   * Add a new element to this menu, before the specific element
+   */
+  public function add_before($target_id, $new_menu_element) {
+    $copy = array();
+    foreach ($this->elements as $id => $menu_element) {
+      if ($id == $target_id) {
+        $copy[$new_menu_element->id] = $new_menu_element;
+      }
+      $copy[$id] = $menu_element;
+    }
+    $this->elements = $copy;
+    return $this;
+  }
+
+  /**
+   * Remove an element from the menu
+   */
+  public function remove($target_id) {
+    unset($this->elements[$target_id]);
+  }
+
+  /**
+   * Retrieve a Menu_Element by id
+   */
+  public function &get($id) {
+    if (array_key_exists($id, $this->elements)) {
+      return $this->elements[$id];
+    }
+
+    $null = null;
+    return $null;
+  }
+
+  public function is_empty() {
+    foreach ($this->elements as $element) {
+      if ($element instanceof Menu) {
+        if (!$element->is_empty()) {
+          return false;
+        }
+      } else {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  public function render() {
+    $view = new View(isset($this->view) ? $this->view : "menu.html");
+    $view->menu = $this;
+    return $view;
+  }
+
+  static function title_comparator($a, $b) {
+    return strnatcasecmp((string)$a->label, (string)$b->label);
+  }
+}
diff --git a/modules/gallery/libraries/ORM_MPTT.php b/modules/gallery/libraries/ORM_MPTT.php
new file mode 100644
index 0000000..0ad8133
--- /dev/null
+++ b/modules/gallery/libraries/ORM_MPTT.php
@@ -0,0 +1,341 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+/**
+ * Implement Modified Preorder Tree Traversal on top of ORM.
+ *
+ * MPTT is an efficient way to store and retrieve hierarchical data in a single database table.
+ * For a good description, read http://www.sitepoint.com/article/hierarchical-data-database/3/
+ *
+ * This code was heavily influenced by code from:
+ *  - http://code.google.com/p/kohana-mptt/
+ *  - http://code.google.com/p/kohana-mptt/wiki/Documentation
+ *  - http://code.google.com/p/s7ncms/source/browse/trunk/modules/s7ncms/libraries/ORM_MPTT.php
+ *
+ * Unfortunately that code was not ready for production and I did not want to absorb their code
+ * and licensing issues so I've reimplemented just the features that we need.
+ */
+class ORM_MPTT_Core extends ORM {
+  private $model_name = null;
+
+  function __construct($id=null) {
+    parent::__construct($id);
+    $this->model_name = inflector::singular($this->table_name);
+  }
+
+  /**
+   * Overload ORM::save() to update the MPTT tree when we add new items to the hierarchy.
+   *
+   * @chainable
+   * @return  ORM
+   */
+  function save() {
+    if (!$this->loaded()) {
+      $this->lock();
+      $parent = ORM::factory("item", $this->parent_id);
+
+      try {
+        // Make a hole in the parent for this new item
+        db::build()
+          ->update($this->table_name)
+          ->set("left_ptr", db::expr("`left_ptr` + 2"))
+          ->where("left_ptr", ">=", $parent->right_ptr)
+          ->execute();
+        db::build()
+          ->update($this->table_name)
+          ->set("right_ptr", db::expr("`right_ptr` + 2"))
+          ->where("right_ptr", ">=", $parent->right_ptr)
+          ->execute();
+        $parent->right_ptr += 2;
+
+        // Insert this item into the hole
+        $this->left_ptr = $parent->right_ptr - 2;
+        $this->right_ptr = $parent->right_ptr - 1;
+        $this->parent_id = $parent->id;
+        $this->level = $parent->level + 1;
+      } catch (Exception $e) {
+        $this->unlock();
+        throw $e;
+      }
+      parent::save();
+      $this->unlock();
+    } else {
+      parent::save();
+    }
+
+    return $this;
+  }
+
+  /**
+   * Delete this node and all of its children.
+   */
+  public function delete($ignored_id=null) {
+    $children = $this->children();
+    if ($children) {
+      foreach ($this->children() as $item) {
+        // Deleting children affects the MPTT tree, so we have to reload each child before we
+        // delete it so that we have current left_ptr/right_ptr pointers.  This is inefficient.
+        // @todo load each child once, not twice.
+        set_time_limit(30);
+        $item->reload()->delete();
+      }
+
+      // Deleting children has affected this item, but we'll reload it below.
+    }
+
+    $this->lock();
+    $this->reload();  // Assume that the prior lock holder may have changed this entry
+    if (!$this->loaded()) {
+      // Concurrent deletes may result in this item already being gone.  Ignore it.
+      return;
+    }
+
+    try {
+      db::build()
+        ->update($this->table_name)
+        ->set("left_ptr", db::expr("`left_ptr` - 2"))
+        ->where("left_ptr", ">", $this->right_ptr)
+        ->execute();
+      db::build()
+        ->update($this->table_name)
+        ->set("right_ptr", db::expr("`right_ptr` - 2"))
+        ->where("right_ptr", ">", $this->right_ptr)
+        ->execute();
+    } catch (Exception $e) {
+      $this->unlock();
+      throw $e;
+    }
+
+    $this->unlock();
+    parent::delete();
+  }
+
+  /**
+   * Return true if the target is descendant of this item.
+   * @param ORM $target
+   * @return boolean
+   */
+  function contains($target) {
+    return ($this->left_ptr <= $target->left_ptr && $this->right_ptr >= $target->right_ptr);
+  }
+
+  /**
+   * Return the parent of this node
+   *
+   * @return ORM
+   */
+  function parent() {
+    if (!$this->parent_id) {
+      return null;
+    }
+    return model_cache::get($this->model_name, $this->parent_id);
+  }
+
+  /**
+   * Return all the parents of this node, in order from root to this node's immediate parent.
+   *
+   * @return array ORM
+   */
+  function parents($where=null) {
+    return $this
+      ->merge_where($where)
+      ->where("left_ptr", "<=", $this->left_ptr)
+      ->where("right_ptr", ">=", $this->right_ptr)
+      ->where("id", "<>", $this->id)
+      ->order_by("left_ptr", "ASC")
+      ->find_all();
+  }
+
+  /**
+   * Return all of the children of this node, ordered by id.
+   *
+   * @chainable
+   * @param   integer  SQL limit
+   * @param   integer  SQL offset
+   * @param   array    additional where clauses
+   * @param   array    order_by
+   * @return array ORM
+   */
+  function children($limit=null, $offset=null, $where=null, $order_by=array("id" => "ASC")) {
+    return $this
+      ->merge_where($where)
+      ->where("parent_id", "=", $this->id)
+      ->order_by($order_by)
+      ->find_all($limit, $offset);
+  }
+
+  /**
+   * Return the number of children of this node.
+   *
+   * @chainable
+   * @param   array    additional where clauses
+   * @return array ORM
+   */
+  function children_count($where=null) {
+    return $this
+      ->merge_where($where)
+      ->where("parent_id", "=", $this->id)
+      ->count_all();
+  }
+
+  /**
+   * Return all of the decendents of the specified type, ordered by id.
+   *
+   * @param   integer  SQL limit
+   * @param   integer  SQL offset
+   * @param   array    additional where clauses
+   * @param   array    order_by
+   * @return object ORM_Iterator
+   */
+  function descendants($limit=null, $offset=null, $where=null, $order_by=array("id" => "ASC")) {
+    return $this
+      ->merge_where($where)
+      ->where("left_ptr", ">", $this->left_ptr)
+      ->where("right_ptr", "<=", $this->right_ptr)
+      ->order_by($order_by)
+      ->find_all($limit, $offset);
+  }
+
+  /**
+   * Return the count of all the children of the specified type.
+   *
+   * @param    array    additional where clauses
+   * @return   integer  child count
+   */
+  function descendants_count($where=null) {
+    return $this
+      ->merge_where($where)
+      ->where("left_ptr", ">", $this->left_ptr)
+      ->where("right_ptr", "<=", $this->right_ptr)
+      ->count_all();
+  }
+
+  /**
+   * Move this item to the specified target.
+   *
+   * @chainable
+   * @param   Item_Model $target Target node
+   * @return  ORM_MTPP
+   */
+  protected function move_to($target) {
+    if ($this->contains($target)) {
+      throw new Exception("@todo INVALID_TARGET can't move item inside itself");
+    }
+
+    $this->lock();
+    $this->reload();  // Assume that the prior lock holder may have changed this entry
+    $target->reload();
+
+    $number_to_move = (int)(($this->right_ptr - $this->left_ptr) / 2 + 1);
+    $size_of_hole = $number_to_move * 2;
+    $original_left_ptr = $this->left_ptr;
+    $original_right_ptr = $this->right_ptr;
+    $target_right_ptr = $target->right_ptr;
+    $level_delta = ($target->level + 1) - $this->level;
+
+    try {
+      if ($level_delta) {
+        // Update the levels for the to-be-moved items
+        db::build()
+          ->update($this->table_name)
+          ->set("level", db::expr("`level` + $level_delta"))
+          ->where("left_ptr", ">=", $original_left_ptr)
+          ->where("right_ptr", "<=", $original_right_ptr)
+          ->execute();
+      }
+
+      // Make a hole in the target for the move
+      db::build()
+        ->update($this->table_name)
+        ->set("left_ptr", db::expr("`left_ptr` + $size_of_hole"))
+        ->where("left_ptr", ">=", $target_right_ptr)
+        ->execute();
+      db::build()
+        ->update($this->table_name)
+        ->set("right_ptr", db::expr("`right_ptr` + $size_of_hole"))
+        ->where("right_ptr", ">=", $target_right_ptr)
+        ->execute();
+
+      // Change the parent.
+      db::build()
+        ->update($this->table_name)
+        ->set("parent_id", $target->id)
+        ->where("id", "=", $this->id)
+        ->execute();
+
+      // If the source is to the right of the target then we just adjusted its left_ptr and
+      // right_ptr above.
+      $left_ptr = $original_left_ptr;
+      $right_ptr = $original_right_ptr;
+      if ($original_left_ptr > $target_right_ptr) {
+        $left_ptr += $size_of_hole;
+        $right_ptr += $size_of_hole;
+      }
+
+      $new_offset = $target->right_ptr - $left_ptr;
+      db::build()
+        ->update($this->table_name)
+        ->set("left_ptr", db::expr("`left_ptr` + $new_offset"))
+        ->set("right_ptr", db::expr("`right_ptr` + $new_offset"))
+        ->where("left_ptr", ">=", $left_ptr)
+        ->where("right_ptr", "<=", $right_ptr)
+        ->execute();
+
+      // Close the hole in the source's parent after the move
+      db::build()
+        ->update($this->table_name)
+        ->set("left_ptr", db::expr("`left_ptr` - $size_of_hole"))
+        ->where("left_ptr", ">", $right_ptr)
+        ->execute();
+      db::build()
+        ->update($this->table_name)
+        ->set("right_ptr", db::expr("`right_ptr` - $size_of_hole"))
+        ->where("right_ptr", ">", $right_ptr)
+        ->execute();
+    } catch (Exception $e) {
+      $this->unlock();
+      throw $e;
+    }
+
+    $this->unlock();
+
+    // Lets reload to get the changes.
+    $this->reload();
+    $target->reload();
+    return $this;
+  }
+
+  /**
+   * Lock the tree to prevent concurrent modification.
+   */
+  protected function lock() {
+    $timeout = module::get_var("gallery", "lock_timeout", 1);
+    $result = $this->db->query("SELECT GET_LOCK('{$this->table_name}', $timeout) AS l")->current();
+    if (empty($result->l)) {
+      throw new Exception("@todo UNABLE_TO_LOCK_EXCEPTION");
+    }
+  }
+
+  /**
+   * Unlock the tree.
+   */
+  protected function unlock() {
+    $this->db->query("SELECT RELEASE_LOCK('{$this->table_name}')");
+  }
+}
diff --git a/modules/gallery/libraries/SafeString.php b/modules/gallery/libraries/SafeString.php
new file mode 100644
index 0000000..179cbd4
--- /dev/null
+++ b/modules/gallery/libraries/SafeString.php
@@ -0,0 +1,162 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * Safe string representation (regarding security - cross site scripting).
+ */
+class SafeString_Core {
+  private $_raw_string;
+  protected $_is_safe_html = false;
+
+  /** Constructor */
+  function __construct($string) {
+    if ($string instanceof SafeString) {
+      $this->_is_safe_html = $string->_is_safe_html;
+      $string = $string->unescaped();
+    }
+    $this->_raw_string = (string) $string;
+  }
+
+  /**
+   * Factory method returning a new SafeString instance for the given string.
+   */
+  static function of($string) {
+    return new SafeString($string);
+  }
+
+  /**
+   * Factory method returning a new SafeString instance after HTML purifying
+   * the given string.
+   */
+  static function purify($string) {
+    if ($string instanceof SafeString) {
+      if ($string->_is_safe_html) {
+        return $string;
+      } else {
+        $string = $string->unescaped();
+      }
+    }
+    $safe_string = self::of_safe_html(self::_purify_for_html($string));
+    return $safe_string;
+  }
+
+  /**
+   * Factory method returning a new SafeString instance which won't HTML escape.
+   */
+  static function of_safe_html($string) {
+    $safe_string = new SafeString($string);
+    $safe_string->_is_safe_html = true;
+    return $safe_string;
+  }
+
+  /**
+   * Safe for use in HTML.
+   * @see #for_html()
+   */
+  function __toString() {
+    if ($this->_is_safe_html) {
+      return $this->_raw_string;
+    } else {
+      return self::_escape_for_html($this->_raw_string);
+    }
+  }
+
+  /**
+   * Safe for use in HTML.
+   *
+   * Example:<pre>
+   *   <div><?= $php_var ?>
+   * </pre>
+   * @return the string escaped for use in HTML.
+   */
+  function for_html() {
+    return $this;
+  }
+
+  /**
+   * Safe for use as JavaScript string.
+   *
+   * Example:<pre>
+   *   <script type="text/javascript>"
+   *     var some_js_var = <?= $php_var->for_js() ?>;
+   *   </script>
+   * </pre>
+   * @return the string escaped for use in JavaScript.
+   */
+  function for_js() {
+    return json_encode((string) $this->_raw_string);
+  }
+
+  /**
+   * Safe for use in HTML element attributes.
+   *
+   * Assumes that the HTML element attribute is already
+   * delimited by single or double quotes
+   *
+   * Example:<pre>
+   *     <a title="<?= $php_var->for_html_attr() ?>">;
+   *   </script>
+   * </pre>
+   * @return the string escaped for use in HTML attributes.
+   */
+  function for_html_attr() {
+    $string = (string) $this->for_html();
+    return strtr($string,
+                 array("'"=>"&#039;",
+                       '"'=>'&quot;'));
+  }
+
+  /**
+   * Safe for use HTML (purified HTML)
+   *
+   * Example:<pre>
+   *   <div><?= $php_var->purified_html() ?>
+   * </pre>
+   * @return the string escaped for use in HTML.
+   */
+  function purified_html() {
+    return self::purify($this);
+  }
+
+  /**
+   * Returns the raw, unsafe string. Do not use lightly.
+   */
+  function unescaped() {
+    return $this->_raw_string;
+  }
+
+  /**
+   * Escape special HTML chars ("<", ">", "&", etc.) to HTML entities.
+   */
+  private static function _escape_for_html($dirty_html) {
+    return html::chars($dirty_html);
+  }
+
+  /**
+   * Purify the string, removing any potentially malicious or unsafe HTML / JavaScript.
+   */
+  private static function _purify_for_html($dirty_html) {
+    if (class_exists("purifier") && method_exists("purifier", "purify")) {
+      return purifier::purify($dirty_html);
+    } else {
+      return self::_escape_for_html($dirty_html);
+    }
+  }
+}
diff --git a/modules/gallery/libraries/Sendmail.php b/modules/gallery/libraries/Sendmail.php
new file mode 100644
index 0000000..69a7c32
--- /dev/null
+++ b/modules/gallery/libraries/Sendmail.php
@@ -0,0 +1,98 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Sendmail_Core {
+  protected $to;
+  protected $subject;
+  protected $message;
+  protected $headers;
+  protected $line_length = 70;
+  protected $header_separator = "\r\n";
+
+  /**
+   * Return an instance of Sendmail
+   * @chainable
+   */
+  static function factory() {
+    return new Sendmail();
+  }
+
+  public function __construct() {
+    $this->headers = array();
+    $this->from(module::get_var("gallery", "email_from", ""));
+    $this->reply_to(module::get_var("gallery", "email_reply_to", ""));
+    $this->line_length(module::get_var("gallery", "email_line_length", 70));
+    $separator = module::get_var("gallery", "email_header_separator", null);
+    $this->header_separator(empty($separator) ? "\n" : unserialize($separator));
+  }
+
+  public function __get($key) {
+    return null;
+  }
+
+  public function __call($key, $value) {
+    switch ($key) {
+    case "to":
+      $this->to = is_array($value[0]) ? $value[0] : array($value[0]);
+      break;
+    case  "header":
+      if (count($value) != 2) {
+        Kohana_Log::add("error", wordwrap("Invalid header parameters\n" . Kohana::debug($value)));
+        throw new Exception("@todo INVALID_HEADER_PARAMETERS");
+      }
+      $this->headers[$value[0]] = $value[1];
+      break;
+    case "from":
+      $this->headers["From"] = $value[0];
+      break;
+    case "reply_to":
+      $this->headers["Reply-To"] = $value[0];
+      break;
+    default:
+      $this->$key = $value[0];
+    }
+    return $this;
+  }
+
+  public function send() {
+    if (empty($this->to)) {
+      Kohana_Log::add("error", wordwrap("Sending mail failed:\nNo to address specified"));
+      throw new Exception("@todo TO_IS_REQUIRED_FOR_MAIL");
+    }
+    $to = implode(", ", $this->to);
+    $headers = array();
+    foreach ($this->headers as $key => $value) {
+      $key = ucfirst($key);
+      $headers[] = "$key: $value";
+    }
+
+    // The docs say headers should be separated by \r\n, but occasionaly that doesn't work and you
+    // need to use a single \n.  This can be set in config/sendmail.php
+    $headers = implode($this->header_separator, $headers);
+    $message = wordwrap($this->message, $this->line_length, "\n");
+    if (!$this->mail($to, $this->subject, $message, $headers)) {
+      throw new Exception("@todo SEND_MAIL_FAILED");
+    }
+    return $this;
+  }
+
+  public function mail($to, $subject, $message, $headers) {
+    return mail($to, $subject, $message, $headers);
+  }
+}
diff --git a/modules/gallery/libraries/Task_Definition.php b/modules/gallery/libraries/Task_Definition.php
new file mode 100644
index 0000000..f695fe3
--- /dev/null
+++ b/modules/gallery/libraries/Task_Definition.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class Task_Definition_Core {
+  public $callback;
+  public $description;
+  public $name;
+  public $severity;
+
+  static function factory() {
+    return new Task_Definition();
+  }
+
+  function callback($callback) {
+    $this->callback = $callback;
+    return $this;
+  }
+
+  function description($description) {
+    $this->description = $description;
+    return $this;
+  }
+
+  function name($name) {
+    $this->name = $name;
+    return $this;
+  }
+
+  function severity($severity) {
+    $this->severity = $severity;
+    return $this;
+  }
+}
diff --git a/modules/gallery/libraries/Theme_View.php b/modules/gallery/libraries/Theme_View.php
new file mode 100644
index 0000000..9118375
--- /dev/null
+++ b/modules/gallery/libraries/Theme_View.php
@@ -0,0 +1,271 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Theme_View_Core extends Gallery_View {
+  /**
+   * Attempts to load a view and pre-load view data.
+   *
+   * @throws  Kohana_Exception  if the requested view cannot be found
+   * @param   string  $name view name
+   * @param   string  $page_type page type: collection, item, or other
+   * @param   string  $page_subtype page sub type: album, photo, tags, etc
+   * @param   string  $theme_name view name
+   * @return  void
+   */
+  public function __construct($name, $page_type, $page_subtype) {
+    parent::__construct($name);
+
+    $this->theme_name = module::get_var("gallery", "active_site_theme");
+    if (identity::active_user()->admin) {
+      $theme_name = Input::instance()->get("theme");
+      if ($theme_name &&
+          file_exists(THEMEPATH . $theme_name) &&
+          strpos(realpath(THEMEPATH . $theme_name), THEMEPATH) == 0) {
+        $this->theme_name = $theme_name;
+      }
+    }
+    $this->item = null;
+    $this->tag = null;
+    $this->set_global(array("theme" => $this,
+                            "theme_info" => theme::get_info($this->theme_name),
+                            "user" => identity::active_user(),
+                            "page_type" => $page_type,
+                            "page_subtype" => $page_subtype,
+                            "page_title" => null));
+
+    if (module::get_var("gallery", "maintenance_mode", 0)) {
+      if (identity::active_user()->admin) {
+        message::warning(t("This site is currently in maintenance mode.  Visit the <a href=\"%maintenance_url\">maintenance page</a>", array("maintenance_url" => url::site("admin/maintenance"))));
+    } else
+        message::warning(t("This site is currently in maintenance mode."));
+    }
+  }
+
+  /**
+   * Proportion of the current thumb_size's to default
+   * @param object Item_Model (optional) check the proportions for this item
+   * @return int
+   */
+  public function thumb_proportion($item=null) {
+    // If the item is an album with children, grab the first item in that album instead.  We're
+    // interested in the size of the thumbnails in this album, not the thumbnail of the
+    // album itself.
+    if ($item && $item->is_album() && $item->children_count()) {
+      $item = $item->children(1)->current();
+    }
+
+    // By default we have a globally fixed thumbnail size In core code, we just return a fixed
+    // proportion based on the global thumbnail size, but since modules can override that, we
+    // return the actual proportions when we have them.
+    if ($item && $item->has_thumb()) {
+      return max($item->thumb_width, $item->thumb_height) / 200;
+    } else {
+      // @TODO change the 200 to a theme supplied value when and if we come up with an
+      // API to allow the theme to set defaults.
+      return module::get_var("gallery", "thumb_size", 200) / 200;
+    }
+  }
+
+  public function item() {
+    return $this->item;
+  }
+
+  public function siblings($limit=null, $offset=null) {
+    return call_user_func_array(
+      $this->siblings_callback[0],
+      array_merge($this->siblings_callback[1], array($limit, $offset)));
+  }
+
+  public function tag() {
+    return $this->tag;
+  }
+
+  public function page_type() {
+    return $this->page_type;
+  }
+
+  public function page_subtype() {
+    return $this->page_subtype;
+  }
+
+  public function user_menu() {
+    $menu = Menu::factory("root")
+      ->css_id("g-login-menu")
+      ->css_class("g-inline ui-helper-clear-fix");
+    module::event("user_menu", $menu, $this);
+    return $menu->render();
+  }
+
+  public function site_menu($item_css_selector) {
+    $menu = Menu::factory("root");
+    module::event("site_menu", $menu, $this, $item_css_selector);
+    return $menu->render();
+  }
+
+  public function album_menu() {
+    $menu = Menu::factory("root");
+    module::event("album_menu", $menu, $this);
+    return $menu->render();
+  }
+
+  public function tag_menu() {
+    $menu = Menu::factory("root");
+    module::event("tag_menu", $menu, $this);
+    return $menu->render();
+  }
+
+  public function photo_menu() {
+    $menu = Menu::factory("root");
+    if (access::can("view_full", $this->item())) {
+      $menu->append(Menu::factory("link")
+                    ->id("fullsize")
+                    ->label(t("View full size"))
+                    ->url($this->item()->file_url())
+                    ->css_class("g-fullsize-link"));
+    }
+
+    module::event("photo_menu", $menu, $this);
+    return $menu->render();
+  }
+
+  public function movie_menu() {
+    $menu = Menu::factory("root");
+    module::event("movie_menu", $menu, $this);
+    return $menu->render();
+  }
+
+  public function context_menu($item, $thumbnail_css_selector) {
+    $menu = Menu::factory("root")
+      ->append(Menu::factory("submenu")
+               ->id("context_menu")
+               ->label(t("Options")))
+      ->css_class("g-context-menu");
+
+    module::event("context_menu", $menu, $this, $item, $thumbnail_css_selector);
+    return $menu->render();
+  }
+
+  /**
+   * Print out any site wide status information.
+   */
+  public function site_status() {
+    return site_status::get();
+  }
+
+  /**
+   * Print out any messages waiting for this user.
+   */
+  public function messages() {
+    return message::get();
+  }
+
+  /**
+   * Print out the sidebar.
+   */
+  public function sidebar_blocks() {
+    $sidebar = block_manager::get_html("site_sidebar", $this);
+    if (empty($sidebar) && identity::active_user()->admin) {
+      $sidebar = new View("no_sidebar.html");
+    }
+    return $sidebar;
+  }
+
+  /**
+   * Handle all theme functions that insert module content.
+   */
+  public function __call($function, $args) {
+    switch ($function) {
+    case "album_blocks":
+    case "album_bottom":
+    case "album_top":
+    case "body_attributes":
+    case "credits";
+    case "dynamic_bottom":
+    case "dynamic_top":
+    case "footer":
+    case "head":
+    case "header_bottom":
+    case "header_top":
+    case "html_attributes":
+    case "page_bottom":
+    case "page_top":
+    case "photo_blocks":
+    case "photo_bottom":
+    case "photo_top":
+    case "resize_bottom":
+    case "resize_top":
+    case "sidebar_bottom":
+    case "sidebar_top":
+    case "thumb_bottom":
+    case "thumb_info":
+    case "thumb_top":
+      $blocks = array();
+      if (method_exists("gallery_theme", $function)) {
+        switch (count($args)) {
+        case 0:
+          $blocks[] = gallery_theme::$function($this);
+          break;
+        case 1:
+          $blocks[] = gallery_theme::$function($this, $args[0]);
+          break;
+        case 2:
+          $blocks[] = gallery_theme::$function($this, $args[0], $args[1]);
+          break;
+        default:
+          $blocks[] = call_user_func_array(
+            array("gallery_theme", $function),
+            array_merge(array($this), $args));
+        }
+      }
+
+      foreach (module::active() as $module) {
+        if ($module->name == "gallery") {
+          continue;
+        }
+        $helper_class = "{$module->name}_theme";
+        if (class_exists($helper_class) && method_exists($helper_class, $function)) {
+          $blocks[] = call_user_func_array(
+            array($helper_class, $function),
+            array_merge(array($this), $args));
+        }
+      }
+
+      $helper_class = theme::$site_theme_name . "_theme";
+      if (class_exists($helper_class) && method_exists($helper_class, $function)) {
+        $blocks[] = call_user_func_array(
+          array($helper_class, $function),
+          array_merge(array($this), $args));
+      }
+
+      if (Session::instance()->get("debug")) {
+        if ($function != "head" && $function != "body_attributes") {
+          array_unshift(
+            $blocks,
+            "<div class=\"g-annotated-theme-block g-annotated-theme-block_$function g-clear-fix\">" .
+            "<div class=\"title\">$function</div>");
+          $blocks[] = "</div>";
+        }
+      }
+      return implode("\n", $blocks);
+
+    default:
+      throw new Exception("@todo UNKNOWN_THEME_FUNCTION: $function");
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/drivers/Cache/Database.php b/modules/gallery/libraries/drivers/Cache/Database.php
new file mode 100644
index 0000000..8790d0e
--- /dev/null
+++ b/modules/gallery/libraries/drivers/Cache/Database.php
@@ -0,0 +1,166 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+/*
+ * Based on the Cache_Sqlite_Driver developed by the Kohana Team
+ */
+class Cache_Database_Driver extends Cache_Driver {
+  // Kohana database instance
+  protected $db;
+
+  /**
+   * Sets a cache item to the given data, tags, and lifetime.
+   *
+   * @param   array    assoc array of key => value pairs
+   * @param   array    cache tags
+   * @param   integer  lifetime
+   * @return  bool
+   */
+  public function set($items, $tags=null, $lifetime=null) {
+    if (!empty($tags)) {
+      // Escape the tags, adding brackets so the tag can be explicitly matched
+      $tags = "<" . implode(">,<", $tags) . ">";
+    } else {
+      $tags = null;
+    }
+
+    // Cache Database driver expects unix timestamp
+    if ($lifetime !== 0) {
+      $lifetime += time();
+    }
+
+    $db = Database::instance();
+    $tags = $db->escape($tags);
+    foreach ($items as $id => $data) {
+      $id = $db->escape($id);
+      $data = $db->escape(serialize($data));
+      $db->query("INSERT INTO {caches} (`key`, `tags`, `expiration`, `cache`)
+                  VALUES ('$id', '$tags', $lifetime, '$data')
+                  ON DUPLICATE KEY UPDATE `tags` = VALUES(tags), `expiration` = VALUES(expiration),
+                  `cache` = VALUES(cache)");
+    }
+
+    return true;
+  }
+
+  /**
+   * Get cache items by tag
+   * @param   array    cache tags
+   * @return  array    cached data
+   */
+  public function get_tag($tags) {
+    $db = db::build()
+      ->select()
+      ->from("caches");
+    foreach ($tags as $tag) {
+      $db->where("tags", "LIKE", "%" . Database::escape_for_like("<$tag>") . "%");
+    }
+    $db_result = $db->execute();
+
+    // An array will always be returned
+    $result = array();
+
+    // Disable notices for unserializing
+    $ER = error_reporting(~E_NOTICE);
+    if ($db_result->count() > 0) {
+      foreach ($db_result as $row) {
+        // Add each cache to the array
+        $result[$row->key] = unserialize($row->cache);
+      }
+    }
+    error_reporting($ER);
+
+    return $result;
+  }
+
+  /**
+   * Fetches a cache item. This will delete the item if it is expired or if
+   * the hash does not match the stored hash.
+   *
+   * @param  string  cache id
+   * @return mixed|NULL
+   */
+  public function get($keys, $single=false) {
+    $data = null;
+    $result = db::build()
+      ->select()
+      ->from("caches")
+      ->where("key", "IN", $keys)
+      ->execute();
+
+    if (count($result) > 0) {
+      $cache = $result->current();
+      // Make sure the expiration is valid and that the hash matches
+      if ($cache->expiration != 0 && $cache->expiration <= time()) {
+        // Cache is not valid, delete it now
+        $this->delete(array($cache->id));
+      } else {
+        // Disable notices for unserializing
+        $ER = error_reporting(~E_NOTICE);
+
+        // Return the valid cache data
+        $data = unserialize($cache->cache);
+
+        // Turn notices back on
+        error_reporting($ER);
+      }
+    }
+
+    return $data;
+  }
+
+  /**
+   * Deletes a cache item by id or tag
+   *
+   * @param  string  cache id or tag, or true for "all items"
+   * @param  bool    delete a tag
+   * @return bool
+   */
+  public function delete($keys, $is_tag=false) {
+    $db = db::build()
+      ->delete("caches");
+    if ($keys === true) {
+      // Delete all caches
+    } else if ($is_tag === true) {
+      foreach ($keys as $tag) {
+        $db->where("tags", "LIKE", "%" . Database::escape_for_like("<$tag>") . "%");
+      }
+    } else {
+      $db->where("key", "IN", $keys);
+    }
+
+    $status = $db->execute();
+
+    return count($status) > 0;
+  }
+
+  /**
+   * Delete cache items by tag
+   */
+  public function delete_tag($tags) {
+    return $this->delete($tags, true);
+  }
+
+  /**
+   * Empty the cache
+   */
+  public function delete_all() {
+    Database::instance()->query("TRUNCATE {caches}");
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/libraries/drivers/IdentityProvider.php b/modules/gallery/libraries/drivers/IdentityProvider.php
new file mode 100644
index 0000000..5256236
--- /dev/null
+++ b/modules/gallery/libraries/drivers/IdentityProvider.php
@@ -0,0 +1,134 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+interface IdentityProvider_Driver {
+  /**
+   * Return the guest user.
+   *
+   * @return User_Definition the user object
+   */
+  public function guest();
+
+  /**
+   * Return the primary admin user.
+   *
+   * @return User_Definition the user object
+   */
+  public function admin_user();
+
+  /**
+   * Create a new user.
+   *
+   * @param string  $name
+   * @param string  $full_name
+   * @param string  $password
+   * @param string  $email
+   * @return User_Definition the user object
+   */
+  public function create_user($name, $full_name, $password, $email);
+
+  /**
+   * Is the password provided correct?
+   *
+   * @param user User_Definition the user object
+   * @param string $password a plaintext password
+   * @return boolean true if the password is correct
+   */
+  public function is_correct_password($user, $password);
+
+  /**
+   * Look up a user by id.
+   * @param integer $id
+   * @return User_Definition the user object, or null if the name was invalid.
+   */
+  public function lookup_user($id);
+
+  /**
+   * Look up a user by name.
+   * @param string $name
+   * @return User_Definition the user object, or null if the name was invalid.
+   */
+  public function lookup_user_by_name($name);
+
+  /**
+   * Create a new group.
+   *
+   * @param string $name
+   * @return Group_Definition the group object
+   */
+  public function create_group($name);
+
+  /**
+   * The group of all possible visitors.  This includes the guest user.
+   *
+   * @return Group_Definition the group object
+   */
+  public function everybody();
+
+  /**
+   * The group of all logged-in visitors.  This does not include guest users.
+   *
+   * @return Group_Definition the group object
+   */
+  public function registered_users();
+
+  /**
+   * List the users
+   * @param array $ids array of ids to return the user objects for
+   * @return array the user list.
+   */
+  public function get_user_list($ids);
+
+  /**
+   * Look up a group by id.
+   * @param integer $id id
+   * @return Group_Definition the user object, or null if the name was invalid.
+   */
+  public function lookup_group($id);
+
+  /**
+   * Look up the group by name.
+   * @param string $name the name of the group to locate
+   * @return Group_Definition
+   */
+  public function lookup_group_by_name($name);
+
+  /**
+   * List the groups defined in the Identity Provider
+   */
+  public function groups();
+
+  /**
+   * Add the user to the specified group
+   * @param User_Definition  the user to add
+   * @param Group_Definition the target group
+   */
+  public function add_user_to_group($user, $group);
+
+  /**
+   * Remove the user to the specified group
+   * @param User_Definition  the user to remove
+   * @param Group_Definition the owning group
+   */
+  public function remove_user_from_group($user, $group);
+} // End Identity Driver Definition
+
+interface Group_Definition {}
+
+interface User_Definition {}
diff --git a/modules/gallery/models/access_cache.php b/modules/gallery/models/access_cache.php
new file mode 100644
index 0000000..b0c0843
--- /dev/null
+++ b/modules/gallery/models/access_cache.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Access_Cache_Model_Core extends ORM {
+}
diff --git a/modules/gallery/models/access_intent.php b/modules/gallery/models/access_intent.php
new file mode 100644
index 0000000..56f9666
--- /dev/null
+++ b/modules/gallery/models/access_intent.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Access_Intent_Model_Core extends ORM {
+}
diff --git a/modules/gallery/models/cache.php b/modules/gallery/models/cache.php
new file mode 100644
index 0000000..37d5265
--- /dev/null
+++ b/modules/gallery/models/cache.php
@@ -0,0 +1,20 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Cache_Model_Core extends ORM {}
diff --git a/modules/gallery/models/failed_auth.php b/modules/gallery/models/failed_auth.php
new file mode 100644
index 0000000..85c6492
--- /dev/null
+++ b/modules/gallery/models/failed_auth.php
@@ -0,0 +1,20 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Failed_Auth_Model_Core extends ORM {}
diff --git a/modules/gallery/models/graphics_rule.php b/modules/gallery/models/graphics_rule.php
new file mode 100644
index 0000000..241560e
--- /dev/null
+++ b/modules/gallery/models/graphics_rule.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Graphics_Rule_Model_Core extends ORM {
+}
diff --git a/modules/gallery/models/incoming_translation.php b/modules/gallery/models/incoming_translation.php
new file mode 100644
index 0000000..f3c9813
--- /dev/null
+++ b/modules/gallery/models/incoming_translation.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Incoming_Translation_Model_Core extends ORM {
+}
diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php
new file mode 100644
index 0000000..c446eea
--- /dev/null
+++ b/modules/gallery/models/item.php
@@ -0,0 +1,1191 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Item_Model_Core extends ORM_MPTT {
+  protected $children = "items";
+  protected $sorting = array();
+  public $data_file = null;
+  private $data_file_error = null;
+
+  public function __construct($id=null) {
+    parent::__construct($id);
+
+    if (!$this->loaded()) {
+      // Set reasonable defaults
+      $this->created = time();
+      $this->rand_key = random::percent();
+      $this->thumb_dirty = 1;
+      $this->resize_dirty = 1;
+      $this->sort_column = "created";
+      $this->sort_order = "ASC";
+      $this->owner_id = identity::active_user()->id;
+    }
+  }
+
+  /**
+   * Add a set of restrictions to any following queries to restrict access only to items
+   * viewable by the active user.
+   * @chainable
+   */
+  public function viewable() {
+    return item::viewable($this);
+  }
+
+  /**
+   * Is this item an album?
+   * @return true if it's an album
+   */
+  public function is_album() {
+    return $this->type == 'album';
+  }
+
+  /**
+   * Is this item a photo?
+   * @return true if it's a photo
+   */
+  public function is_photo() {
+    return $this->type == 'photo';
+  }
+
+  /**
+   * Is this item a movie?
+   * @return true if it's a movie
+   */
+  public function is_movie() {
+    return $this->type == 'movie';
+  }
+
+  public function delete($ignored_id=null) {
+    if (!$this->loaded()) {
+      // Concurrent deletes may result in this item already being gone.  Ignore it.
+      return;
+    }
+
+    if ($this->id == 1) {
+      $v = new Validation(array("id"));
+      $v->add_error("id", "cant_delete_root_album");
+      ORM_Validation_Exception::handle_validation($this->table_name, $v);
+    }
+
+    $old = clone $this;
+    module::event("item_before_delete", $this);
+
+    $parent = $this->parent();
+    if ($parent->album_cover_item_id == $this->id) {
+      item::remove_album_cover($parent);
+    }
+
+    $path = $this->file_path();
+    $resize_path = $this->resize_path();
+    $thumb_path = $this->thumb_path();
+
+    parent::delete();
+    if (is_dir($path)) {
+      // Take some precautions against accidentally deleting way too much
+      $delete_resize_path = dirname($resize_path);
+      $delete_thumb_path = dirname($thumb_path);
+      if ($delete_resize_path == VARPATH . "resizes" ||
+          $delete_thumb_path == VARPATH . "thumbs" ||
+          $path == VARPATH . "albums") {
+        throw new Exception(
+          "@todo DELETING_TOO_MUCH ($delete_resize_path, $delete_thumb_path, $path)");
+      }
+      @dir::unlink($path);
+      @dir::unlink($delete_resize_path);
+      @dir::unlink($delete_thumb_path);
+    } else {
+      @unlink($path);
+      @unlink($resize_path);
+      @unlink($thumb_path);
+    }
+
+    module::event("item_deleted", $old);
+  }
+
+  /**
+   * Specify the path to the data file associated with this item.  To actually associate it,
+   * you still have to call save().
+   * @chainable
+   */
+  public function set_data_file($data_file) {
+    $this->data_file = $data_file;
+    return $this;
+  }
+
+  /**
+   * Return the server-relative url to this item, eg:
+   *   album: /gallery3/index.php/Bobs%20Wedding?page=2
+   *   photo: /gallery3/index.php/Bobs%20Wedding/Eating-Cake
+   *   movie: /gallery3/index.php/Bobs%20Wedding/First-Dance
+   *
+   * @param string $query the query string (eg "page=2")
+   */
+  public function url($query=null) {
+    $url = url::site($this->relative_url());
+    if ($query) {
+      $url .= "?$query";
+    }
+    return $url;
+  }
+
+  /**
+   * Return the full url to this item, eg:
+   *   album: http://example.com/gallery3/index.php/Bobs%20Wedding?page=2
+   *   photo: http://example.com/gallery3/index.php/Bobs%20Wedding/Eating-Cake
+   *   movie: http://example.com/gallery3/index.php/Bobs%20Wedding/First-Dance
+   *
+   * @param string $query the query string (eg "page=2")
+   */
+  public function abs_url($query=null) {
+    $url = url::abs_site($this->relative_url());
+    if ($query) {
+      $url .= "?$query";
+    }
+    return $url;
+  }
+
+  /**
+   * Return the full path to this item's file, eg:
+   *   album: /usr/home/www/gallery3/var/albums/Bobs Wedding
+   *   photo: /usr/home/www/gallery3/var/albums/Bobs Wedding/Eating-Cake.jpg
+   *   movie: /usr/home/www/gallery3/var/albums/Bobs Wedding/First-Dance.mp4
+   */
+  public function file_path() {
+    return VARPATH . "albums/" . urldecode($this->relative_path());
+  }
+
+  /**
+   * Return the relative url to this item's file, with cache buster, eg:
+   *   album: var/albums/Bobs%20Wedding?m=1234567890
+   *   photo: var/albums/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+   *   movie: var/albums/Bobs%20Wedding/First-Dance.mp4?m=1234567890
+   * If $full_uri==true, return the full url to this item's file, with cache buster, eg:
+   *   album: http://example.com/gallery3/var/albums/Bobs%20Wedding?m=1234567890
+   *   photo: http://example.com/gallery3/var/albums/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+   *   movie: http://example.com/gallery3/var/albums/Bobs%20Wedding/First-Dance.mp4?m=1234567890
+   */
+  public function file_url($full_uri=false) {
+    $relative_path = "var/albums/" . $this->relative_path();
+    $cache_buster = $this->_cache_buster($this->file_path());
+    return ($full_uri ? url::abs_file($relative_path) : url::file($relative_path))
+      . $cache_buster;
+  }
+
+  /**
+   * Return the full path to this item's thumb, eg:
+   *   album: /usr/home/www/gallery3/var/thumbs/Bobs Wedding/.album.jpg
+   *   photo: /usr/home/www/gallery3/var/thumbs/Bobs Wedding/Eating-Cake.jpg
+   *   movie: /usr/home/www/gallery3/var/thumbs/Bobs Wedding/First-Dance.jpg
+   */
+  public function thumb_path() {
+    $base = VARPATH . "thumbs/" . urldecode($this->relative_path());
+    if ($this->is_photo()) {
+      return $base;
+    } else if ($this->is_album()) {
+      return $base . "/.album.jpg";
+    } else if ($this->is_movie()) {
+      // Replace the extension with jpg
+      return legal_file::change_extension($base, "jpg");
+    }
+  }
+
+  /**
+   * Return true if there is a thumbnail for this item.
+   */
+  public function has_thumb() {
+    return $this->thumb_width && $this->thumb_height;
+  }
+
+  /**
+   * Return the relative url to this item's thumb, with cache buster, eg:
+   *   album: var/thumbs/Bobs%20Wedding/.album.jpg?m=1234567890
+   *   photo: var/thumbs/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+   *   movie: var/thumbs/Bobs%20Wedding/First-Dance.mp4?m=1234567890
+   * If $full_uri==true, return the full url to this item's file, with cache buster, eg:
+   *   album: http://example.com/gallery3/var/thumbs/Bobs%20Wedding/.album.jpg?m=1234567890
+   *   photo: http://example.com/gallery3/var/thumbs/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+   *   movie: http://example.com/gallery3/var/thumbs/Bobs%20Wedding/First-Dance.mp4?m=1234567890
+   */
+  public function thumb_url($full_uri=false) {
+    $cache_buster = $this->_cache_buster($this->thumb_path());
+    $relative_path = "var/thumbs/" . $this->relative_path();
+    $base = ($full_uri ? url::abs_file($relative_path) : url::file($relative_path));
+    if ($this->is_photo()) {
+      return $base . $cache_buster;
+    } else if ($this->is_album()) {
+      return $base . "/.album.jpg" . $cache_buster;
+    } else if ($this->is_movie()) {
+      // Replace the extension with jpg
+      $base = legal_file::change_extension($base, "jpg");
+      return $base . $cache_buster;
+    }
+  }
+
+  /**
+   * Return the full path to this item's resize, eg:
+   *   album: /usr/home/www/gallery3/var/resizes/Bobs Wedding/.album.jpg      (*)
+   *   photo: /usr/home/www/gallery3/var/resizes/Bobs Wedding/Eating-Cake.jpg
+   *   movie: /usr/home/www/gallery3/var/resizes/Bobs Wedding/First-Dance.mp4 (*)
+   * (*) Since only photos have resizes, album and movie paths are fictitious.
+   */
+  public function resize_path() {
+    return VARPATH . "resizes/" . urldecode($this->relative_path()) .
+      ($this->is_album() ? "/.album.jpg" : "");
+  }
+
+  /**
+   * Return the relative url to this item's resize, with cache buster, eg:
+   *   album: var/resizes/Bobs%20Wedding/.album.jpg?m=1234567890      (*)
+   *   photo: var/resizes/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+   *   movie: var/resizes/Bobs%20Wedding/First-Dance.mp4?m=1234567890 (*)
+   * If $full_uri==true, return the full url to this item's file, with cache buster, eg:
+   *   album: http://example.com/gallery3/var/resizes/Bobs%20Wedding/.album.jpg?m=1234567890      (*)
+   *   photo: http://example.com/gallery3/var/resizes/Bobs%20Wedding/Eating-Cake.jpg?m=1234567890
+   *   movie: http://example.com/gallery3/var/resizes/Bobs%20Wedding/First-Dance.mp4?m=1234567890 (*)
+   * (*) Since only photos have resizes, album and movie urls are fictitious.
+   */
+  public function resize_url($full_uri=false) {
+    $relative_path = "var/resizes/" . $this->relative_path();
+    $cache_buster = $this->_cache_buster($this->resize_path());
+    return ($full_uri ? url::abs_file($relative_path) : url::file($relative_path)) .
+      ($this->is_album() ? "/.album.jpg" : "") . $cache_buster;
+  }
+
+  /**
+   * Rebuild the relative_path_cache and relative_url_cache.
+   */
+  private function _build_relative_caches() {
+    $names = array();
+    $slugs = array();
+    foreach (db::build()
+             ->select(array("name", "slug"))
+             ->from("items")
+             ->where("left_ptr", "<=", $this->left_ptr)
+             ->where("right_ptr", ">=", $this->right_ptr)
+             ->where("id", "<>", 1)
+             ->order_by("left_ptr", "ASC")
+             ->execute() as $row) {
+      // Don't encode the names segment
+      $names[] = rawurlencode($row->name);
+      $slugs[] = rawurlencode($row->slug);
+    }
+    $this->relative_path_cache = implode($names, "/");
+    $this->relative_url_cache = implode($slugs, "/");
+    return $this;
+  }
+
+  /**
+   * Return the relative path to this item's file.  Note that the components of the path are
+   * urlencoded so if you want to use this as a filesystem path, you need to call urldecode
+   * on it.
+   * @return string
+   */
+  public function relative_path() {
+    if (!$this->loaded()) {
+      return;
+    }
+
+    if (!isset($this->relative_path_cache)) {
+      $this->_build_relative_caches()->save();
+    }
+    return $this->relative_path_cache;
+  }
+
+  /**
+   * Return the relative url to this item's file.
+   * @return string
+   */
+  public function relative_url() {
+    if (!$this->loaded()) {
+      return;
+    }
+
+    if (!isset($this->relative_url_cache)) {
+      $this->_build_relative_caches()->save();
+    }
+    return $this->relative_url_cache;
+  }
+
+  /**
+   * @see ORM::__get()
+   */
+  public function __get($column) {
+    if ($column == "owner") {
+      // This relationship depends on an outside module, which may not be present so handle
+      // failures gracefully.
+      try {
+        return identity::lookup_user($this->owner_id);
+      } catch (Exception $e) {
+        return null;
+      }
+    } else {
+      return parent::__get($column);
+    }
+  }
+
+  /**
+   * Handle any business logic necessary to create or modify an item.
+   * @see ORM::save()
+   *
+   * @return ORM Item_Model
+   */
+  public function save() {
+    $significant_changes = $this->changed;
+    foreach (array("view_count", "relative_url_cache", "relative_path_cache",
+                   "resize_width", "resize_height", "resize_dirty",
+                   "thumb_width", "thumb_height", "thumb_dirty") as $key) {
+      unset($significant_changes[$key]);
+    }
+
+    if ((!empty($this->changed) && $significant_changes) || isset($this->data_file)) {
+      $this->updated = time();
+      if (!$this->loaded()) {
+        // Create a new item.
+        module::event("item_before_create", $this);
+
+        // Set a weight if it's missing.  We don't do this in the constructor because it's not a
+        // simple assignment.
+        if (empty($this->weight)) {
+          $this->weight = item::get_max_weight();
+        }
+
+        // Process the data file info.
+        if (isset($this->data_file)) {
+          $this->_process_data_file_info();
+        } else if (!$this->is_album()) {
+          // Unless it's an album, new items must have a data file.
+          $this->data_file_error = true;
+        }
+
+        // Make an url friendly slug from the name, if necessary
+        if (empty($this->slug)) {
+          $this->slug = item::convert_filename_to_slug(pathinfo($this->name, PATHINFO_FILENAME));
+
+          // If the filename is all invalid characters, then the slug may be empty here.  We set a
+          // generic name ("photo", "movie", or "album") based on its type, then rely on
+          // check_and_fix_conflicts to ensure it doesn't conflict with another name.
+          if (empty($this->slug)) {
+            $this->slug = $this->type;
+          }
+        }
+
+        $this->_check_and_fix_conflicts();
+
+        parent::save();
+
+        // Build our url caches, then save again.  We have to do this after it's already been
+        // saved once because we use only information from the database to build the paths.  If we
+        // could depend on a save happening later we could defer this 2nd save.
+        $this->_build_relative_caches();
+        parent::save();
+
+        // Take any actions that we can only do once all our paths are set correctly after saving.
+        switch ($this->type) {
+        case "album":
+          mkdir($this->file_path());
+          mkdir(dirname($this->thumb_path()));
+          mkdir(dirname($this->resize_path()));
+          break;
+
+        case "photo":
+        case "movie":
+          copy($this->data_file, $this->file_path());
+          break;
+        }
+
+        // This will almost definitely trigger another save, so put it at the end so that we're
+        // tail recursive.  Null out the data file variable first, otherwise the next save will
+        // trigger an item_updated_data_file event.
+        $this->data_file = null;
+        module::event("item_created", $this);
+      } else {
+        // Update an existing item
+        module::event("item_before_update", $this);
+
+        // If any significant fields have changed, load up a copy of the original item and
+        // keep it around.
+        $original = ORM::factory("item", $this->id);
+
+        // If we have a new data file, process its info.  This will get its metadata and
+        // preserve the extension of the data file. Many helpers, (e.g. ImageMagick), assume
+        // the MIME type from the extension. So when we adopt the new data file, it's important
+        // to adopt the new extension. That ensures that the item's extension is always
+        // appropriate for its data. We don't try to preserve the name of the data file, though,
+        // because the name is typically a temporary randomly-generated name.
+        if (isset($this->data_file)) {
+          $this->_process_data_file_info();
+        } else if (!$this->is_album() && array_key_exists("name", $this->changed)) {
+          // There's no new data file, but the name changed.  If it's a photo or movie,
+          // make sure the new name still agrees with the file type.
+          $this->name = legal_file::sanitize_filename($this->name,
+            pathinfo($original->name, PATHINFO_EXTENSION), $this->type);
+        }
+
+        // If an album's cover has changed (or been removed), delete any existing album cover,
+        // reset the thumb metadata, and mark the thumb as dirty.
+        if (array_key_exists("album_cover_item_id", $this->changed) && $this->is_album()) {
+          @unlink($original->thumb_path());
+          $this->thumb_dirty = 1;
+          $this->thumb_height = 0;
+          $this->thumb_width = 0;
+        }
+
+        if (array_intersect($this->changed, array("parent_id", "name", "slug"))) {
+          $original->_build_relative_caches();
+          $this->relative_path_cache = null;
+          $this->relative_url_cache = null;
+        }
+
+        $this->_check_and_fix_conflicts();
+
+        parent::save();
+
+        // Now update the filesystem and any database caches if there were significant value
+        // changes.  If anything past this point fails, then we'll have an inconsistent database
+        // so this code should be as robust as we can make it.
+
+        // Update the MPTT pointers, if necessary.  We have to do this before we generate any
+        // cached paths!
+        if ($original->parent_id != $this->parent_id) {
+          parent::move_to($this->parent());
+        }
+
+        if ($original->parent_id != $this->parent_id || $original->name != $this->name) {
+          $this->_build_relative_caches();
+          // If there is a data file, then we want to preserve both the old data and the new data.
+          // (Third-party event handlers would like access to both). The old data file will be
+          // accessible via the $original item, and the new one via $this item. But in that case,
+          // we don't want to rename the original as below, because the old data would end up being
+          // clobbered by the new data file. Also, the rename isn't necessary, because the new item
+          // data is coming from the data file anyway. So we only perform the rename if there isn't
+          // a data file. Another way to solve this would be to copy the original file rather than
+          // conditionally rename it, but a copy would cost far more than the rename.
+          if (!isset($this->data_file)) {
+            @rename($original->file_path(), $this->file_path());
+          }
+          // Move all of the items associated data files
+          if ($this->is_album()) {
+            @rename(dirname($original->resize_path()), dirname($this->resize_path()));
+            @rename(dirname($original->thumb_path()), dirname($this->thumb_path()));
+          } else {
+            @rename($original->resize_path(), $this->resize_path());
+            @rename($original->thumb_path(), $this->thumb_path());
+          }
+
+          if ($original->parent_id != $this->parent_id) {
+            // This will result in 2 events since we'll still fire the item_updated event below
+            module::event("item_moved", $this, $original->parent());
+          }
+        }
+
+        // Changing the name, slug or parent ripples downwards
+        if ($this->is_album() &&
+            ($original->name != $this->name ||
+             $original->slug != $this->slug ||
+             $original->parent_id != $this->parent_id)) {
+          db::build()
+            ->update("items")
+            ->set("relative_url_cache", null)
+            ->set("relative_path_cache", null)
+            ->where("left_ptr", ">", $this->left_ptr)
+            ->where("right_ptr", "<", $this->right_ptr)
+            ->execute();
+        }
+
+        // Replace the data file, if requested.
+        if ($this->data_file && ($this->is_photo() || $this->is_movie())) {
+          copy($this->data_file, $this->file_path());
+          $this->thumb_dirty = 1;
+          $this->resize_dirty = 1;
+        }
+
+        module::event("item_updated", $original, $this);
+
+        if ($this->data_file) {
+          // Null out the data file variable here, otherwise this event will trigger another
+          // save() which will think that we're doing another file move.
+          $this->data_file = null;
+          if ($original->file_path() != $this->file_path()) {
+            @unlink($original->file_path());
+          }
+          module::event("item_updated_data_file", $this);
+        }
+      }
+    } else if (!empty($this->changed)) {
+      // Insignificant changes only.  Don't fire events or do any special checking to try to keep
+      // this lightweight.
+      parent::save();
+    }
+
+    return $this;
+  }
+
+  /**
+   * Check to see if there's another item that occupies the same name or slug that this item
+   * intends to use, and if so choose a new name/slug while preserving the extension.  Since this
+   * checks the name without its extension, it covers possible collisions with thumbs and resizes
+   * as well (e.g. between the thumbs of movie "foo.flv" and photo "foo.jpg").
+   */
+  private function _check_and_fix_conflicts() {
+    $suffix_num = 1;
+    $suffix = "";
+    if ($this->is_album()) {
+      while (db::build()
+             ->from("items")
+             ->where("parent_id", "=", $this->parent_id)
+             ->where("id", $this->id ? "<>" : "IS NOT", $this->id)
+             ->and_open()
+             ->where("name", "=", "{$this->name}{$suffix}")
+             ->or_where("slug", "=", "{$this->slug}{$suffix}")
+             ->close()
+             ->count_records()) {
+        $suffix = "-" . (($suffix_num <= 99) ? sprintf("%02d", $suffix_num++) : random::int());
+      }
+      if ($suffix) {
+        $this->name = "{$this->name}{$suffix}";
+        $this->slug = "{$this->slug}{$suffix}";
+        $this->relative_path_cache = null;
+        $this->relative_url_cache = null;
+      }
+    } else {
+      // Split the filename into its base and extension.  This uses a regexp similar to
+      // legal_file::change_extension (which isn't always the same as pathinfo).
+      if (preg_match("/^(.*)(\.[^\.\/]*?)$/", $this->name, $matches)) {
+        $base_name = $matches[1];
+        $extension = $matches[2]; // includes a leading dot
+      } else {
+        $base_name = $this->name;
+        $extension = "";
+      }
+      $base_name_escaped = Database::escape_for_like($base_name);
+      // Note: below query uses LIKE with wildcard % at end, which is still sargable (i.e. quick)
+      while (db::build()
+             ->from("items")
+             ->where("parent_id", "=", $this->parent_id)
+             ->where("id", $this->id ? "<>" : "IS NOT", $this->id)
+             ->and_open()
+             ->where("name", "LIKE", "{$base_name_escaped}{$suffix}.%")
+             ->or_where("slug", "=", "{$this->slug}{$suffix}")
+             ->close()
+             ->count_records()) {
+        $suffix = "-" . (($suffix_num <= 99) ? sprintf("%02d", $suffix_num++) : random::int());
+      }
+      if ($suffix) {
+        $this->name = "{$base_name}{$suffix}{$extension}";
+        $this->slug = "{$this->slug}{$suffix}";
+        $this->relative_path_cache = null;
+        $this->relative_url_cache = null;
+      }
+    }
+  }
+
+  /**
+   * Process the data file info.  Get its metadata and extension.
+   * If valid, use it to sanitize the item name and update the
+   * width, height, and mime type.
+   */
+  private function _process_data_file_info() {
+    try {
+      if ($this->is_photo()) {
+        list ($this->width, $this->height, $this->mime_type, $extension) =
+          photo::get_file_metadata($this->data_file);
+      } else if ($this->is_movie()) {
+        list ($this->width, $this->height, $this->mime_type, $extension) =
+          movie::get_file_metadata($this->data_file);
+      } else {
+        // Albums don't have data files.
+        $this->data_file = null;
+        return;
+      }
+
+      // Sanitize the name based on the idenified extension, but only set $this->name if different
+      // to ensure it isn't unnecessarily marked as "changed"
+      $name = legal_file::sanitize_filename($this->name, $extension, $this->type);
+      if ($this->name != $name) {
+        $this->name = $name;
+      }
+
+      // Data file valid - make sure the flag is reset to false.
+      $this->data_file_error = false;
+    } catch (Exception $e) {
+      // Data file invalid - set the flag so it's reported during item validation.
+      $this->data_file_error = true;
+    }
+  }
+
+  /**
+   * Return the Item_Model representing the cover for this album.
+   * @return Item_Model or null if there's no cover
+   */
+  public function album_cover() {
+    if (!$this->is_album()) {
+      return null;
+    }
+
+    if (empty($this->album_cover_item_id)) {
+      return null;
+    }
+
+    try {
+      return model_cache::get("item", $this->album_cover_item_id);
+    } catch (Exception $e) {
+      // It's possible (unlikely) that the item was deleted, if so keep going.
+      return null;
+    }
+  }
+
+  /**
+   * Find the position of the given child id in this album.  The resulting value is 1-indexed, so
+   * the first child in the album is at position 1.
+   *
+   * This method stands as a backward compatibility for gallery 3.0, and will
+   * be deprecated in version 3.1.
+   */
+  public function get_position($child, $where=array()) {
+    return item::get_position($child, $where);
+  }
+
+  /**
+   * Return an <img> tag for the thumbnail.
+   * @param array $extra_attrs  Extra attributes to add to the img tag
+   * @param int (optional) $max Maximum size of the thumbnail (default: null)
+   * @param boolean (optional) $center_vertically Center vertically (default: false)
+   * @return string
+   */
+  public function thumb_img($extra_attrs=array(), $max=null, $center_vertically=false) {
+    list ($height, $width) = $this->scale_dimensions($max);
+    if ($center_vertically && $max) {
+      // The constant is divide by 2 to calculate the file and 10 to convert to em
+      $margin_top = (int)(($max - $height) / 20);
+      $extra_attrs["style"] = "margin-top: {$margin_top}em";
+      $extra_attrs["title"] = $this->title;
+    }
+    $attrs = array_merge($extra_attrs,
+            array(
+              "src" => $this->thumb_url(),
+              "alt" => $this->title,
+              "width" => $width,
+              "height" => $height)
+            );
+    // html::image forces an absolute url which we don't want
+    return "<img" . html::attributes($attrs) . "/>";
+  }
+
+  /**
+   * Calculate the largest width/height that fits inside the given maximum, while preserving the
+   * aspect ratio.  Don't upscale.
+   * @param int $max Maximum size of the largest dimension
+   * @return array
+   */
+  public function scale_dimensions($max) {
+    $width = $this->thumb_width;
+    $height = $this->thumb_height;
+
+    if ($width <= $max && $height <= $max) {
+        return array($height, $width);
+    }
+
+    if ($height) {
+      if (isset($max)) {
+        if ($width > $height) {
+          $height = (int)($max * $height / $width);
+          $width = $max;
+        } else {
+          $width = (int)($max * $width / $height);
+          $height = $max;
+        }
+      }
+    } else {
+      // Missing thumbnail, can happen on albums with no photos yet.
+      // @todo we should enforce a placeholder for those albums.
+      $width = 0;
+      $height = 0;
+    }
+    return array($height, $width);
+  }
+
+  /**
+   * Return an <img> tag for the resize.
+   * @param array $extra_attrs  Extra attributes to add to the img tag
+   * @return string
+   */
+  public function resize_img($extra_attrs) {
+    $attrs = array_merge($extra_attrs,
+            array("src" => $this->resize_url(),
+                  "alt" => $this->title,
+                  "width" => $this->resize_width,
+                  "height" => $this->resize_height)
+            );
+    // html::image forces an absolute url which we don't want
+    return "<img" . html::attributes($attrs) . "/>";
+  }
+
+  /**
+   * Return a view for movies.  By default this is a Flowplayer v3 <script> tag, but
+   * movie_img events can override this and provide their own player/view.  If no player/view
+   * is found and the movie is unsupported by Flowplayer v3, this returns a simple download link.
+   * @param array $extra_attrs
+   * @return string
+   */
+  public function movie_img($extra_attrs) {
+    $max_size = module::get_var("gallery", "resize_size", 640);
+    $width = $this->width;
+    $height = $this->height;
+    if ($width == 0 || $height == 0) {
+      // Not set correctly, likely because ffmpeg isn't available.  Making the window 0x0 causes the
+      // video to be effectively unviewable.  So, let's guess: set width to max_size and guess a
+      // height (using 4:3 aspect ratio).  Once the video metadata is loaded, js in
+      // movieplayer.html.php will correct these values.
+      $width = $max_size;
+      $height = ceil($width * 3/4);
+    }
+    $attrs = array_merge(array("id" => "g-item-id-{$this->id}"), $extra_attrs,
+                         array("class" => "g-movie"));
+
+    // Run movie_img events, which can either:
+    //  - generate a view, which is used in place of the standard Flowplayer v3 player
+    //    (use view variable)
+    //  - alter the arguments sent to the standard player
+    //    (use fp_params and fp_config variables)
+    $movie_img = new stdClass();
+    $movie_img->max_size = $max_size;
+    $movie_img->width = $width;
+    $movie_img->height = $height;
+    $movie_img->attrs = $attrs;
+    $movie_img->url = $this->file_url(true);
+    $movie_img->filename = $this->name;
+    $movie_img->fp_params = array(); // additional Flowplayer params values (will be json encoded)
+    $movie_img->fp_config = array(); // additional Flowplayer config values (will be json encoded)
+    $movie_img->view = array();
+    module::event("movie_img", $movie_img, $this);
+
+    if (count($movie_img->view) > 0) {
+      // View generated - use it
+      $view = implode("\n", $movie_img->view);
+    } else {
+      // View NOT generated - see if filetype supported by Flowplayer v3
+      // Note that the extension list below is hard-coded and doesn't use the legal_file helper
+      // since anything else will not work in Flowplayer v3.
+      if (in_array(strtolower(pathinfo($movie_img->filename, PATHINFO_EXTENSION)),
+                   array("flv", "mp4", "m4v", "mov", "f4v"))) {
+        // Filetype supported by Flowplayer v3 - use it (default)
+        $view = new View("movieplayer.html");
+        $view->max_size = $movie_img->max_size;
+        $view->width = $movie_img->width;
+        $view->height = $movie_img->height;
+        $view->attrs = $movie_img->attrs;
+        $view->url = $movie_img->url;
+        $view->fp_params = $movie_img->fp_params;
+        $view->fp_config = $movie_img->fp_config;
+      } else {
+        // Filetype NOT supported by Flowplayer v3 - display download link
+        $attrs = array_merge($attrs, array("style" => "width: {$max_size}px;",
+                                           "download" => $this->name, // forces download (HTML5 only)
+                                           "class" => "g-movie g-movie-download-link"));
+        $view = html::anchor($this->file_url(true), t("Click here to download item."), $attrs);
+      }
+    }
+    return $view;
+  }
+
+  /**
+   * Return all of the children of this album.  Unless you specify a specific sort order, the
+   * results will be ordered by this album's sort order.
+   *
+   * @chainable
+   * @param   integer  SQL limit
+   * @param   integer  SQL offset
+   * @param   array    additional where clauses
+   * @param   array    order_by
+   * @return array ORM
+   */
+  function children($limit=null, $offset=null, $where=array(), $order_by=null) {
+    if (empty($order_by)) {
+      $order_by = array($this->sort_column => $this->sort_order);
+      // Use id as a tie breaker
+      if ($this->sort_column != "id") {
+        $order_by["id"] = "ASC";
+      }
+    }
+    return parent::children($limit, $offset, $where, $order_by);
+  }
+
+  /**
+   * Return the children of this album, and all of it's sub-albums.  Unless you specify a specific
+   * sort order, the results will be ordered by this album's sort order.  Note that this
+   * album's sort order is imposed on all sub-albums, regardless of their sort order.
+   *
+   * @chainable
+   * @param   integer  SQL limit
+   * @param   integer  SQL offset
+   * @param   array    additional where clauses
+   * @return object ORM_Iterator
+   */
+  function descendants($limit=null, $offset=null, $where=array(), $order_by=null) {
+    if (empty($order_by)) {
+      $order_by = array($this->sort_column => $this->sort_order);
+      // Use id as a tie breaker
+      if ($this->sort_column != "id") {
+        $order_by["id"] = "ASC";
+      }
+    }
+    return parent::descendants($limit, $offset, $where, $order_by);
+  }
+
+  /**
+   * Specify our rules here so that we have access to the instance of this model.
+   */
+  public function validate(Validation $array=null) {
+    if (!$array) {
+      $this->rules = array(
+        "album_cover_item_id" => array("callbacks" => array(array($this, "valid_album_cover"))),
+        "description"         => array("rules"     => array("length[0,65535]")),
+        "mime_type"           => array("callbacks" => array(array($this, "valid_field"))),
+        "name"                => array("rules"     => array("length[0,255]", "required"),
+                                       "callbacks" => array(array($this, "valid_name"))),
+        "parent_id"           => array("callbacks" => array(array($this, "valid_parent"))),
+        "rand_key"            => array("rule"      => array("decimal")),
+        "slug"                => array("rules"     => array("length[0,255]", "required"),
+                                       "callbacks" => array(array($this, "valid_slug"))),
+        "sort_column"         => array("callbacks" => array(array($this, "valid_field"))),
+        "sort_order"          => array("callbacks" => array(array($this, "valid_field"))),
+        "title"               => array("rules"     => array("length[0,255]", "required")),
+        "type"                => array("callbacks" => array(array($this, "read_only"),
+                                                            array($this, "valid_field"))),
+      );
+
+      // Conditional rules
+      if ($this->id == 1) {
+        // We don't care about the name and slug for the root album.
+        $this->rules["name"] = array();
+        $this->rules["slug"] = array();
+      }
+
+      // Movies and photos must have data files.  Verify the data file on new items, or if it has
+      // been replaced.
+      if (($this->is_photo() || $this->is_movie()) && $this->data_file) {
+        $this->rules["name"]["callbacks"][] = array($this, "valid_data_file");
+      }
+    }
+
+    parent::validate($array);
+  }
+
+  /**
+   * Validate that the desired slug does not conflict.
+   */
+  public function valid_slug(Validation $v, $field) {
+    if (preg_match("/[^A-Za-z0-9-_]/", $this->slug)) {
+      $v->add_error("slug", "not_url_safe");
+    } else if (db::build()
+        ->from("items")
+        ->where("parent_id", "=", $this->parent_id)
+        ->where("id", "<>", $this->id)
+        ->where("slug", "=", $this->slug)
+        ->count_records()) {
+      $v->add_error("slug", "conflict");
+    }
+  }
+
+  /**
+   * Validate the item name.  It can't conflict with other names, can't contain slashes or
+   * trailing periods.
+   */
+  public function valid_name(Validation $v, $field) {
+    if (strpos($this->name, "/") !== false) {
+      $v->add_error("name", "no_slashes");
+      return;
+    }
+
+    if (rtrim($this->name, ".") !== $this->name) {
+      $v->add_error("name", "no_trailing_period");
+      return;
+    }
+
+    // Do not accept files with double extensions, they can cause problems on some
+    // versions of Apache.
+    if (!$this->is_album() && substr_count($this->name, ".") > 1) {
+      $v->add_error("name", "illegal_data_file_extension");
+    }
+
+    if ($this->is_movie() || $this->is_photo()) {
+      $ext = pathinfo($this->name, PATHINFO_EXTENSION);
+
+      if (!$this->loaded() && !$ext) {
+        // New items must have an extension
+        $v->add_error("name", "illegal_data_file_extension");
+        return;
+      }
+
+      if ($this->is_photo() && !legal_file::get_photo_extensions($ext) ||
+          $this->is_movie() && !legal_file::get_movie_extensions($ext)) {
+        $v->add_error("name", "illegal_data_file_extension");
+      }
+    }
+
+    if ($this->is_album()) {
+      if (db::build()
+          ->from("items")
+          ->where("parent_id", "=", $this->parent_id)
+          ->where("name", "=", $this->name)
+          ->merge_where($this->id ? array(array("id", "<>", $this->id)) : null)
+          ->count_records()) {
+        $v->add_error("name", "conflict");
+        return;
+      }
+    } else {
+      if (preg_match("/^(.*)(\.[^\.\/]*?)$/", $this->name, $matches)) {
+        $base_name = $matches[1];
+      } else {
+        $base_name = $this->name;
+      }
+      $base_name_escaped = Database::escape_for_like($base_name);
+      if (db::build()
+          ->from("items")
+          ->where("parent_id", "=", $this->parent_id)
+          ->where("name", "LIKE", "{$base_name_escaped}.%")
+          ->merge_where($this->id ? array(array("id", "<>", $this->id)) : null)
+          ->count_records()) {
+        $v->add_error("name", "conflict");
+        return;
+      }
+    }
+
+    if ($this->parent_id == 1 && Kohana::auto_load("{$this->slug}_Controller")) {
+      $v->add_error("slug", "reserved");
+      return;
+    }
+  }
+
+  /**
+   * Make sure that the data file is well formed (it exists and isn't empty).
+   */
+  public function valid_data_file(Validation $v, $field) {
+    if (!is_file($this->data_file)) {
+      $v->add_error("name", "bad_data_file_path");
+    } else if (filesize($this->data_file) == 0) {
+      $v->add_error("name", "empty_data_file");
+    } else if ($this->data_file_error) {
+      $v->add_error("name", "invalid_data_file");
+    }
+  }
+
+  /**
+   * Make sure that the parent id refers to an album.
+   */
+  public function valid_parent(Validation $v, $field) {
+    if ($this->id == 1) {
+      if ($this->parent_id != 0) {
+        $v->add_error("parent_id", "invalid");
+      }
+    } else {
+      $query = db::build()
+        ->from("items")
+        ->where("id", "=", $this->parent_id)
+        ->where("type", "=", "album");
+
+      // If this is an existing item, make sure the new parent is not part of our hierarchy
+      if ($this->loaded()) {
+        $query->and_open()
+          ->where("left_ptr", "<", $this->left_ptr)
+          ->or_where("right_ptr", ">", $this->right_ptr)
+          ->close();
+      }
+
+      if ($query->count_records() != 1) {
+        $v->add_error("parent_id", "invalid");
+      }
+    }
+  }
+
+  /**
+   * Make sure the album cover item id refers to a valid item, or is null.
+   */
+  public function valid_album_cover(Validation $v, $field) {
+    if ($this->id == 1) {
+      return;
+    }
+
+    if ($this->album_cover_item_id && ($this->is_photo() || $this->is_movie() ||
+        db::build()
+        ->from("items")
+        ->where("id", "=", $this->album_cover_item_id)
+        ->where("type", "<>", "album")
+        ->count_records() != 1)) {
+      $v->add_error("album_cover_item_id", "invalid_item");
+    }
+  }
+
+  /**
+   * Make sure that the type is valid.
+   */
+  public function valid_field(Validation $v, $field) {
+    switch($field) {
+    case "mime_type":
+      if ($this->is_movie()) {
+        $legal_values = legal_file::get_movie_types();
+      } else if ($this->is_photo()) {
+        $legal_values = legal_file::get_photo_types();
+      }
+      break;
+
+    case "sort_column":
+      if (!array_key_exists($this->sort_column, $this->object)) {
+        $v->add_error($field, "invalid");
+      }
+      break;
+
+    case "sort_order":
+      $legal_values = array("ASC", "DESC", "asc", "desc");
+      break;
+
+    case "type":
+      $legal_values = array("album", "photo", "movie");
+      break;
+
+    default:
+      $v->add_error($field, "unvalidated_field");
+      break;
+    }
+
+    if (isset($legal_values) && !in_array($this->$field, $legal_values)) {
+      $v->add_error($field, "invalid");
+    }
+  }
+
+  /**
+   * This field cannot be changed after it's been set.
+   */
+  public function read_only(Validation $v, $field) {
+    if ($this->loaded() && isset($this->changed[$field])) {
+      $v->add_error($field, "read_only");
+    }
+  }
+
+  /**
+   * Same as ORM::as_array() but convert id fields into their RESTful form.
+   *
+   * @param array if specified, only return the named fields
+   */
+  public function as_restful_array($fields=array()) {
+    if ($fields) {
+      $data = array();
+      foreach ($fields as $field) {
+        if (isset($this->object[$field])) {
+          $data[$field] = $this->__get($field);
+        }
+      }
+      $fields = array_flip($fields);
+    } else {
+      $data = $this->as_array();
+    }
+
+    // Convert item ids to rest URLs for consistency
+    if (empty($fields) || isset($fields["parent"])) {
+      if ($tmp = $this->parent()) {
+        $data["parent"] = rest::url("item", $tmp);
+      }
+      unset($data["parent_id"]);
+    }
+
+    if (empty($fields) || isset($fields["album_cover"])) {
+      if ($tmp = $this->album_cover()) {
+        $data["album_cover"] = rest::url("item", $tmp);
+      }
+      unset($data["album_cover_item_id"]);
+    }
+
+    if (empty($fields) || isset($fields["web_url"])) {
+      $data["web_url"] = $this->abs_url();
+    }
+
+    if (!$this->is_album()) {
+      if (access::can("view_full", $this)) {
+        if (empty($fields) || isset($fields["file_url"])) {
+          $data["file_url"] = rest::url("data", $this, "full");
+        }
+        if (empty($fields) || isset($fields["file_size"])) {
+          $data["file_size"] = filesize($this->file_path());
+        }
+        if (access::user_can(identity::guest(), "view_full", $this)) {
+          if (empty($fields) || isset($fields["file_url_public"])) {
+            $data["file_url_public"] = $this->file_url(true);
+          }
+        }
+      }
+    }
+
+    if ($this->is_photo()) {
+      if (empty($fields) || isset($fields["resize_url"])) {
+        $data["resize_url"] = rest::url("data", $this, "resize");
+      }
+      if (empty($fields) || isset($fields["resize_size"])) {
+        $data["resize_size"] = filesize($this->resize_path());
+      }
+      if (access::user_can(identity::guest(), "view", $this)) {
+        if (empty($fields) || isset($fields["resize_url_public"])) {
+          $data["resize_url_public"] = $this->resize_url(true);
+        }
+      }
+    }
+
+    if ($this->has_thumb()) {
+      if (empty($fields) || isset($fields["thumb_url"])) {
+        $data["thumb_url"] = rest::url("data", $this, "thumb");
+      }
+      if (empty($fields) || isset($fields["thumb_size"])) {
+        $data["thumb_size"] = filesize($this->thumb_path());
+      }
+      if (access::user_can(identity::guest(), "view", $this)) {
+        if (empty($fields) || isset($fields["thumb_url_public"])) {
+          $data["thumb_url_public"] = $this->thumb_url(true);
+        }
+      }
+    }
+
+    if (empty($fields) || isset($fields["can_edit"])) {
+      $data["can_edit"] = access::can("edit", $this);
+    }
+
+    if (empty($fields) || isset($fields["can_add"])) {
+      $data["can_add"] = access::can("add", $this);
+    }
+
+    // Elide some internal-only data that is going to cause confusion in the client.
+    foreach (array("relative_path_cache", "relative_url_cache", "left_ptr", "right_ptr",
+                   "thumb_dirty", "resize_dirty", "weight") as $key) {
+      unset($data[$key]);
+    }
+    return $data;
+  }
+
+  /**
+   * Increments the view counter of this item
+   * We can't use math in ORM or the query builder, so do this by hand.  It's important
+   * that we do this with math, otherwise concurrent accesses will damage accuracy.
+   */
+  public function increment_view_count() {
+    db::query("UPDATE {items} SET `view_count` = `view_count` + 1 WHERE `id` = $this->id")
+      ->execute();
+  }
+
+  private function _cache_buster($path) {
+    return "?m=" . (string)(file_exists($path) ? filemtime($path) : 0);
+  }
+}
diff --git a/modules/gallery/models/log.php b/modules/gallery/models/log.php
new file mode 100644
index 0000000..b01bcd2
--- /dev/null
+++ b/modules/gallery/models/log.php
@@ -0,0 +1,38 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Log_Model_Core extends ORM {
+  /**
+   * @see ORM::__get()
+   */
+  public function __get($column) {
+    if ($column == "user") {
+      // This relationship depends on an outside module, which may not be present so handle
+      // failures gracefully.
+      try {
+        return identity::lookup_user($this->user_id);
+      } catch (Exception $e) {
+        Kohana_Log::add("alert", "Unable to load user with id $this->user_id");
+        return null;
+      }
+    } else {
+      return parent::__get($column);
+    }
+  }
+}
diff --git a/modules/gallery/models/message.php b/modules/gallery/models/message.php
new file mode 100644
index 0000000..0fa803d
--- /dev/null
+++ b/modules/gallery/models/message.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Message_Model_Core extends ORM {
+}
diff --git a/modules/gallery/models/module.php b/modules/gallery/models/module.php
new file mode 100644
index 0000000..0b2fb77
--- /dev/null
+++ b/modules/gallery/models/module.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Module_Model_Core extends ORM {
+}
diff --git a/modules/gallery/models/outgoing_translation.php b/modules/gallery/models/outgoing_translation.php
new file mode 100644
index 0000000..66e2091
--- /dev/null
+++ b/modules/gallery/models/outgoing_translation.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Outgoing_Translation_Model_Core extends ORM {
+}
diff --git a/modules/gallery/models/permission.php b/modules/gallery/models/permission.php
new file mode 100644
index 0000000..26d1ee7
--- /dev/null
+++ b/modules/gallery/models/permission.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Permission_Model_Core extends ORM {
+}
diff --git a/modules/gallery/models/task.php b/modules/gallery/models/task.php
new file mode 100644
index 0000000..31332ba
--- /dev/null
+++ b/modules/gallery/models/task.php
@@ -0,0 +1,86 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Task_Model_Core extends ORM {
+  public function get($key, $default=null) {
+    $context = unserialize($this->context);
+    if (array_key_exists($key, $context)) {
+      return $context[$key];
+    } else {
+      return $default;
+    }
+  }
+
+  public function set($key, $value=null) {
+    $context = unserialize($this->context);
+    $context[$key] = $value;
+    $this->context = serialize($context);
+  }
+
+  public function save() {
+    if (!empty($this->changed)) {
+      $this->updated = time();
+    }
+    return parent::save();
+  }
+
+  public function delete($ignored_id=null) {
+    Cache::instance()->delete($this->_cache_key());
+    return parent::delete();
+  }
+
+  public function owner() {
+    return identity::lookup_user($this->owner_id);
+  }
+
+  /**
+   * Log a message to the task log.
+   * @params $msg mixed a string or array of strings
+   */
+  public function log($msg) {
+    $key = $this->_cache_key();
+    $log = Cache::instance()->get($key);
+
+    if (is_array($msg)) {
+      $msg = implode("\n", $msg);
+    }
+
+    // Save for 30 days.
+    $log .= !empty($log) ? "\n" : "";
+    Cache::instance()->set($key, "$log{$msg}",
+                           array("task", "log", "import"), 2592000);
+  }
+
+  /**
+   * Retrieve the cached log information for this task.
+   * @returns the log data or null if there is no log data
+   */
+  public function get_log() {
+    $log_data = Cache::instance()->get($this->_cache_key());
+    return  $log_data !== null ? $log_data : false;
+  }
+
+  /**
+   * Build the task cache key
+   * @returns the key to use in access the cache
+   */
+  private function _cache_key() {
+    return md5("$this->id; $this->name; $this->callback");
+  }
+}
\ No newline at end of file
diff --git a/modules/gallery/models/theme.php b/modules/gallery/models/theme.php
new file mode 100644
index 0000000..2e4d932
--- /dev/null
+++ b/modules/gallery/models/theme.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Theme_Model_Core extends ORM {
+}
\ No newline at end of file
diff --git a/modules/gallery/models/var.php b/modules/gallery/models/var.php
new file mode 100644
index 0000000..7049e7d
--- /dev/null
+++ b/modules/gallery/models/var.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Var_Model_Core extends ORM {
+}
diff --git a/modules/gallery/module.info b/modules/gallery/module.info
new file mode 100644
index 0000000..7f49b72
--- /dev/null
+++ b/modules/gallery/module.info
@@ -0,0 +1,7 @@
+name = "Gallery 3"
+description = "Gallery core application"
+version = 57
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:gallery"
+discuss_url = "http://galleryproject.org/forum_module_gallery"
diff --git a/modules/gallery/vendor/joomla/crypt.php b/modules/gallery/vendor/joomla/crypt.php
new file mode 100644
index 0000000..c7d477d
--- /dev/null
+++ b/modules/gallery/vendor/joomla/crypt.php
@@ -0,0 +1,151 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * @package     Joomla.Platform
+ * @subpackage  Crypt
+ *
+ * @copyright   Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
+ * @license     GNU General Public License version 2 or later; see LICENSE
+ */
+
+// defined('JPATH_PLATFORM') or die;
+
+/**
+ * JCrypt is a Joomla Platform class for handling basic encryption/decryption of data.
+ *
+ * @package     Joomla.Platform
+ * @subpackage  Crypt
+ * @since       12.1
+ */
+class JCrypt
+{
+	/**
+	 * Generate random bytes.
+	 *
+	 * @param   integer  $length  Length of the random data to generate
+	 *
+	 * @return  string  Random binary data
+	 *
+	 * @since  12.1
+	 */
+	public static function genRandomBytes($length = 16)
+	{
+		$sslStr = '';
+		/*
+		 * if a secure randomness generator exists and we don't
+		 * have a buggy PHP version use it.
+		 */
+		if (
+			function_exists('openssl_random_pseudo_bytes')
+			&& (version_compare(PHP_VERSION, '5.3.4') >= 0
+				|| substr(PHP_OS, 0, 3) !== 'WIN'
+			)
+		)
+		{
+			$sslStr = openssl_random_pseudo_bytes($length, $strong);
+			if ($strong)
+			{
+				return $sslStr;
+			}
+		}
+
+		/*
+		 * Collect any entropy available in the system along with a number
+		 * of time measurements of operating system randomness.
+		 */
+		$bitsPerRound = 2;
+		$maxTimeMicro = 400;
+		$shaHashLength = 20;
+		$randomStr = '';
+		$total = $length;
+
+		// Check if we can use /dev/urandom.
+		$urandom = false;
+		$handle = null;
+		if (function_exists('stream_set_read_buffer') && @is_readable('/dev/urandom'))
+		{
+			$handle = @fopen('/dev/urandom', 'rb');
+			if ($handle)
+			{
+				$urandom = true;
+			}
+		}
+
+		while ($length > strlen($randomStr))
+		{
+			$bytes = ($total > $shaHashLength)? $shaHashLength : $total;
+			$total -= $bytes;
+			/*
+			 * Collect any entropy available from the PHP system and filesystem.
+			 * If we have ssl data that isn't strong, we use it once.
+			 */
+			$entropy = rand() . uniqid(mt_rand(), true) . $sslStr;
+			$entropy .= implode('', @fstat(fopen( __FILE__, 'r')));
+			$entropy .= memory_get_usage();
+			$sslStr = '';
+			if ($urandom)
+			{
+				stream_set_read_buffer($handle, 0);
+				$entropy .= @fread($handle, $bytes);
+			}
+			else
+			{
+				/*
+				 * There is no external source of entropy so we repeat calls
+				 * to mt_rand until we are assured there's real randomness in
+				 * the result.
+				 *
+				 * Measure the time that the operations will take on average.
+				 */
+				$samples = 3;
+				$duration = 0;
+				for ($pass = 0; $pass < $samples; ++$pass)
+				{
+					$microStart = microtime(true) * 1000000;
+					$hash = sha1(mt_rand(), true);
+					for ($count = 0; $count < 50; ++$count)
+					{
+						$hash = sha1($hash, true);
+					}
+					$microEnd = microtime(true) * 1000000;
+					$entropy .= $microStart . $microEnd;
+					if ($microStart > $microEnd) {
+						$microEnd += 1000000;
+					}
+					$duration += $microEnd - $microStart;
+				}
+				$duration = $duration / $samples;
+
+				/*
+				 * Based on the average time, determine the total rounds so that
+				 * the total running time is bounded to a reasonable number.
+				 */
+				$rounds = (int)(($maxTimeMicro / $duration) * 50);
+
+				/*
+				 * Take additional measurements. On average we can expect
+				 * at least $bitsPerRound bits of entropy from each measurement.
+				 */
+				$iter = $bytes * (int) ceil(8 / $bitsPerRound);
+				for ($pass = 0; $pass < $iter; ++$pass)
+				{
+					$microStart = microtime(true);
+					$hash = sha1(mt_rand(), true);
+					for ($count = 0; $count < $rounds; ++$count)
+					{
+						$hash = sha1($hash, true);
+					}
+					$entropy .= $microStart . microtime(true);
+				}
+			}
+
+			$randomStr .= sha1($entropy, true);
+		}
+
+		if ($urandom)
+		{
+			@fclose($handle);
+		}
+
+		return substr($randomStr, 0, $length);
+	}
+}
diff --git a/modules/gallery/views/admin_advanced_settings.html.php b/modules/gallery/views/admin_advanced_settings.html.php
new file mode 100644
index 0000000..6745f0d
--- /dev/null
+++ b/modules/gallery/views/admin_advanced_settings.html.php
@@ -0,0 +1,57 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-admin-advanced-settings" class="g-block">
+  <h1> <?= t("Advanced settings") ?> </h1>
+  <p>
+    <?= t("Here are internal Gallery configuration settings.  Most of these settings are accessible elsewhere in the administrative console.") ?>
+  </p>
+
+  <ul id="g-action-status" class="g-message-block">
+    <li class="g-warning"><?= t("Change these values at your own risk!") ?></li>
+  </ul>
+
+  <?= t("Filter:") ?> <input id="g-admin-advanced-settings-filter" type="text"></input>
+  <div class="g-block-content">
+    <table>
+      <tr>
+        <th> <?= t("Module") ?> </th>
+        <th> <?= t("Name") ?> </th>
+        <th> <?= t("Value") ?></th>
+      </tr>
+      <? foreach ($vars as $var): ?>
+      <tr class="setting-row <?= text::alternate("g-odd", "g-even") ?>">
+        <td> <?= html::clean($var->module_name) ?> </td>
+        <td> <?= html::clean($var->name) ?> </td>
+        <td>
+          <a href="<?= url::site("admin/advanced_settings/edit/$var->module_name/" . html::clean($var->name)) ?>"
+            class="g-dialog-link"
+            title="<?= t("Edit %var (%module_name)", array("var" => $var->name, "module_name" => $var->module_name))->for_html_attr() ?>">
+            <? if (!isset($var->value) || $var->value === ""): ?>
+            <i> <?= t("empty") ?> </i>
+            <? else: ?>
+            <?= html::clean($var->value) ?>
+            <? endif ?>
+        </a>
+        </td>
+      </tr>
+      <? endforeach ?>
+    </table>
+  </div>
+
+  <script>
+    $(document).ready(function() {
+      $("#g-admin-advanced-settings-filter").keyup(function() {
+        var filter = $(this).attr("value");
+        if (filter) {
+          $("tr.setting-row").fadeOut("fast");
+          $("tr.setting-row").each(function() {
+            if ($(this).text().indexOf(filter) > 0) {
+              $(this).stop().show();
+            }
+          });
+        } else {
+          $("tr.setting-row").show();
+        }
+      });
+    });
+  </script>
+</div>
diff --git a/modules/gallery/views/admin_block_log_entries.html.php b/modules/gallery/views/admin_block_log_entries.html.php
new file mode 100644
index 0000000..5a8ed23
--- /dev/null
+++ b/modules/gallery/views/admin_block_log_entries.html.php
@@ -0,0 +1,15 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul>
+  <? foreach ($entries as $entry): ?>
+  <li class="<?= log::severity_class($entry->severity) ?>" style="direction: ltr">
+    <? if ($entry->user->guest): ?>
+    </span><?= html::clean($entry->user->name) ?></span>
+    <? else: ?>
+    <a href="<?= user_profile::url($entry->user->id) ?>"><?= html::clean($entry->user->name) ?></a>
+    <? endif ?>
+    <?= gallery::date_time($entry->timestamp) ?>
+    <?= $entry->message ?>
+    <?= $entry->html ?>
+  </li>
+  <? endforeach ?>
+</ul>
diff --git a/modules/gallery/views/admin_block_news.html.php b/modules/gallery/views/admin_block_news.html.php
new file mode 100644
index 0000000..cb276ae
--- /dev/null
+++ b/modules/gallery/views/admin_block_news.html.php
@@ -0,0 +1,11 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul>
+  <? foreach ($feed as $entry): ?>
+  <li>
+    <a href="<?= $entry["link"] ?>"><?= $entry["title"] ?></a>
+    <p>
+      <?= text::limit_words(strip_tags($entry["description"]), 25); ?>
+    </p>
+  </li>
+  <? endforeach ?>
+</ul>
diff --git a/modules/gallery/views/admin_block_photo_stream.html.php b/modules/gallery/views/admin_block_photo_stream.html.php
new file mode 100644
index 0000000..f9725ee
--- /dev/null
+++ b/modules/gallery/views/admin_block_photo_stream.html.php
@@ -0,0 +1,14 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul>
+<? foreach ($photos as $photo): ?>
+  <li class="g-item g-photo">
+    <a href="<?= $photo->url() ?>" title="<?= html::purify($photo->title)->for_html_attr() ?>">
+      <img <?= photo::img_dimensions($photo->width, $photo->height, 72) ?>
+        src="<?= $photo->thumb_url() ?>" alt="<?= html::purify($photo->title)->for_html_attr() ?>" />
+    </a>
+  </li>
+<? endforeach ?>
+</ul>
+<p>
+  <?= t("Recent photos added to your Gallery") ?>
+</p>
diff --git a/modules/gallery/views/admin_block_platform.html.php b/modules/gallery/views/admin_block_platform.html.php
new file mode 100644
index 0000000..9a594fa
--- /dev/null
+++ b/modules/gallery/views/admin_block_platform.html.php
@@ -0,0 +1,24 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul>
+  <li>
+    <?= t("Host name: %host_name", array("host_name" => php_uname("n"))) ?>
+  </li>
+  <li>
+    <?= t("Operating system: %os %version", array("os" => php_uname("s"), "version" => php_uname("r"))) ?>
+  </li>
+  <li>
+    <?= t("Apache: %apache_version", array("apache_version" => function_exists("apache_get_version") ? apache_get_version() : t("Unknown"))) ?>
+  </li>
+  <li>
+    <?= t("PHP: %php_version", array("php_version" => phpversion())) ?>
+  </li>
+  <li>
+    <?= t("MySQL: %mysql_version", array("mysql_version" => Database::instance()->query("SELECT version() as v")->current()->v)) ?>
+  </li>
+  <li>
+    <?= t("Server load: %load_average", array("load_average" => join(" ", sys_getloadavg()))) ?>
+  </li>
+  <li>
+    <?= t("Graphics toolkit: %toolkit", array("toolkit" => module::get_var("gallery", "graphics_toolkit"))) ?>
+  </li>
+</ul>
diff --git a/modules/gallery/views/admin_block_stats.html.php b/modules/gallery/views/admin_block_stats.html.php
new file mode 100644
index 0000000..c8c5476
--- /dev/null
+++ b/modules/gallery/views/admin_block_stats.html.php
@@ -0,0 +1,12 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul>
+  <li>
+    <?= t("Version: %version", array("version" => gallery::version_string())) ?>
+  </li>
+  <li>
+    <?= t("Albums: %count", array("count" => $album_count)) ?>
+  </li>
+  <li>
+    <?= t("Photos: %count", array("count" => $photo_count)) ?>
+  </li>
+</ul>
diff --git a/modules/gallery/views/admin_block_welcome.html.php b/modules/gallery/views/admin_block_welcome.html.php
new file mode 100644
index 0000000..d3765d1
--- /dev/null
+++ b/modules/gallery/views/admin_block_welcome.html.php
@@ -0,0 +1,20 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<p>
+  <?= t("This is your administration dashboard and it provides a quick overview of status messages, recent updates, and frequently used options. Add or remove blocks and rearrange them to tailor to your needs. The admin menu provides quick access to all of Gallery 3's options and settings. Here are a few of the most used options to get you started.") ?>
+</p>
+<ul class="g-text">
+  <li>
+    <?= t("General Settings - choose your <a href=\"%graphics_url\">graphics</a> and <a href=\"%language_url\">language</a> settings.",
+          array("graphics_url" => html::mark_clean(url::site("admin/graphics")),
+                "language_url" => html::mark_clean(url::site("admin/languages")))) ?>
+  </li>
+  <li>
+    <?= t("Appearance - <a href=\"%theme_url\">choose a theme</a>, or <a href=\"%theme_options_url\">customize the way it looks</a>.",
+          array("theme_url" => html::mark_clean(url::site("admin/themes")),
+                "theme_options_url" => html::mark_clean(url::site("admin/theme_options")))) ?>
+  </li>
+  <li>
+    <?= t("Customize - <a href=\"%modules_url\">install modules</a> to add cool features!",
+          array("modules_url" => html::mark_clean(url::site("admin/modules")))) ?>
+  </li>
+</ul>
diff --git a/modules/gallery/views/admin_dashboard.html.php b/modules/gallery/views/admin_dashboard.html.php
new file mode 100644
index 0000000..cf90ef2
--- /dev/null
+++ b/modules/gallery/views/admin_dashboard.html.php
@@ -0,0 +1,43 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  update_blocks = function() {
+    $.get(<?= html::js_string(url::site("admin/dashboard/reorder")) ?>,
+          {"csrf": "<?= $csrf ?>",
+           "dashboard_center[]": $("#g-admin-dashboard").sortable(
+             "toArray", {attribute: "block_id"}),
+           "dashboard_sidebar[]": $("#g-admin-dashboard-sidebar").sortable(
+             "toArray", {attribute: "block_id"})});
+  };
+
+  $(document).ready(function(){
+    $("#g-admin-dashboard .g-block .ui-widget-header").addClass("g-draggable");
+    $("#g-admin-dashboard").sortable({
+      connectWith: ["#g-admin-dashboard-sidebar"],
+      cursor: "move",
+      handle: $(".ui-widget-header"),
+      opacity: 0.6,
+      placeholder: "g-target",
+      stop: update_blocks
+    });
+
+    $("#g-admin-dashboard-sidebar .g-block .ui-widget-header").addClass("g-draggable");
+    $("#g-admin-dashboard-sidebar").sortable({
+      connectWith: ["#g-admin-dashboard"],
+      cursor: "move",
+      handle: $(".ui-widget-header"),
+      opacity: 0.6,
+      placeholder: "g-target",
+      stop: update_blocks
+    });
+  });
+</script>
+<div>
+  <? if ($obsolete_modules_message): ?>
+  <p class="g-warning">
+    <?= $obsolete_modules_message ?>
+  </p>
+  <? endif ?>
+</div>
+<div id="g-admin-dashboard">
+  <?= $blocks ?>
+</div>
diff --git a/modules/gallery/views/admin_graphics.html.php b/modules/gallery/views/admin_graphics.html.php
new file mode 100644
index 0000000..1f45bb1
--- /dev/null
+++ b/modules/gallery/views/admin_graphics.html.php
@@ -0,0 +1,40 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  $(document).ready(function() {
+    $(".g-available .g-block").equal_heights();
+    select_toolkit = function(el) {
+      if (!$(this).hasClass("g-unavailable")) {
+        window.location = <?= html::js_string(url::site("admin/graphics/choose/__TK__?csrf=$csrf")) ?>
+          .replace("__TK__", $(this).attr("id"));
+      }
+    };
+    $("#g-admin-graphics div.g-available .g-block").click(select_toolkit);
+  });
+</script>
+
+<div id="g-admin-graphics" class="g-block ui-helper-clearfix">
+  <h1> <?= t("Graphics settings") ?> </h1>
+  <p>
+    <?= t("Gallery needs a graphics toolkit in order to manipulate your photos.  Please choose one from the list below.") ?>
+    <?= t("Can't decide which toolkit to choose?  <a href=\"%url\">We can help!</a>", array("url" => "http://codex.galleryproject.org/Gallery3:Choosing_A_Graphics_Toolkit")) ?>
+  </p>
+
+  <div class="g-block-content">
+    <h2> <?= t("Active toolkit") ?> </h2>
+    <? if ($active == "none"): ?>
+    <?= new View("admin_graphics_none.html") ?>
+    <? else: ?>
+    <?= new View("admin_graphics_$active.html", array("tk" => $tk->$active, "is_active" => true)) ?>
+    <? endif ?>
+
+    <div class="g-available">
+      <h2> <?= t("Available toolkits") ?> </h2>
+      <? foreach (array_keys((array)$tk) as $id): ?>
+      <? if ($id != $active): ?>
+      <?= new View("admin_graphics_$id.html", array("tk" => $tk->$id, "is_active" => false)) ?>
+      <? endif ?>
+      <? endforeach ?>
+    </div>
+  </div>
+</div>
+
diff --git a/modules/gallery/views/admin_graphics_gd.html.php b/modules/gallery/views/admin_graphics_gd.html.php
new file mode 100644
index 0000000..1cc9dc9
--- /dev/null
+++ b/modules/gallery/views/admin_graphics_gd.html.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="gd" class="g-block<?= $is_active ? " g-selected" : "" ?><?= $tk->installed ? " g-installed-toolkit" : " g-unavailable" ?>">
+  <img class="logo" width="170" height="110" src="<?= url::file("modules/gallery/images/gd.png"); ?>" alt="<? t("Visit the GD lib project site") ?>" />
+  <h3> <?= t("GD") ?> </h3>
+  <p>
+    <?= t("The GD graphics library is an extension to PHP commonly installed most webservers.  Please refer to the <a href=\"%url\">GD website</a> for more information.",
+        array("url" => "http://www.boutell.com/gd")) ?>
+  </p>
+  <? if ($tk->installed && $tk->rotate): ?>
+  <div class="g-module-status g-info">
+    <?= t("You have GD version %version.", array("version" => $tk->version)) ?>
+  </div>
+  <p>
+    <a class="g-button ui-state-default ui-corner-all"><?= t("Activate GD") ?></a>
+  </p>
+  <? elseif ($tk->installed): ?>
+  <? if ($tk->error): ?>
+  <p class="g-module-status g-warning">
+    <?= $tk->error ?>
+  </p>
+  <? endif ?>
+  <p>
+    <a class="g-button ui-state-default ui-corner-all"><?= t("Activate GD") ?></a>
+  </p>
+  <? else: ?>
+  <div class="g-module-status g-info">
+    <?= t("You do not have GD installed.") ?>
+  </div>
+  <? endif ?>
+</div>
diff --git a/modules/gallery/views/admin_graphics_graphicsmagick.html.php b/modules/gallery/views/admin_graphics_graphicsmagick.html.php
new file mode 100644
index 0000000..5dae144
--- /dev/null
+++ b/modules/gallery/views/admin_graphics_graphicsmagick.html.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="graphicsmagick" class="g-block<?= $is_active ? " g-selected" : "" ?><?= $tk->installed ? "  g-installed-toolkit" : " g-unavailable" ?>">
+  <img class="logo" width="107" height="76" src="<?= url::file("modules/gallery/images/graphicsmagick.png"); ?>" alt="<? t("Visit the GraphicsMagick project site") ?>" />
+  <h3> <?= t("GraphicsMagick") ?> </h3>
+  <p>
+    <?= t("GraphicsMagick is a standalone graphics program available on most Linux systems.  Please refer to the <a href=\"%url\">GraphicsMagick website</a> for more information.",
+        array("url" => "http://www.graphicsmagick.org")) ?>
+  </p>
+  <? if ($tk->installed): ?>
+  <div class="g-module-status g-info">
+    <?= t("GraphicsMagick version %version is available in %dir", array("version" => $tk->version, "dir" => $tk->dir)) ?>
+  </div>
+  <p>
+    <a class="g-button ui-state-default ui-corner-all"><?= t("Activate Graphics Magic") ?></a>
+  </p>
+  <? else: ?>
+  <div class="g-module-status g-warning">
+    <?= $tk->error ?>
+  </div>
+  <? endif ?>
+</div>
diff --git a/modules/gallery/views/admin_graphics_imagemagick.html.php b/modules/gallery/views/admin_graphics_imagemagick.html.php
new file mode 100644
index 0000000..9c1a990
--- /dev/null
+++ b/modules/gallery/views/admin_graphics_imagemagick.html.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="imagemagick" class="g-block<?= $is_active ? " g-selected" : "" ?><?= $tk->installed ? "  g-installed-toolkit" : " g-unavailable" ?>">
+  <img class="logo" width="114" height="118" src="<?= url::file("modules/gallery/images/imagemagick.jpg"); ?>" alt="<? t("Visit the ImageMagick project site") ?>" />
+  <h3> <?= t("ImageMagick") ?> </h3>
+  <p>
+    <?= t("ImageMagick is a standalone graphics program available on most Linux systems.  Please refer to the <a href=\"%url\">ImageMagick website</a> for more information.",
+        array("url" => "http://www.imagemagick.org")) ?>
+  </p>
+  <? if ($tk->installed): ?>
+  <div class="g-module-status g-info">
+    <?= t("ImageMagick version %version is available in %dir", array("version" => $tk->version, "dir" => $tk->dir)) ?>
+  </div>
+  <p>
+    <a class="g-button ui-state-default ui-corner-all"><?= t("Activate ImageMagick") ?></a>
+  </p>
+  <? elseif ($tk->error): ?>
+  <div class="g-module-status g-warning">
+    <?= $tk->error ?>
+  </div>
+  <? endif ?>
+</div>
diff --git a/modules/gallery/views/admin_graphics_none.html.php b/modules/gallery/views/admin_graphics_none.html.php
new file mode 100644
index 0000000..e0fc417
--- /dev/null
+++ b/modules/gallery/views/admin_graphics_none.html.php
@@ -0,0 +1,8 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+
+<div id="none" class="g-module-status g-warning g-block">
+  <h3> <?= t("No active toolkit") ?> </h3>
+  <p>
+    <?= t("We were unable to detect a graphics program.  You must install one of the toolkits below in order to use many Gallery features.") ?>
+  </p>
+</div>
diff --git a/modules/gallery/views/admin_languages.html.php b/modules/gallery/views/admin_languages.html.php
new file mode 100644
index 0000000..d6a9c22
--- /dev/null
+++ b/modules/gallery/views/admin_languages.html.php
@@ -0,0 +1,118 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  var old_default_locale = <?= html::js_string($default_locale) ?>;
+
+  $("#g-languages-form").ready(function() {
+    $("input[name='installed_locales[]']").change(function (event) {
+      if (this.checked) {
+        $("input[type='radio'][value='" + this.value + "']").enable();
+      } else {
+        if ($("input[type='radio'][value='" + this.value + "']").selected()) { // if you deselect your default language, switch to some other installed language
+          $("input[type='radio'][value='" + old_default_locale + "']").attr("checked", "checked");
+        }
+        $("input[type='radio'][value='" + this.value + "']").attr("disabled", "disabled");
+      }
+    });
+
+    $("#g-languages-form").ajaxForm({
+      dataType: "json",
+      success: function(data) {
+        if (data.result == "success") {
+          el = $('<a href="' + <?= html::js_string(url::site("admin/maintenance/start/gallery_task::update_l10n?csrf=$csrf")) ?> + '"></a>'); // this is a little hack to trigger the update_l10n task in a dialog
+          el.gallery_dialog();
+          el.trigger('click');
+        }
+      }
+    });
+  });
+</script>
+
+<div class="g-block">
+  <h1> <?= t("Languages and translation") ?> </h1>
+
+  <div class="g-block-content">
+
+    <div id="g-languages" class="g-block">
+      <h2> <?= t("Languages") ?> </h2>
+      <p>
+        <?= t("Install new languages, update installed ones and set the default language for your Gallery.") ?>
+      </p>
+
+      <div class="g-block-content ui-helper-clearfix">
+        <form id="g-languages-form" method="post" action="<?= url::site("admin/languages/save") ?>">
+          <?= access::csrf_form_field() ?>
+          <table class="g-left">
+            <tr>
+              <th> <?= t("Installed") ?> </th>
+              <th> <?= t("Language") ?> </th>
+              <th> <?= t("Default language") ?> </th>
+            </tr>
+            <? $i = 0 ?>
+            <? foreach ($available_locales as $code => $display_name):  ?>
+            <? if ($i == (int) (count($available_locales)/2)): ?>
+          </table>
+          <table class="g-left">
+            <tr>
+              <th> <?= t("Installed") ?> </th>
+              <th> <?= t("Language") ?> </th>
+              <th> <?= t("Default language") ?> </th>
+            </tr>
+            <? endif ?>
+            <tr class="<?= (isset($installed_locales[$code])) ? "g-available" : "" ?><?= ($default_locale == $code) ? " g-selected" : "" ?>">
+              <td> <?= form::checkbox("installed_locales[]", $code, isset($installed_locales[$code])) ?> </td>
+              <td> <?= $display_name ?> </td>
+              <td>
+              <?= form::radio("default_locale", $code, ($default_locale == $code), ((isset($installed_locales[$code]))?'':'disabled="disabled"') ) ?>
+              </td>
+            </tr>
+            <? $i++ ?>
+            <? endforeach ?>
+          </table>
+          <input type="submit" value="<?= t("Update languages")->for_html_attr() ?>" />
+        </form>
+      </div>
+    </div>
+
+    <div id="g-translations" class="g-block">
+      <h2> <?= t("Translations") ?> </h2>
+      <p>
+        <?= t("Create your own translations and share them with the rest of the Gallery community.") ?>
+      </p>
+
+      <div class="g-block-content">
+        <a href="http://codex.galleryproject.org/Gallery3:Localization" target="_blank"
+            class="g-right ui-state-default ui-corner-all ui-icon ui-icon-help"
+            title="<?= t("Localization documentation")->for_html_attr() ?>">
+          <?= t("Localization documentation") ?>
+        </a>
+
+        <h3><?= t("Translating Gallery") ?></h3>
+
+        <p><?= t("Follow these steps to begin translating Gallery.") ?></p>
+
+        <ol>
+          <li><?= t("Make sure the target language is installed and up to date (check above).") ?></li>
+          <li><?= t("Make sure you have selected the right target language (currently %default_locale).",
+               array("default_locale" => locales::display_name())) ?></li>
+          <li><?= t("Start the translation mode and the translation interface will appear at the bottom of each Gallery page.") ?></li>
+        </ol>
+        <a href="<?= url::site("l10n_client/toggle_l10n_mode?csrf=".access::csrf_token()) ?>"
+           class="g-button ui-state-default ui-corner-all ui-icon-left">
+          <span class="ui-icon ui-icon-power"></span>
+          <? if (Session::instance()->get("l10n_mode", false)): ?>
+          <?= t("Stop translation mode") ?>
+          <? else: ?>
+          <?= t("Start translation mode") ?>
+          <? endif ?>
+        </a>
+
+        <h3><?= t("Sharing your translations") ?></h3>
+          <p>
+            <?= t("Sharing your own translations with the Gallery community is easy. Please do!") ?>
+          </p>
+        <?= $share_translations_form ?>
+      </div>
+    </div>
+
+  </div>
+</div>
diff --git a/modules/gallery/views/admin_maintenance.html.php b/modules/gallery/views/admin_maintenance.html.php
new file mode 100644
index 0000000..230e935
--- /dev/null
+++ b/modules/gallery/views/admin_maintenance.html.php
@@ -0,0 +1,212 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-admin-maintenance" class="g-block">
+  <h1> <?= t("Maintenance") ?> </h1>
+  <div class="g-block-content">
+    <div id="g-maintenance-mode">
+      <p>
+      <?= t("When you're performing maintenance on your Gallery, you can enable <b>maintenance mode</b> which prevents any non-admin from accessing your Gallery.  Some of the tasks below will automatically put your Gallery in maintenance mode for you.") ?>
+      </p>
+      <ul id="g-action-status" class="g-message-block">
+        <? if (module::get_var("gallery", "maintenance_mode")): ?>
+        <li class="g-warning">
+          <?= t("Maintenance mode is <b>on</b>.  Non admins cannot access your Gallery.  <a href=\"%enable_maintenance_mode_url\">Turn off maintenance mode</a>", array("enable_maintenance_mode_url" => url::site("admin/maintenance/maintenance_mode/0?csrf=$csrf"))) ?>
+        </li>
+        <? else: ?>
+        <li class="g-info">
+          <?= t("Maintenance mode is off.  User access is permitted.  <a href=\"%enable_maintenance_mode_url\">Turn on maintenance mode</a>", array("enable_maintenance_mode_url" => url::site("admin/maintenance/maintenance_mode/1?csrf=$csrf"))) ?>
+        </li>
+        <? endif ?>
+      </ul>
+    </div>
+  </div>
+
+  <div class="g-block-content">
+    <div id="g-available-tasks">
+      <h2> <?= t("Maintenance tasks") ?> </h2>
+      <p>
+        <?= t("Occasionally your Gallery will require some maintenance.  Here are some tasks you can use to keep it running smoothly.") ?>
+      </p>
+      <table>
+        <tr>
+          <th>
+            <?= t("Name") ?>
+          </th>
+          <th>
+            <?= t("Description") ?>
+          </th>
+          <th>
+            <?= t("Action") ?>
+          </th>
+        </tr>
+        <? foreach ($task_definitions as $task): ?>
+        <tr class="<?= text::alternate("g-odd", "g-even") ?> <?= log::severity_class($task->severity) ?>">
+          <td class="<?= log::severity_class($task->severity) ?>">
+            <?= $task->name ?>
+          </td>
+          <td>
+            <?= $task->description ?>
+          </td>
+          <td>
+            <a href="<?= url::site("admin/maintenance/start/$task->callback?csrf=$csrf") ?>"
+              class="g-dialog-link g-button ui-icon-left ui-state-default ui-corner-all">
+              <?= t("run") ?>
+            </a>
+          </td>
+        </tr>
+        <? endforeach ?>
+      </table>
+    </div>
+
+    <? if ($running_tasks->count()): ?>
+    <div id="g-running-tasks">
+      <a href="<?= url::site("admin/maintenance/cancel_running_tasks?csrf=$csrf") ?>"
+         class="g-button g-right ui-icon-left ui-state-default ui-corner-all">
+        <?= t("cancel all running") ?></a>
+      <h2> <?= t("Running tasks") ?> </h2>
+      <table>
+        <tr>
+          <th>
+            <?= t("Last updated") ?>
+          </th>
+          <th>
+            <?= t("Name") ?>
+          </th>
+          <th>
+            <?= t("Status") ?>
+          </th>
+          <th>
+            <?= t("Info") ?>
+          </th>
+          <th>
+            <?= t("Owner") ?>
+          </th>
+          <th>
+            <?= t("Action") ?>
+          </th>
+        </tr>
+        <? foreach ($running_tasks as $task): ?>
+        <tr class="<?= text::alternate("g-odd", "g-even") ?> <?= $task->state == "stalled" ? "g-warning" : "" ?>">
+          <td class="<?= $task->state == "stalled" ? "g-warning" : "" ?>">
+            <?= gallery::date_time($task->updated) ?>
+          </td>
+          <td>
+            <?= $task->name ?>
+          </td>
+          <td>
+            <? if ($task->done): ?>
+            <? if ($task->state == "cancelled"): ?>
+            <?= t("Cancelled") ?>
+            <? endif ?>
+            <?= t("Close") ?>
+            <? elseif ($task->state == "stalled"): ?>
+            <?= t("Stalled") ?>
+            <? else: ?>
+            <?= t("%percent_complete% Complete", array("percent_complete" => $task->percent_complete)) ?>
+            <? endif ?>
+          </td>
+          <td>
+            <?= $task->status ?>
+          </td>
+          <td>
+            <?= html::clean($task->owner()->name) ?>
+          </td>
+          <td>
+            <? if ($task->state == "stalled"): ?>
+            <a class="g-dialog-link g-button ui-icon-left ui-state-default ui-corner-all"
+               href="<?= url::site("admin/maintenance/resume/$task->id?csrf=$csrf") ?>">
+              <?= t("resume") ?>
+            </a>
+            <? endif ?>
+            <? if ($task->get_log()): ?>
+            <a href="<?= url::site("admin/maintenance/show_log/$task->id?csrf=$csrf") ?>" class="g-dialog-link g-button ui-state-default ui-corner-all">
+              <?= t("view log") ?>
+            </a>
+            <? endif ?>
+            <a href="<?= url::site("admin/maintenance/cancel/$task->id?csrf=$csrf") ?>"
+               class="g-button ui-icon-left ui-state-default ui-corner-all">
+              <?= t("cancel") ?>
+            </a>
+          </td>
+        </tr>
+        <? endforeach ?>
+      </table>
+    </div>
+    <? endif ?>
+
+    <? if ($finished_tasks->count()): ?>
+    <div id="g-finished-tasks">
+      <a href="<?= url::site("admin/maintenance/remove_finished_tasks?csrf=$csrf") ?>"
+           class="g-button g-right ui-icon-left ui-state-default ui-corner-all">
+         <span class="ui-icon ui-icon-trash"></span><?= t("remove all finished") ?></a>
+      <h2> <?= t("Finished tasks") ?> </h2>
+      <table>
+        <tr>
+          <th>
+            <?= t("Last updated") ?>
+          </th>
+          <th>
+            <?= t("Name") ?>
+          </th>
+          <th>
+            <?= t("Status") ?>
+          </th>
+          <th>
+            <?= t("Info") ?>
+          </th>
+          <th>
+            <?= t("Owner") ?>
+          </th>
+          <th>
+            <?= t("Action") ?>
+          </th>
+        </tr>
+        <? foreach ($finished_tasks as $task): ?>
+        <tr class="<?= text::alternate("g-odd", "g-even") ?> <?= $task->state == "success" ? "g-success" : "g-error" ?>">
+          <td class="<?= $task->state == "success" ? "g-success" : "g-error" ?>">
+            <?= gallery::date_time($task->updated) ?>
+          </td>
+          <td>
+            <?= $task->name ?>
+          </td>
+          <td>
+            <? if ($task->state == "success"): ?>
+            <?= t("Success") ?>
+            <? elseif ($task->state == "error"): ?>
+            <?= t("Failed") ?>
+            <? elseif ($task->state == "cancelled"): ?>
+            <?= t("Cancelled") ?>
+            <? endif ?>
+          </td>
+          <td>
+            <?= $task->status ?>
+          </td>
+          <td>
+            <?= html::clean($task->owner()->name) ?>
+          </td>
+          <td>
+            <? if ($task->done): ?>
+            <a href="<?= url::site("admin/maintenance/remove/$task->id?csrf=$csrf") ?>" class="g-button ui-state-default ui-corner-all">
+              <?= t("remove") ?>
+            </a>
+            <? if ($task->get_log()): ?>
+            <a href="<?= url::site("admin/maintenance/show_log/$task->id?csrf=$csrf") ?>" class="g-dialog-link g-button ui-state-default ui-corner-all">
+              <?= t("view log") ?>
+            </a>
+            <? endif ?>
+            <? else: ?>
+            <a href="<?= url::site("admin/maintenance/resume/$task->id?csrf=$csrf") ?>" class="g-dialog-link g-button" ui-state-default ui-corner-all>
+              <?= t("resume") ?>
+            </a>
+            <a href="<?= url::site("admin/maintenance/cancel/$task->id?csrf=$csrf") ?>" class="g-button ui-state-default ui-corner-all">
+              <?= t("cancel") ?>
+            </a>
+            <? endif ?>
+            </ul>
+          </td>
+        </tr>
+        <? endforeach ?>
+      </table>
+    </div>
+    <? endif ?>
+  </div>
+</div>
diff --git a/modules/gallery/views/admin_maintenance_show_log.html.php b/modules/gallery/views/admin_maintenance_show_log.html.php
new file mode 100644
index 0000000..ecf882f
--- /dev/null
+++ b/modules/gallery/views/admin_maintenance_show_log.html.php
@@ -0,0 +1,19 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  dismiss = function() {
+    window.location.reload();
+  };
+  download = function() {
+    // send request
+    $('<form action="<?= url::site("admin/maintenance/save_log/$task->id?csrf=$csrf") ?>" method="post"></form>').
+appendTo('body').submit().remove();
+  };
+</script>
+<div id="g-task-log-dialog">
+  <h1> <?= $task->name ?> </h1>
+  <div class="g-task-log g-text-small">
+    <pre><?= html::purify($task->get_log()) ?></pre>
+  </div>
+  <button id="g-close" class="ui-state-default ui-corner-all" onclick="dismiss()"><?= t("Close") ?></button>
+  <button id="g-save" class="ui-state-default ui-corner-all" onclick="download()"><?= t("Download") ?></button>
+</div>
diff --git a/modules/gallery/views/admin_maintenance_task.html.php b/modules/gallery/views/admin_maintenance_task.html.php
new file mode 100644
index 0000000..013ac01
--- /dev/null
+++ b/modules/gallery/views/admin_maintenance_task.html.php
@@ -0,0 +1,84 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  var target_value;
+  var animation = null;
+  var delta = 1;
+  var consecutive_error_count = 0;
+  animate_progress_bar = function() {
+    var current_value = parseInt($(".g-progress-bar div").css("width").replace("%", ""));
+    if (target_value > current_value) {
+      // speed up
+      delta = Math.min(delta + 0.04, 3);
+    } else {
+      // slow down
+      delta = Math.max(delta - 0.05, 1);
+    }
+
+    if (target_value == 100) {
+      $(".g-progress-bar").progressbar("value", 100);
+    } else if (current_value != target_value || delta != 1) {
+      var new_value = Math.min(current_value + delta, target_value);
+      $(".g-progress-bar").progressbar("value", new_value);
+      animation = setTimeout(function() { animate_progress_bar(target_value); }, 100);
+    } else {
+      animation = null;
+      delta = 1;
+    }
+    $.fn.gallery_hover_init();
+  }
+
+  var FAILED_MSG = <?= t("Something went wrong...sorry!  <a>Retry</a> or check the task log for details")->for_js() ?>;
+  var ERROR_MSG = <?= t("Something went wrong!  Trying again in a moment... (__COUNT__)")->for_js() ?>;
+  update = function() {
+    $.ajax({
+      url: <?= html::js_string(url::site("admin/maintenance/run/$task->id?csrf=$csrf")) ?>,
+      dataType: "json",
+      success: function(data) {
+        target_value = data.task.percent_complete;
+        consecutive_error_count = 0;
+        if (!animation) {
+          animate_progress_bar();
+        }
+        $("#g-status").html("" + data.task.status);
+        if (data.task.done) {
+          $("#g-pause-button").hide();
+          $("#g-done-button").show();
+        } else {
+          setTimeout(update, 100);
+        }
+      },
+      error: function(req, textStatus, errorThrown) {
+        if (textStatus == "timeout" || textStatus == "parsererror") {
+          consecutive_error_count++;
+          if (consecutive_error_count == 5) {
+            $("#g-status").html(FAILED_MSG);
+            $("#g-pause-button").hide();
+            $("#g-done-button").show();
+            consecutive_error_count = 0;  // in case of a manual retry
+            $("#g-status a").attr("href", "javascript:update()");
+          } else {
+            $("#g-status").html(ERROR_MSG.replace("__COUNT__", consecutive_error_count));
+            // Give a little time to back off before retrying
+            setTimeout(update, 1500 * consecutive_error_count);
+          }
+        }
+      }
+    });
+  }
+  $(".g-progress-bar").progressbar({value: 0});
+  update();
+  dismiss = function() {
+    window.location.reload();
+  }
+</script>
+<div id="g-progress">
+  <h1> <?= $task->name ?> </h1>
+  <div class="g-progress-bar"></div>
+  <div id="g-status">
+    <?= t("Starting up...") ?>
+  </div>
+  <div class="g-text-right">
+    <button id="g-pause-button" class="ui-state-default ui-corner-all" onclick="dismiss()"><?= t("Pause") ?></button>
+    <button id="g-done-button" class="ui-state-default ui-corner-all" style="display: none" onclick="dismiss()"><?= t("Close") ?></button>
+  </div>
+</div>
diff --git a/modules/gallery/views/admin_modules.html.php b/modules/gallery/views/admin_modules.html.php
new file mode 100644
index 0000000..96576ae
--- /dev/null
+++ b/modules/gallery/views/admin_modules.html.php
@@ -0,0 +1,129 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="g-block ui-helper-clearfix">
+  <script type="text/javascript">
+  $("#g-module-update-form").ready(function() {
+    $("#g-module-update-form").ajaxForm({
+      dataType: "json",
+      success: function(data) {
+        if (data.reload) {
+          window.location = "<? url::site("/admin/modules") ?>";
+        } else {
+          $("body").append('<div id="g-dialog">' + data.dialog + '</div>');
+          $("#g-dialog").dialog({
+            bgiframe: true,
+            autoOpen: true,
+            autoResize: true,
+            modal: true,
+            resizable: false,
+            height: 400,
+            width: 500,
+            position: "center",
+            title: <?= t("Confirm module activation")->for_js() ?>,
+            buttons: {
+              <?= t("Continue")->for_js() ?>: function() {
+                $("form", this).submit();
+                $(".ui-dialog-buttonpane button:contains(" + <?= t("Continue")->for_js() ?> + ")")
+                  .attr("disabled", "disabled")
+                  .addClass("ui-state-disabled");
+              },
+              <?= t("Cancel")->for_js() ?>: function() {
+                $(this).dialog("destroy").remove();
+              }
+            }
+          });
+          if (!data.allow_continue) {
+            $(".ui-dialog-buttonpane button:contains(" + <?= t("Continue")->for_js() ?> + ")")
+              .attr("disabled", "disabled")
+              .addClass("ui-state-disabled");
+          }
+        }
+      }
+    });
+  });
+  </script>
+  <h1> <?= t("Gallery Modules") ?> </h1>
+  <p>
+    <?= t("Power up your Gallery by <a href=\"%url\">adding more modules</a>! Each module provides new cool features.", array("url" => "http://codex.galleryproject.org/Category:Gallery_3:Modules")) ?>
+  </p>
+
+  <? if ($obsolete_modules_message): ?>
+  <p class="g-warning">
+    <?= $obsolete_modules_message ?>
+  </p>
+  <? endif ?>
+
+  <div class="g-block-content">
+    <form id="g-module-update-form" method="post" action="<?= url::site("admin/modules/confirm") ?>">
+      <?= access::csrf_form_field() ?>
+      <table>
+        <tr>
+          <th> <?= t("Installed") ?> </th>
+          <th style="width: 8em"> <?= t("Name") ?> </th>
+          <th> <?= t("Version") ?> </th>
+          <th> <?= t("Description") ?> </th>
+          <th style="width: 60px"> <?= t("Details") ?> </th>
+        </tr>
+        <? foreach ($available as $module_name => $module_info):  ?>
+        <tr class="<?= text::alternate("g-odd", "g-even") ?>">
+          <? $data = array("name" => $module_name); ?>
+          <? if ($module_info->locked) $data["disabled"] = 1; ?>
+          <td> <?= form::checkbox($data, '1', module::is_active($module_name)) ?> </td>
+          <td> <?= t($module_info->name) ?> </td>
+          <td> <?= $module_info->version ?> </td>
+          <td> <?= t($module_info->description) ?> </td>
+          <td style="white-space: nowrap">
+            <ul class="g-buttonset">
+              <li>
+                <a target="_blank"
+                   <? if (isset($module_info->author_url)): ?>
+                   class="ui-state-default ui-icon ui-icon-person ui-corner-left"
+                   href="<?= $module_info->author_url ?>"
+                   <? else: ?>
+                   class="ui-state-disabled ui-icon ui-icon-person ui-corner-left"
+                   href="#"
+                   <? endif ?>
+
+                   <? if (isset($module_info->author_name)): ?>
+                   title="<?= $module_info->author_name ?>"
+                   <? endif ?>
+                   >
+                   <? if (isset($module_info->author_name)): ?>
+                   <?= $module_info->author_name ?>
+                   <? endif ?>
+                </a>
+              </li>
+              <li>
+                <a target="_blank"
+                   <? if (isset($module_info->info_url)): ?>
+                   class="ui-state-default ui-icon ui-icon-info"
+                   href="<?= $module_info->info_url ?>"
+                   <? else: ?>
+                   class="ui-state-disabled ui-icon ui-icon-info"
+                   href="#"
+                   <? endif ?>
+                   >
+                  <?= t("info") ?>
+                </a>
+              </li>
+              <li>
+                <a target="_blank"
+                   <? if (isset($module_info->discuss_url)): ?>
+                   class="ui-state-default ui-icon ui-icon-comment ui-corner-right"
+                   href="<?= $module_info->discuss_url ?>"
+                   <? else: ?>
+                   class="ui-state-disabled ui-icon ui-icon-comment ui-corner-right"
+                   href="#"
+                   <? endif ?>
+                   >
+                  <?= t("discuss") ?>
+                </a>
+              </li>
+            </ul>
+          </td>
+        </tr>
+        <? endforeach ?>
+      </table>
+      <input type="submit" value="<?= t("Update")->for_html_attr() ?>" />
+    </form>
+  </div>
+</div>
diff --git a/modules/gallery/views/admin_modules_confirm.html.php b/modules/gallery/views/admin_modules_confirm.html.php
new file mode 100644
index 0000000..8c4cb2b
--- /dev/null
+++ b/modules/gallery/views/admin_modules_confirm.html.php
@@ -0,0 +1,22 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="ui-helper-clearfix">
+  <p>
+    <?= t("The following issue(s) have been identified:") ?>
+  </p>
+
+  <div id="g-admin-modules-messages" class="g-block-content">
+   <ul>
+     <? foreach (array("error" => "g-error", "warn" => "g-warning") as $type => $css_class): ?>
+     <? foreach ($messages[$type] as $message): ?>
+     <li class="<?= $css_class ?>" style="padding-bottom: 0"><?= $message ?></li>
+     <? endforeach ?>
+     <? endforeach ?>
+   </ul>
+    <form method="post" action="<?= url::site("admin/modules/save") ?>">
+      <?= access::csrf_form_field() ?>
+      <? foreach ($modules as $module): ?>
+        <?= form::hidden($module, 1) ?>
+      <? endforeach ?>
+    </form>
+  </div>
+</div>
diff --git a/modules/gallery/views/admin_movies.html.php b/modules/gallery/views/admin_movies.html.php
new file mode 100644
index 0000000..abf8fb2
--- /dev/null
+++ b/modules/gallery/views/admin_movies.html.php
@@ -0,0 +1,44 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-movies-admin" class="g-block ui-helper-clearfix">
+  <h1> <?= t("Movies settings") ?> </h1>
+  <p>
+    <?= t("Gallery comes with everything it needs to upload and play movies.") ?>
+    <?= t("However, it needs the FFmpeg toolkit to extract thumbnails and size information from them.") ?>
+  </p>
+  <p>
+    <?= t("Although popular, FFmpeg is not installed on all Linux systems.") ?>
+    <?= t("To use FFmpeg without fully installing it, download a pre-compiled, <b>static build</b> of FFmpeg from one of the links <a href=\"%url\">here</a>.", array("url" => "http://ffmpeg.org/download.html")) ?>
+    <?= t("Then, put the \"ffmpeg\" file in Gallery's \"bin\" directory (e.g. \"/gallery3/bin\"), where Gallery will auto-detect it.") ?>
+  </p>
+  <p>
+    <?= t("Movies will work without FFmpeg, but their thumbnails will be placeholders.") ?>
+  </p>
+  <p>
+    <?= t("Can't get FFmpeg configured on your system? <a href=\"%url\">We can help!</a>",
+          array("url" => "http://codex.galleryproject.org/Gallery3:FAQ#Why_does_it_say_I.27m_missing_ffmpeg.3F")) ?>
+  </p>
+
+  <div class="g-available">
+    <h2> <?= t("Current configuration") ?> </h2>
+    <div id="g-ffmpeg" class="g-block">
+      <img class="logo" width="284" height="70" src="<?= url::file("modules/gallery/images/ffmpeg.png") ?>" alt="<? t("Visit the FFmpeg project site") ?>" />
+      <p>
+        <?= t("FFmpeg is a cross-platform standalone audio/video program.") ?><br/>
+        <?= t("Please refer to the <a href=\"%url\">FFmpeg website</a> for more information.", array("url" => "http://ffmpeg.org")) ?>
+      </p>
+      <div class="g-module-status g-info">
+        <? if ($ffmpeg_dir): ?>
+          <? if ($ffmpeg_version): ?>
+            <p><?= t("FFmpeg version %version was found in %dir", array("version" => $ffmpeg_version, "dir" => $ffmpeg_dir)) ?></p>
+          <? else: ?>
+            <p><?= t("FFmpeg (of unknown version) was found in %dir", array("dir" => $ffmpeg_dir)) ?></p>
+          <? endif ?>
+        <? else: ?>
+          <p><?= t("We could not locate FFmpeg on your system.") ?></p>
+        <? endif ?>
+      </div>
+    </div>
+  </div>
+
+  <?= $form ?>
+</div>
diff --git a/modules/gallery/views/admin_sidebar.html.php b/modules/gallery/views/admin_sidebar.html.php
new file mode 100644
index 0000000..75499cb
--- /dev/null
+++ b/modules/gallery/views/admin_sidebar.html.php
@@ -0,0 +1,64 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  $(document).ready(function(){
+    $(".g-admin-blocks-list").equal_heights();
+    var extra_ht = $(".g-admin-blocks-list li").length * $(".g-admin-blocks-list li:first").height();
+    $(".g-admin-blocks-list").height($(".g-admin-blocks-list").height() + extra_ht);
+  });
+
+  $(function() {
+    $(".g-admin-blocks-list ul").sortable({
+      connectWith: ".g-sortable-blocks",
+      opacity: .7,
+      placeholder: "g-target",
+      update: function(event,ui) {
+        if ($(this).attr("id") == "g-active-blocks") {
+          var active_blocks = "";
+          $("ul#g-active-blocks li").each(function(i) {
+            active_blocks += "&block["+i+"]="+$(this).attr("ref");
+          });
+          $.getJSON($("#g-site-blocks").attr("ref").replace("__ACTIVE__", active_blocks), function(data) {
+            if (data.result == "success") {
+              $("ul#g-available-blocks").html(data.available);
+              $("ul#g-active-blocks").html(data.active);
+              $("#g-action-status").remove();
+              var message = "<ul id=\"g-action-status\" class=\"g-message-block\">";
+              message += "<li class=\"g-success\">" + data.message + "</li>";
+              message += "</ul>";
+              $("#g-block-admin").before(message);
+              $("#g-action-status li").gallery_show_message();
+            }
+          });
+        }
+      }
+    }).disableSelection();
+  });
+</script>
+
+<div id="g-block-admin" class="g-block ui-helper-clearfix">
+  <h1> <?= t("Manage sidebar") ?> </h1>
+  <p>
+    <?= t("Select and drag blocks from the available column to the active column to add to the sidebar; remove by dragging the other way.") ?>
+  </p>
+
+  <div class="g-block-content">
+    <div id="g-site-blocks" ref="<?= url::site("admin/sidebar/update?csrf={$csrf}__ACTIVE__") ?>">
+      <div class="g-admin-blocks-list g-left">
+        <h3><?= t("Available blocks") ?></h3>
+        <div>
+          <ul id="g-available-blocks" class="g-sortable-blocks">
+          <?= $available ?>
+          </ul>
+        </div>
+      </div>
+      <div class="g-admin-blocks-list g-left">
+        <h3><?= t("Active blocks") ?></h3>
+        <div>
+          <ul id="g-active-blocks" class="g-sortable-blocks">
+          <?= $active ?>
+          </ul>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/modules/gallery/views/admin_sidebar_blocks.html.php b/modules/gallery/views/admin_sidebar_blocks.html.php
new file mode 100644
index 0000000..48aa3f0
--- /dev/null
+++ b/modules/gallery/views/admin_sidebar_blocks.html.php
@@ -0,0 +1,5 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+
+<? foreach ($blocks as $ref => $text): ?>
+<li class="g-draggable" ref="<?= $ref ?>"><?= $text ?></li>
+<? endforeach ?>
diff --git a/modules/gallery/views/admin_theme_options.html.php b/modules/gallery/views/admin_theme_options.html.php
new file mode 100644
index 0000000..e452913
--- /dev/null
+++ b/modules/gallery/views/admin_theme_options.html.php
@@ -0,0 +1,7 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="g-block">
+  <h1> <?= t("Theme options") ?> </h1>
+  <div class="g-block-content">
+  <?= $form ?>
+  </div>
+</div>
diff --git a/modules/gallery/views/admin_themes.html.php b/modules/gallery/views/admin_themes.html.php
new file mode 100644
index 0000000..547f27d
--- /dev/null
+++ b/modules/gallery/views/admin_themes.html.php
@@ -0,0 +1,98 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  var select_url = "<?= url::site("admin/themes/choose") ?>";
+  select = function(type, id) {
+    $.post(select_url, {"type": type, "id": id, "csrf": '<?= $csrf ?>'},
+      function() { load(type) });
+  }
+</script>
+
+<div class="g-block ui-helper-clearfix">
+  <h1> <?= t("Theme choice") ?> </h1>
+  <p>
+    <?= t("Make your Gallery beautiful <a href=\"%url\">with a new theme</a>!  There are separate themes for the regular site and for the administration interface.  Click a theme below to preview and activate it.", array("url" => "http://codex.galleryproject.org/Category:Gallery_3:Themes")) ?>
+  </p>
+
+  <div class="g-block-content">
+    <div id="g-site-theme">
+      <h2> <?= t("Gallery theme") ?> </h2>
+      <div class="g-block g-selected ui-helper-clearfix">
+        <img src="<?= url::file("themes/{$site}/thumbnail.png") ?>"
+             alt="<?= html::clean_attribute($themes[$site]->name) ?>" />
+        <h3> <?= $themes[$site]->name ?> </h3>
+        <p>
+          <?= $themes[$site]->description ?>
+        </p>
+        <? $v = new View("admin_themes_buttonset.html"); $v->info = $themes[$site]; print $v; ?>
+      </div>
+
+      <h2> <?= t("Available Gallery themes") ?> </h2>
+      <div class="g-available">
+        <? $count = 0 ?>
+        <? foreach ($themes as $id => $info): ?>
+        <? if (!$info->site) continue ?>
+        <? if ($id == $site) continue ?>
+        <div class="g-block ui-helper-clearfix">
+          <a href="<?= url::site("admin/themes/preview/site/$id") ?>" class="g-dialog-link" title="<?= t("Theme Preview: %theme_name", array("theme_name" => $info->name))->for_html_attr() ?>">
+            <img src="<?= url::file("themes/{$id}/thumbnail.png") ?>"
+                 alt="<?= html::clean_attribute($info->name) ?>" />
+            <h3> <?= $info->name ?> </h3>
+            <p>
+              <?= $info->description ?>
+            </p>
+          </a>
+          <? $v = new View("admin_themes_buttonset.html"); $v->info = $info; print $v; ?>
+        </div>
+        <? $count++ ?>
+        <? endforeach ?>
+
+        <? if (!$count): ?>
+        <p>
+          <?= t("There are no other site themes available. <a href=\"%url\">Download one now!</a>", array("url" => "http://codex.galleryproject.org/Category:Gallery_3:Themes")) ?>
+        </p>
+        <? endif ?>
+      </div>
+    </div>
+
+    <div id="g-admin-theme">
+      <h2> <?= t("Admin theme") ?> </h2>
+      <div class="g-block g-selected ui-helper-clearfix">
+        <img src="<?= url::file("themes/{$admin}/thumbnail.png") ?>"
+             alt="<?= html::clean_attribute($themes[$admin]->name) ?>" />
+        <h3> <?= $themes[$admin]->name ?> </h3>
+        <p>
+          <?= $themes[$admin]->description ?>
+        </p>
+        <? $v = new View("admin_themes_buttonset.html"); $v->info = $themes[$admin]; print $v; ?>
+      </div>
+
+      <h2> <?= t("Available admin themes") ?> </h2>
+      <div class="g-available">
+        <? $count = 0 ?>
+        <? foreach ($themes as $id => $info): ?>
+        <? if (!$info->admin) continue ?>
+        <? if ($id == $admin) continue ?>
+        <div class="g-block ui-helper-clearfix">
+          <a href="<?= url::site("admin/themes/preview/admin/$id") ?>" class="g-dialog-link" title="<?= t("Theme Preview: %theme_name", array("theme_name" => $info->name))->for_html_attr() ?>">
+            <img src="<?= url::file("themes/{$id}/thumbnail.png") ?>"
+                 alt="<?= html::clean_attribute($info->name) ?>" />
+            <h3> <?= $info->name ?> </h3>
+            <p>
+              <?= $info->description ?>
+            </p>
+          </a>
+          <? $v = new View("admin_themes_buttonset.html"); $v->info = $info; print $v; ?>
+        </div>
+        <? $count++ ?>
+        <? endforeach ?>
+
+        <? if (!$count): ?>
+        <p>
+          <?= t("There are no other admin themes available. <a href=\"%url\">Download one now!</a>", array("url" => "http://codex.galleryproject.org/Category:Gallery_3:Themes")) ?>
+        </p>
+        <? endif ?>
+      </div>
+    </div>
+
+  </div>
+</div>
diff --git a/modules/gallery/views/admin_themes_buttonset.html.php b/modules/gallery/views/admin_themes_buttonset.html.php
new file mode 100644
index 0000000..bf474a2
--- /dev/null
+++ b/modules/gallery/views/admin_themes_buttonset.html.php
@@ -0,0 +1,48 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul class="g-buttonset">
+  <li>
+    <a target="_blank"
+       <? if (isset($info['author_url'])): ?>
+       class="ui-state-default ui-icon ui-icon-person ui-corner-left"
+       href="<?= $info['author_url'] ?>"
+       <? else: ?>
+       class="ui-state-disabled ui-icon ui-icon-person ui-corner-left"
+       href="#"
+       <? endif ?>
+
+       <? if (isset($info['author_name'])): ?>
+       title="<?= $info['author_name'] ?>"
+       <? endif ?>
+       >
+       <? if (isset($info['author_name'])): ?>
+       <?= $info['author_name'] ?>
+       <? endif ?>
+    </a>
+  </li>
+  <li>
+    <a target="_blank"
+       <? if (isset($info['info_url'])): ?>
+       class="ui-state-default ui-icon ui-icon-info"
+       href="<?= $info['info_url'] ?>"
+       <? else: ?>
+       class="ui-state-disabled ui-icon ui-icon-info"
+       href="#"
+       <? endif ?>
+       >
+      <?= t("info") ?>
+    </a>
+  </li>
+  <li>
+    <a target="_blank"
+       <? if (isset($info['discuss_url'])): ?>
+       class="ui-state-default ui-icon ui-icon-comment ui-corner-right"
+       href="<?= $info['discuss_url'] ?>"
+       <? else: ?>
+       class="ui-state-disabled ui-icon ui-icon-comment ui-corner-right"
+       href="#"
+       <? endif ?>
+       >
+      <?= t("discuss") ?>
+    </a>
+  </li>
+</ul>
diff --git a/modules/gallery/views/admin_themes_preview.html.php b/modules/gallery/views/admin_themes_preview.html.php
new file mode 100644
index 0000000..80a6158
--- /dev/null
+++ b/modules/gallery/views/admin_themes_preview.html.php
@@ -0,0 +1,8 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h1><?= t("Preview of the %theme_name theme", array("theme_name" => $info->name)) ?></h1>
+<p>
+  <a href="<?= url::site("admin/themes/choose/$type/$theme_name?csrf=$csrf") ?>">
+    <?= t("Activate <strong>%theme_name</strong>", array("theme_name" => $info->name)) ?>
+  </a>
+</p>
+<iframe src="<?= $url ?>" style="width: 900px; height: 450px"></iframe>
diff --git a/modules/gallery/views/error.html.php b/modules/gallery/views/error.html.php
new file mode 100644
index 0000000..5d81b65
--- /dev/null
+++ b/modules/gallery/views/error.html.php
@@ -0,0 +1,12 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-error">
+  <h1>
+    <?= t("Dang...  Something went wrong!") ?>
+  </h1>
+  <h2>
+    <?= t("We tried really hard, but it's broken.") ?>
+  </h2>
+  <p>
+    <?= t("Talk to your Gallery administrator for help fixing this!") ?>
+  </p>
+</div>
\ No newline at end of file
diff --git a/modules/gallery/views/error_404.html.php b/modules/gallery/views/error_404.html.php
new file mode 100644
index 0000000..42f62b6
--- /dev/null
+++ b/modules/gallery/views/error_404.html.php
@@ -0,0 +1,26 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-error">
+  <h1>
+    <?= t("Dang...  Page not found!") ?>
+  </h1>
+  <? if ($is_guest): ?>
+    <h2>
+      <?= t("Hey wait, you're not signed in yet!") ?>
+    </h2>
+    <p>
+       <?= t("Maybe the page exists, but is only visible to authorized users.") ?>
+       <?= t("Please sign in to find out.") ?>
+    </p>
+    <?= $login_form ?>
+    <script type="text/javascript">
+      $(document).ready(function() {
+        $("#g-username").focus();
+      });
+    </script>
+  <? else: ?>
+    <p>
+      <?= t("Maybe the page exists, but is only visible to authorized users.") ?>
+      <?= t("If you think this is an error, talk to your Gallery administrator!") ?>
+    </p>
+ <? endif; ?>
+</div>
diff --git a/modules/gallery/views/error_admin.html.php b/modules/gallery/views/error_admin.html.php
new file mode 100644
index 0000000..036e204
--- /dev/null
+++ b/modules/gallery/views/error_admin.html.php
@@ -0,0 +1,307 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? $error_id = uniqid("error") ?>
+<? if (!function_exists("t")) { function t($msg) { return $msg; } } ?>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8">
+    <style type="text/css">
+      body {
+        background: #fff;
+        font-size: 14px;
+        line-height: 130%;
+      }
+
+      div.big_box {
+        padding: 10px;
+        background: #eee;
+        border: solid 1px #ccc;
+        font-family: sans-serif;
+        color: #111;
+        width: 60em;
+        margin: 20px auto;
+      }
+
+      #framework_error {
+        height: 6em;
+      }
+
+      #framework_error .crashlogo {
+        position: relative;
+        top: .3em;
+        font-size: 6.0em;
+      }
+
+      #framework_error .title {
+        position: relative;
+        top: -2.5em;
+        padding: 0px;
+        text-align: center;
+      }
+
+      div#error_details {
+        text-align: left;
+      }
+
+      code {
+        font-family: monospace;
+        font-size: 12px;
+        margin: 20px 20px 20px 0px;
+        color: #333;
+        white-space: pre-wrap;
+        white-space: -moz-pre-wrap;
+        word-wrap: break-word;
+      }
+
+      code .line {
+        padding-left: 10px;
+      }
+
+      h3 {
+        font-family: sans-serif;
+        margin: 2px 0px 0px 0px;
+        padding: 8px 0px 0px 0px;
+        border-top: 1px solid #ddd;
+      }
+
+      p {
+        padding: 0px;
+        margin: 0px 0px 10px 0px;
+      }
+
+      li, pre {
+        padding: 0px;
+        margin: 0px;
+      }
+
+      .collapsed {
+        display: none;
+      }
+
+      .highlight {
+        font-weight: bold;
+        color: darkred;
+      }
+
+      #kohana_error .message {
+        display: block;
+        padding-bottom: 10px;
+      }
+
+      .source {
+        border: solid 1px #ccc;
+        background: #efe;
+        margin-bottom: 5px;
+      }
+
+      table {
+        width: 100%;
+        display: block;
+        margin: 0 0 0.4em;
+        padding: 0;
+        border-collapse: collapse;
+        background: #efe;
+      }
+
+      table td {
+        border: solid 1px #ddd;
+        text-align: left;
+        vertical-align: top;
+        padding: 0.4em;
+      }
+
+      .args table td.key {
+        width: 200px;
+      }
+
+      .number {
+        padding-right: 1em;
+      }
+
+      #g-platform h2, #g-stats h2 {
+        font-size: 1.1em;
+      }
+    </style>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+    <title><?= t("Something went wrong!") ?></title>
+
+    <script type="text/javascript">
+      function koggle(elem) {
+        elem = document.getElementById(elem);
+        if (elem.style && elem.style["display"]) {
+          // Only works with the "style" attr
+          var disp = elem.style["display"];
+        } else {
+          if (elem.currentStyle) {
+            // For MSIE, naturally
+            var disp = elem.currentStyle["display"];
+          } else {
+            if (window.getComputedStyle) {
+              // For most other browsers
+              var disp = document.defaultView.getComputedStyle(elem, null).getPropertyValue('display');
+            }
+          }
+        }
+
+        // Toggle the state of the "display" style
+        elem.style.display = disp == 'block' ? 'none' : 'block';
+        return false;
+      }
+    </script>
+  </head>
+  <body>
+    <? try { $user = identity::active_user(); } catch (Exception $e) { } ?>
+    <div class="big_box" id="framework_error">
+      <div class="crashlogo">
+        :-(
+      </div>
+      <div class="title">
+        <h1>
+          <?= t("Dang...  Something went wrong!") ?>
+        </h1>
+        <h2>
+          <?= t("We tried really hard, but it's broken.") ?>
+        </h2>
+      </div>
+    </div>
+    <div class="big_box" id="error_details">
+      <h2>
+        <?= t("Hey wait, you're an admin!  We can tell you stuff.") ?>
+      </h2>
+      <p>
+        There's an error message below and you can find more details
+        in gallery3/var/logs (look for the file with the most recent
+        date on it).  Stuck?  Stop by the <a href="http://galleryproject.org/forum/96">Gallery 3
+        Forums</a> and ask for help.  You can also look at our list
+        of <a href="http://sourceforge.net/apps/trac/gallery/roadmap">open
+        tickets</a> to see if the problem you're seeing has been
+        reported.  If you post a request, here's some useful
+        information to include:
+        <?=  @gallery_block::get("platform_info") ?>
+        <?=  @gallery_block::get("stats") ?>
+      </p>
+      <div id="kohana_error">
+        <h3>
+          <span class="type">
+            <?= $type?> [ <?= $code ?> ]:
+          </span>
+          <span class="message">
+            <?= html::purify($message) ?>
+          </span>
+        </h3>
+        <div id="<?= $error_id ?>" class="content">
+          <ol class="trace">
+            <li class="snippet">
+              <p>
+                <span class="file">
+                  <?= Kohana_Exception::debug_path($file)?>[ <?= $line?> ]
+                </span>
+              </p>
+
+              <div class="source">
+                <? if (Kohana_Exception::$source_output and $source_code = Kohana_Exception::debug_source($file, $line)): ?><code><? foreach ($source_code as $num => $row): ?><span class="line <?= ($num == $line) ? "highlight" : ""?>"><span class="number"><?= $num ?></span><?= htmlspecialchars($row, ENT_NOQUOTES, Kohana::CHARSET) ?></span><? endforeach ?></code>
+                <? endif ?>
+              </div>
+            </li>
+
+            <? if (Kohana_Exception::$trace_output): ?>
+            <? foreach (Kohana_Exception::trace($trace) as $i => $step): ?>
+            <li class="snippet">
+              <p>
+                <span class="file">
+                  <? if ($step["file"]): $source_id = "$error_id.source.$i" ?>
+                  <? if (Kohana_Exception::$source_output and $step["source"]): ?>
+                  <a href="#<?= $source_id ?>" onclick="return koggle('<?= $source_id ?>')"><?= Kohana_Exception::debug_path($step["file"])?>[ <?= $step["line"]?> ]</a>
+                  <? else: ?>
+                  <span class="file"><?= Kohana_Exception::debug_path($step["file"])?>[ <?= $step["line"]?> ]</span>
+                  <? endif ?>
+                  <? else: ?>
+                  {<?= t("PHP internal call")?>}
+                  <? endif?>
+                </span>
+                &raquo;
+                <?= $step["function"]?>(<? if ($step["args"]): $args_id = "$error_id.args.$i" ?>
+                <a href="#<?= $args_id ?>" onclick="return koggle('<?= $args_id ?>')"><?= t("arguments")?></a>
+                <? endif?>)
+              </p>
+              <? if (isset($args_id)): ?>
+              <div id="<?= $args_id ?>" class="args collapsed">
+                <table cellspacing="0">
+                  <? foreach ($step["args"] as $name => $arg): ?>
+                  <tr>
+                    <td class="key">
+                      <pre><?= $name?></pre>
+                    </td>
+                    <td class="value">
+                      <pre><?= Kohana_Exception::safe_dump($arg, $name) ?></pre>
+                    </td>
+                  </tr>
+                  <? endforeach?>
+                </table>
+              </div>
+              <? endif?>
+              <? if (Kohana_Exception::$source_output and $step["source"] and isset($source_id)): ?>
+              <pre id="<?= $source_id ?>" class="source collapsed"><code><? foreach ($step["source"] as $num => $row): ?><span class="line <?= ($num == $step["line"]) ? "highlight" : "" ?>"><span class="number"><?= $num ?></span><?= htmlspecialchars($row, ENT_NOQUOTES, Kohana::CHARSET) ?></span><? endforeach ?></code></pre>
+              <? endif?>
+            </li>
+            <? unset($args_id, $source_id) ?>
+            <? endforeach?>
+          </ol>
+          <? endif ?>
+
+        </div>
+        <h2>
+          <a href="#<?= $env_id = $error_id."environment" ?>" onclick="return koggle('<?= $env_id ?>')"><?= t("Environment")?></a>
+        </h2>
+        <div id="<?= $env_id ?>" class="content collapsed">
+          <? $included = get_included_files()?>
+          <h3><a href="#<?= $env_id = $error_id."environment_included" ?>" onclick="return koggle('<?= $env_id ?>')"><?= t("Included files")?></a>(<?= count($included)?>)</h3>
+          <div id="<?= $env_id ?>" class="collapsed">
+            <table cellspacing="0">
+              <? foreach ($included as $file): ?>
+              <tr>
+                <td>
+                  <pre><?= Kohana_Exception::debug_path($file)?></pre>
+                </td>
+              </tr>
+              <? endforeach?>
+            </table>
+          </div>
+          <? $included = get_loaded_extensions()?>
+          <h3><a href="#<?= $env_id = $error_id."environment_loaded" ?>" onclick="return koggle('<?= $env_id ?>')"><?= t("Loaded extensions")?></a>(<?= count($included)?>)</h3>
+          <div id="<?= $env_id ?>" class="collapsed">
+            <table cellspacing="0">
+              <? foreach ($included as $file): ?>
+              <tr>
+                <td>
+                  <pre><?= Kohana_Exception::debug_path($file)?></pre>
+                </td>
+              </tr>
+              <? endforeach?>
+            </table>
+          </div>
+          <? foreach (array("_SESSION", "_GET", "_POST", "_FILES", "_COOKIE", "_SERVER") as $var): ?>
+          <? if ( empty($GLOBALS[$var]) OR ! is_array($GLOBALS[$var])) continue ?>
+          <h3><a href="#<?= $env_id = "$error_id.environment" . strtolower($var) ?>"
+                 onclick="return koggle('<?= $env_id ?>')">$<?= $var?></a></h3>
+          <div id="<?= $env_id ?>" class="collapsed">
+            <table cellspacing="0">
+              <? foreach ($GLOBALS[$var] as $key => $value): ?>
+              <tr>
+                <td class="key">
+                  <code>
+                    <?= html::purify($key) ?>
+                  </code>
+                </td>
+                <td class="value">
+                  <pre><?= Kohana_Exception::safe_dump($value, $key) ?></pre>
+                </td>
+              </tr>
+              <? endforeach?>
+            </table>
+          </div>
+          <? endforeach?>
+        </div>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/modules/gallery/views/error_cli.txt.php b/modules/gallery/views/error_cli.txt.php
new file mode 100644
index 0000000..9f476f5
--- /dev/null
+++ b/modules/gallery/views/error_cli.txt.php
@@ -0,0 +1,3 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? echo Kohana_Exception::text($e), "\n";
+
diff --git a/modules/gallery/views/error_user.html.php b/modules/gallery/views/error_user.html.php
new file mode 100644
index 0000000..09ab752
--- /dev/null
+++ b/modules/gallery/views/error_user.html.php
@@ -0,0 +1,60 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? if (!function_exists("t")) { function t($msg) { return $msg; } } ?>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <style type="text/css">
+      body {
+        background: #fff;
+        font-size: 14px;
+        line-height: 130%;
+      }
+
+      div.big_box {
+        padding: 10px;
+        background: #eee;
+        border: solid 1px #ccc;
+        font-family: sans-serif;
+        color: #111;
+        width: 60em;
+        margin: 20px auto;
+      }
+
+      #framework_error {
+        height: 8em;
+      }
+
+      #framework_error .crashlogo {
+        position: relative;
+        top: .3em;
+        font-size: 6em;
+      }
+
+      #framework_error .title {
+        position: relative;
+        top: -3em;
+        text-align: center;
+        margin: 0 auto;
+      }
+    </style>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+    <title><?= t("Something went wrong!") ?></title>
+  </head>
+  <body>
+    <div class="big_box" id="framework_error">
+      <div class="crashlogo">
+        :-(
+      </div>
+      <div class="title">
+        <h1>
+          <?= t("Dang...  Something went wrong!") ?>
+        </h1>
+        <h2>
+          <?= t("We tried really hard, but it's broken.") ?>
+        </h2>
+        <p>
+          <?= t("Talk to your Gallery administrator for help fixing this!") ?>
+        </p>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/modules/gallery/views/form.html.php b/modules/gallery/views/form.html.php
new file mode 100644
index 0000000..abc3216
--- /dev/null
+++ b/modules/gallery/views/form.html.php
@@ -0,0 +1,77 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?
+print($open);
+
+// Not sure what to do with these, but at least show that we received them.
+if ($class) {
+  print "<!-- unused class in form.html.php: $class -->";
+}
+if ($title) {
+  print $title;
+}
+
+if (!function_exists("DrawForm")) {
+  function DrawForm($inputs, $level=1) {
+    $error_messages = array();
+    $prefix = str_repeat("  ", $level);
+    $haveGroup = false;
+    // On the first level, make sure we have a group if not add the <ul> tag now
+    if ($level == 1) {
+      foreach ($inputs as $input) {
+        $haveGroup |= $input->type == 'group';
+      }
+      if (!$haveGroup) {
+        print "$prefix<ul>\n";
+      }
+    }
+
+    foreach ($inputs as $input) {
+      if ($input->type == 'group') {
+        print "$prefix<fieldset>\n";
+        print "$prefix  <legend>{$input->label}</legend>\n";
+        print "$prefix  <ul>\n";
+
+        DrawForm($input->inputs, $level + 2);
+        print "$prefix  </ul>\n";
+
+        // Since hidden fields can only have name and value attributes lets just render it now
+        $hidden_prefix = "$prefix    ";
+        foreach ($input->hidden as $hidden) {
+          print "$prefix  {$hidden->render()}\n";
+        }
+        print "$prefix</fieldset>\n";
+      } else if ($input->type == 'script') {
+        print $input->render();
+      } else {
+        if ($input->error_messages()) {
+          print "$prefix<li class=\"g-error\">\n";
+        } else {
+          print "$prefix<li>\n";
+        }
+
+        if ($input->label()) {
+          print "$prefix  {$input->label()}\n";
+        }
+        print "$prefix  {$input->render()}\n";
+        if ($input->message()) {
+          print "$prefix  <p>{$input->message()}</p>\n";
+        }
+        if ($input->error_messages()) {
+          foreach ($input->error_messages() as $error_message) {
+            print "$prefix  <p class=\"g-message g-error\">\n";
+            print "$prefix    $error_message\n";
+            print "$prefix  </p>\n";
+          }
+        }
+        print "$prefix</li>\n";
+      }
+    }
+    if ($level == 1 && !$haveGroup) {
+      print "$prefix</ul>\n";
+    }
+  }
+}
+DrawForm($inputs);
+
+print($close);
+?>
diff --git a/modules/gallery/views/form_uploadify.html.php b/modules/gallery/views/form_uploadify.html.php
new file mode 100644
index 0000000..bba6db7
--- /dev/null
+++ b/modules/gallery/views/form_uploadify.html.php
@@ -0,0 +1,167 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript" src="<?= url::file("lib/swfobject.js") ?>"></script>
+<script type="text/javascript" src="<?= url::file("lib/uploadify/jquery.uploadify.min.js") ?>"></script>
+<script type="text/javascript">
+  <? $flash_minimum_version = "9.0.24" ?>
+  var success_count = 0;
+  var error_count = 0;
+  var updating = 0;
+  $("#g-add-photos-canvas").ready(function () {
+    var update_status = function() {
+      if (updating) {
+        // poor man's mutex
+        setTimeout(function() { update_status(); }, 500);
+      }
+      updating = 1;
+      $.get("<?= url::site("uploader/status/_S/_E") ?>"
+            .replace("_S", success_count).replace("_E", error_count),
+          function(data) {
+            $("#g-add-photos-status-message").html(data);
+            updating = 0;
+          });
+    };
+
+    if (swfobject.hasFlashPlayerVersion("<?= $flash_minimum_version ?>")) {
+      $("#g-uploadify").uploadify({
+        width: 298,
+        height: 32,
+        uploader: "<?= url::file("lib/uploadify/uploadify.swf.php") ?>",
+        script: "<?= url::site("uploader/add_photo/{$album->id}") ?>",
+        scriptData: <?= json_encode($script_data) ?>,
+        fileExt: "<?= implode(";", $extensions) ?>",
+        fileDesc: <?= t("Photos and movies")->for_js() ?>,
+        cancelImg: "<?= url::file("lib/uploadify/cancel.png") ?>",
+        simUploadLimit: <?= $simultaneous_upload_limit ?>,
+        sizeLimit: <?= $size_limit_bytes ?>,
+        wmode: "transparent",
+        hideButton: true, /* should be true */
+        auto: true,
+        multi: true,
+        onAllComplete: function(filesUploaded, errors, allbytesLoaded, speed) {
+          $("#g-upload-cancel-all")
+            .addClass("ui-state-disabled")
+            .attr("disabled", "disabled");
+          $("#g-upload-done")
+            .removeClass("ui-state-disabled")
+            .attr("disabled", null);
+          return true;
+        },
+        onClearQueue: function(event) {
+          $("#g-upload-cancel-all")
+            .addClass("ui-state-disabled")
+            .attr("disabled", "disabled");
+          $("#g-upload-done")
+            .removeClass("ui-state-disabled")
+            .attr("disabled", null);
+          return true;
+        },
+        onComplete: function(event, queueID, fileObj, response, data) {
+          var re = /^error: (.*)$/i;
+          var msg = re.exec(response);
+          $("#g-add-photos-status ul").append(
+            "<li id=\"q" + queueID + "\" class=\"g-success\"><span></span> - " +
+            <?= t("Completed")->for_js() ?> + "</li>");
+          $("#g-add-photos-status li#q" + queueID + " span").text(fileObj.name);
+          setTimeout(function() { $("#q" + queueID).slideUp("slow").remove() }, 5000);
+          success_count++;
+          update_status();
+          return true;
+        },
+        onError: function(event, queueID, fileObj, errorObj) {
+          if (errorObj.type == "HTTP") {
+            if (errorObj.info == "500") {
+              error_msg = <?= t("Unable to process this photo")->for_js() ?>;
+            } else if (errorObj.info == "404") {
+              error_msg = <?= t("The upload script was not found")->for_js() ?>;
+            } else if (errorObj.info == "400") {
+              error_msg = <?= t("This photo is too large (max is %size bytes)",
+                                array("size" => $size_limit))->for_js() ?>;
+            } else {
+              msg += (<?= t("Server error: __INFO__ (__TYPE__)")->for_js() ?>
+                .replace("__INFO__", errorObj.info)
+                .replace("__TYPE__", errorObj.type));
+            }
+          } else if (errorObj.type == "File Size") {
+            error_msg = <?= t("This photo is too large (max is %size bytes)",
+                              array("size" => $size_limit))->for_js() ?>;
+          } else {
+            error_msg = <?= t("Server error: __INFO__ (__TYPE__)")->for_js() ?>
+                        .replace("__INFO__", errorObj.info)
+                        .replace("__TYPE__", errorObj.type);
+          }
+          msg = " - <a target=\"_blank\" href=\"http://codex.galleryproject.org/Gallery3:Troubleshooting:Uploading\">" +
+            error_msg + "</a>";
+
+          $("#g-add-photos-status ul").append(
+            "<li id=\"q" + queueID + "\" class=\"g-error\"><span></span>" + msg + "</li>");
+          $("#g-add-photos-status li#q" + queueID + " span").text(fileObj.name);
+          $("#g-uploadify").uploadifyCancel(queueID);
+          error_count++;
+          update_status();
+        },
+        onSelect: function(event) {
+          if ($("#g-upload-cancel-all").hasClass("ui-state-disabled")) {
+            $("#g-upload-cancel-all")
+              .removeClass("ui-state-disabled")
+              .attr("disabled", null);
+            $("#g-upload-done")
+              .addClass("ui-state-disabled")
+              .attr("disabled", "disabled");
+          }
+          return true;
+        }
+      });
+    } else {
+      $(".requires-flash").hide();
+      $(".no-flash").show();
+    }
+  });
+</script>
+
+<div class="requires-flash">
+  <? if ($suhosin_session_encrypt || (identity::active_user()->admin && !$movies_allowed)): ?>
+  <div class="g-message-block g-info">
+    <? if ($suhosin_session_encrypt): ?>
+    <p class="g-error">
+      <?= t("Error: your server is configured to use the <a href=\"%encrypt_url\"><code>suhosin.session.encrypt</code></a> setting from <a href=\"%suhosin_url\">Suhosin</a>.  You must disable this setting to upload photos.",
+          array("encrypt_url" => "http://www.hardened-php.net/suhosin/configuration.html#suhosin.session.encrypt",
+      "suhosin_url" => "http://www.hardened-php.net/suhosin/")) ?>
+    </p>
+    <? endif ?>
+
+    <? if (identity::active_user()->admin && !$movies_allowed): ?>
+    <p class="g-warning">
+      <?= t("Movie uploading is disabled on your system. <a href=\"%help_url\">Help!</a>", array("help_url" => url::site("admin/movies"))) ?>
+    </p>
+    <? endif ?>
+  </div>
+  <? endif ?>
+
+  <div>
+    <ul class="g-breadcrumbs">
+      <? foreach ($album->parents() as $i => $parent): ?>
+      <li<? if ($i == 0) print " class=\"g-first\"" ?>> <?= html::clean($parent->title) ?> </li>
+      <? endforeach ?>
+      <li class="g-active"> <?= html::purify($album->title) ?> </li>
+    </ul>
+  </div>
+
+  <div id="g-add-photos-canvas">
+    <button id="g-add-photos-button" class="g-button ui-state-default ui-corner-all" href="#"><?= t("Select photos (%size max per file)...", array("size" => $size_limit)) ?></button>
+    <span id="g-uploadify"></span>
+  </div>
+  <div id="g-add-photos-status">
+    <ul id="g-action-status" class="g-message-block">
+    </ul>
+  </div>
+</div>
+
+<div class="no-flash" style="display: none">
+  <p>
+    <?= t("Your browser must have Adobe Flash Player version %flash_minimum_version or greater installed to use this feature.", array("flash_minimum_version" => $flash_minimum_version)) ?>
+  </p>
+  <a href="http://www.adobe.com/go/getflashplayer">
+    <img src="<?= request::protocol() ?>://www.adobe.com/images/shared/download_buttons/get_flash_player.gif"
+         alt=<?= t("Get Adobe Flash Player")->for_js() ?> />
+  </a>
+</div>
diff --git a/modules/gallery/views/form_uploadify_buttons.html.php b/modules/gallery/views/form_uploadify_buttons.html.php
new file mode 100644
index 0000000..e002d82
--- /dev/null
+++ b/modules/gallery/views/form_uploadify_buttons.html.php
@@ -0,0 +1,11 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="requires-flash">
+  <!-- Proxy the done request back to our form, since its been ajaxified -->
+  <button id="g-upload-done" class="ui-state-default ui-corner-all" onclick="$('#g-add-photos-form').submit();return false;">
+  <?= t("Done") ?>
+  </button>
+  <button id="g-upload-cancel-all" class="ui-state-default ui-corner-all ui-state-disabled" onclick="$('#g-uploadify').uploadifyClearQueue();return false;" disabled="disabled">
+  <?= t("Cancel uploads") ?>
+  </button>
+  <span id="g-add-photos-status-message" />
+</div>
diff --git a/modules/gallery/views/in_place_edit.html.php b/modules/gallery/views/in_place_edit.html.php
new file mode 100644
index 0000000..2d6cbe9
--- /dev/null
+++ b/modules/gallery/views/in_place_edit.html.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?= form::open($action, array("method" => "post", "id" => "g-in-place-edit-form", "class" => "g-short-form")) ?>
+  <?= access::csrf_form_field() ?>
+  <ul>
+    <li<? if (!empty($errors["input"])): ?> class="g-error"<? endif ?>>
+      <?= form::input("input", $form["input"], " class=\"textbox\"") ?>
+    </li>
+    <li>
+      <?= form::submit(array("class" => "submit ui-state-default"), t("Save")) ?>
+    </li>
+    <li><a href="#" class="g-cancel"><?= t("Cancel") ?></a></li>
+    <? if (!empty($errors["input"])): ?>
+    <li>
+      <p id="g-in-place-edit-message" class="g-error"><?= $errors["input"] ?></p>
+    </li>
+    <? endif ?>
+  </ul>
+</form>
+
+
+
diff --git a/modules/gallery/views/kohana/error.php b/modules/gallery/views/kohana/error.php
new file mode 100644
index 0000000..0e84f09
--- /dev/null
+++ b/modules/gallery/views/kohana/error.php
@@ -0,0 +1,46 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?
+// This is the template for all HTML errors.  If you're throwing an exception and you want your
+// error to appear differently, extend Kohana_Exception and specify a different template.
+
+// Log validation exceptions to ease debugging
+if ($e instanceof ORM_Validation_Exception) {
+  Kohana_Log::add("error", "Validation errors: " . print_r($e->validation->errors(), 1));
+}
+
+if (php_sapi_name() == "cli") {
+  include Kohana::find_file("views", "error_cli.txt");
+  return;
+}
+
+try {
+  // Admins get a special error page
+  $user = identity::active_user();
+  if ($user && $user->admin) {
+    include Kohana::find_file("views", "error_admin.html");
+    return;
+  }
+} catch (Exception $ignored) {
+}
+
+// Try to show a themed error page for 404 errors
+if ($e instanceof Kohana_404_Exception) {
+  if (Router::$controller == "file_proxy") {
+    print "File not found";
+  } else {
+    $view = new Theme_View("page.html", "other", "error");
+    $view->page_title = t("Dang...  Page not found!");
+    $view->content = new View("error_404.html");
+    $user = identity::active_user();
+    $view->content->is_guest = $user && $user->guest;
+    if ($view->content->is_guest) {
+      $view->content->login_form = new View("login_ajax.html");
+      $view->content->login_form->form = auth::get_login_form("login/auth_html");
+    }
+    print $view;
+  }
+  return;
+}
+
+header("HTTP/1.1 500 Internal Server Error");
+include Kohana::find_file("views", "error_user.html");
diff --git a/modules/gallery/views/kohana_profiler.php b/modules/gallery/views/kohana_profiler.php
new file mode 100644
index 0000000..c753434
--- /dev/null
+++ b/modules/gallery/views/kohana_profiler.php
@@ -0,0 +1,35 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<style type="text/css">
+  #kohana-profiler {
+    background-color: #F8FFF8;
+    border: 1px solid #E5EFF8;
+    clear: both;
+    font-family: Monaco, 'Courier New';
+    margin-top: 20px;
+    padding: 10px 10px 0;
+    text-align: left;
+  }
+  #kohana-profiler pre {
+    font: inherit;
+    margin: 0;
+  }
+  #kohana-profiler .kp-meta {
+    background: #fff;
+    border: 1px solid #E5EFF8;
+    color: #A6B0B8;
+    margin: 0 0 10px;
+    padding: 4px;
+    text-align: center;
+  }
+  #kohana-profiler td {
+    padding-right: 1em;
+  }
+  <? echo $styles ?>
+</style>
+
+<div id="kohana-profiler">
+  <? foreach ($profiles as $profile): ?>
+  <?= $profile->render(); ?>
+  <? endforeach; ?>
+  <p class="kp-meta"><?= t("Profiler executed in ") . number_format($execution_time, 3) ?>s</p>
+</div>
diff --git a/modules/gallery/views/l10n_client.html.php b/modules/gallery/views/l10n_client.html.php
new file mode 100644
index 0000000..47a45e2
--- /dev/null
+++ b/modules/gallery/views/l10n_client.html.php
@@ -0,0 +1,82 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="l10n-client" class="hidden">
+  <div class="labels">
+    <span id="l10n-client-toggler">
+      <a id="g-minimize-l10n">_</a>
+      <a id="g-close-l10n" title="<?= t("Stop the translation mode")->for_html_attr() ?>"
+         href="<?= html::clean_attribute(url::site("l10n_client/toggle_l10n_mode?csrf=".access::csrf_token())) ?>">X</a>
+    </span>
+    <div class="label strings"><h2><?= t("Page text") ?>
+    <? if (!Input::instance()->get('show_all_l10n_messages')): ?>
+      <a style="background-color:#fff" href="<?= url::site("admin/languages?show_all_l10n_messages=1") ?>"><?= t("(Show all)") ?></a>
+    <? endif; ?>
+    </h2></div>
+    <div class="label source"><h2><?= t("Source") ?></div>
+    <div class="label translation"><h2><?= t("Translation to %language",
+                                             array("language" => locales::display_name())) ?></h2></div>
+  </div>
+  <div id="l10n-client-string-select">
+    <ul class="string-list">
+      <? foreach ($string_list as $string): ?>
+      <li class="<?= $string["translation"] === ""  ? "untranslated" : "translated" ?>">
+        <? if (is_array($string["source"])): ?>
+       [one] - <?= $string["source"]["one"] ?><br/>
+       [other] - <?= $string["source"]["other"] ?>
+        <? else: ?>
+        <?= $string["source"] ?>
+        <? endif; ?>
+      </li>
+      <? endforeach; ?>
+    </ul>
+
+    <?= $l10n_search_form ?>
+  </div>
+  <div id="l10n-client-string-editor">
+    <div class="source">
+      <p class="source-text"></p>
+      <p id="source-text-tmp-space" style="display:none"></p>
+    </div>
+    <div class="translation">
+      <form method="post" action="<?= url::site("l10n_client/save") ?>" id="g-l10n-client-save-form">
+        <?= access::csrf_form_field() ?>
+        <?= form::hidden("l10n-message-key") ?>
+        <?= form::textarea("l10n-edit-translation", "", ' id="l10n-edit-translation" rows="5" class="translationField"') ?>
+        <div id="plural-zero" class="translationField hidden">
+          <label for="l10n-edit-plural-translation-zero">[zero]</label>
+          <?= form::textarea("l10n-edit-plural-translation-zero", "", ' rows="2"') ?>
+        </div>
+        <div id="plural-one" class="translationField hidden">
+          <label for="l10n-edit-plural-translation-one">[one]</label>
+          <?= form::textarea("l10n-edit-plural-translation-one", "", ' rows="2"') ?>
+        </div>
+        <div id="plural-two" class="translationField hidden">
+          <label for="l10n-edit-plural-translation-two">[two]</label>
+          <?= form::textarea("l10n-edit-plural-translation-two", "", ' rows="2"') ?>
+        </div>
+        <div id="plural-few" class="translationField hidden">
+          <label for="l10n-edit-plural-translation-few">[few]</label>
+          <?= form::textarea("l10n-edit-plural-translation-few", "", ' rows="2"') ?>
+        </div>
+        <div id="plural-many" class="translationField hidden">
+          <label for="l10n-edit-plural-translation-many">[many]</label>
+          <?= form::textarea("l10n-edit-plural-translation-many", "", ' rows="2"') ?>
+        </div>
+        <div id="plural-other" class="translationField hidden">
+          <label for="l10n-edit-plural-translation-other">[other]</label>
+          (<a href="http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html"><?= t("learn more about plural forms") ?></a>)
+          <?= form::textarea("l10n-edit-plural-translation-other", "", ' rows="2"') ?>
+        </div>
+        <input type="submit" name="l10n-edit-save" value="<?= t("Save translation")->for_html_attr() ?>"/>
+        <a href="javascript: Gallery.l10nClient.copySourceText()"
+           class="g-button ui-state-default ui-corner-all"><?= t("Copy source text") ?></a>
+      </form>
+    </div>
+  </div>
+  <script type="text/javascript">
+    var MSG_TRANSLATE_TEXT = <?= t("Translate text")->for_js() ?>;
+    var l10n_client_data = <?= json_encode($string_list) ?>;
+    var plural_forms = <?= json_encode($plural_forms) ?>;
+    var toggle_l10n_mode_url = <?= html::js_string(url::site("l10n_client/toggle_l10n_mode")) ?>;
+    var csrf = <?= html::js_string(access::csrf_token()) ?>;
+  </script>
+</div>
diff --git a/modules/gallery/views/login_ajax.html.php b/modules/gallery/views/login_ajax.html.php
new file mode 100644
index 0000000..a40d195
--- /dev/null
+++ b/modules/gallery/views/login_ajax.html.php
@@ -0,0 +1,52 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  $("#g-login-form").ready(function() {
+    $("#g-password-reset").click(function() {
+      $.ajax({
+        url: "<?= url::site("password/reset") ?>",
+        success: function(data) {
+          $("#g-login").html(data);
+          $("#ui-dialog-title-g-dialog").html(<?= t("Reset password")->for_js() ?>);
+          $(".submit").addClass("g-button ui-state-default ui-corner-all");
+          $(".submit").gallery_hover_init();
+          ajaxify_login_reset_form();
+
+          // See comment about IE7 below
+          setTimeout('$("#g-name").focus()', 100);
+        }
+      });
+    });
+
+    // Setting the focus here doesn't work on IE7, perhaps because the field is
+    // not ready yet?  So set a timeout and do it the next time we're idle
+    setTimeout('$("#g-username").focus()', 100);
+  });
+
+  function ajaxify_login_reset_form() {
+    $("#g-login form").ajaxForm({
+      dataType: "json",
+      success: function(data) {
+        if (data.form) {
+          $("#g-login form").replaceWith(data.form);
+          ajaxify_login_reset_form();
+        }
+        if (data.result == "success") {
+          $("#g-dialog").dialog("close");
+          window.location.reload();
+        }
+      }
+    });
+  };
+</script>
+<div id="g-login">
+  <ul>
+    <li id="g-login-form">
+      <?= $form ?>
+    </li>
+    <? if (identity::is_writable() && !module::get_var("gallery", "maintenance_mode")): ?>
+    <li>
+      <a href="#" id="g-password-reset" class="g-right g-text-small"><?= t("Forgot your password?") ?></a>
+    </li>
+    <? endif ?>
+  </ul>
+</div>
diff --git a/modules/gallery/views/login_current_user.html.php b/modules/gallery/views/login_current_user.html.php
new file mode 100644
index 0000000..9452557
--- /dev/null
+++ b/modules/gallery/views/login_current_user.html.php
@@ -0,0 +1,7 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<li>
+  <? $name = $menu->label->for_html() ?>
+  <? $hover_text = t("Your profile")->for_html_attr() ?>
+  <?= t("Logged in as %name", array("name" => html::mark_clean(
+        "<a href='$menu->url' title='$hover_text' id='$menu->id'>{$name}</a>"))) ?>
+</li>
diff --git a/modules/gallery/views/menu.html.php b/modules/gallery/views/menu.html.php
new file mode 100644
index 0000000..17a249d
--- /dev/null
+++ b/modules/gallery/views/menu.html.php
@@ -0,0 +1,24 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? if (!$menu->is_empty()): // Don't show the menu if it has no choices ?>
+<? if ($menu->is_root): ?>
+<ul <?= $menu->css_id ? "id='$menu->css_id'" : "" ?> class="<?= $menu->css_class ?>">
+  <? foreach ($menu->elements as $element): ?>
+  <?= $element->render() ?>
+  <? endforeach ?>
+</ul>
+
+<? else: ?>
+
+<li title="<?= $menu->label->for_html_attr() ?>">
+  <a href="#">
+    <?= $menu->label->for_html() ?>
+  </a>
+  <ul>
+    <? foreach ($menu->elements as $element): ?>
+    <?= $element->render() ?>
+    <? endforeach ?>
+  </ul>
+</li>
+
+<? endif ?>
+<? endif ?>
diff --git a/modules/gallery/views/menu_ajax_link.html.php b/modules/gallery/views/menu_ajax_link.html.php
new file mode 100644
index 0000000..06cd6f9
--- /dev/null
+++ b/modules/gallery/views/menu_ajax_link.html.php
@@ -0,0 +1,10 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<li>
+  <a <?= $menu->css_id ? "id='{$menu->css_id}'" : "" ?>
+     class="g-ajax-link <?= $menu->css_class ?>"
+     href="<?= $menu->url ?>"
+     title="<?= $menu->label->for_html_attr() ?>"
+     ajax_handler="<?= $menu->ajax_handler ?>">
+    <?= $menu->label->for_html() ?>
+  </a>
+</li>
diff --git a/modules/gallery/views/menu_dialog.html.php b/modules/gallery/views/menu_dialog.html.php
new file mode 100644
index 0000000..b44080c
--- /dev/null
+++ b/modules/gallery/views/menu_dialog.html.php
@@ -0,0 +1,9 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<li>
+  <a <?= $menu->css_id ? "id='{$menu->css_id}'" : "" ?>
+     class="g-dialog-link <?= $menu->css_class ?>"
+     href="<?= $menu->url ?>"
+     title="<?= $menu->label->for_html_attr() ?>">
+    <?= $menu->label->for_html() ?>
+  </a>
+</li>
diff --git a/modules/gallery/views/menu_link.html.php b/modules/gallery/views/menu_link.html.php
new file mode 100644
index 0000000..a36d275
--- /dev/null
+++ b/modules/gallery/views/menu_link.html.php
@@ -0,0 +1,9 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<li>
+  <a <?= $menu->css_id ? "id='{$menu->css_id}'" : "" ?>
+     class="g-menu-link <?= $menu->css_class ?>"
+     href="<?= $menu->url ?>"
+     title="<?= $menu->label->for_html_attr() ?>">
+    <?= $menu->label->for_html() ?>
+  </a>
+</li>
diff --git a/modules/gallery/views/movieplayer.html.php b/modules/gallery/views/movieplayer.html.php
new file mode 100644
index 0000000..3cf5d17
--- /dev/null
+++ b/modules/gallery/views/movieplayer.html.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?= html::anchor($url, "", $attrs) ?>
+<script type="text/javascript">
+  var id = "<?= $attrs["id"] ?>";
+  var max_size = <?= $max_size ?>;
+  // set the size of the movie html anchor, taking into account max_size and height of control bar
+  function set_movie_size(width, height) {
+    if((width > max_size) || (height > max_size)) {
+      if (width > height) {
+        height = Math.ceil(height * max_size / width);
+        width = max_size;
+      } else {
+        width = Math.ceil(width * max_size / height);
+        height = max_size;
+      }
+    }
+    height += flowplayer(id).getConfig().plugins.controls.height;
+    $("#" + id).css({width: width, height: height});
+  };
+  // setup flowplayer
+  flowplayer(id,
+    $.extend(true, {
+      "src": "<?= url::abs_file("lib/flowplayer.swf.php") ?>",
+      "wmode": "transparent",
+      "provider": "pseudostreaming"
+    }, <?= json_encode($fp_params) ?>),
+    $.extend(true, {
+      "plugins": {
+        "pseudostreaming": {
+          "url": "<?= url::abs_file("lib/flowplayer.pseudostreaming-byterange.swf.php") ?>"
+        },
+        "controls": {
+          "autoHide": "always",
+          "hideDelay": 2000,
+          "height": 24,
+          "url": "<?= url::abs_file("lib/flowplayer.controls.swf.php") ?>"
+        }
+      },
+      "clip": {
+        "scaling": "fit",
+        "onMetaData": function(clip) {
+          // set movie size a second time using actual size from metadata
+          set_movie_size(parseInt(clip.metaData.width), parseInt(clip.metaData.height));
+        }
+      }
+    }, <?= json_encode($fp_config) ?>)
+  ).ipad();
+  // set movie size using width and height passed from movie_img function
+  $("document").ready(set_movie_size(<?= $width ?>, <?= $height ?>));
+</script>
diff --git a/modules/gallery/views/permissions_browse.html.php b/modules/gallery/views/permissions_browse.html.php
new file mode 100644
index 0000000..0b27336
--- /dev/null
+++ b/modules/gallery/views/permissions_browse.html.php
@@ -0,0 +1,62 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  var form_url = "<?= url::site("permissions/form/__ITEM__") ?>";
+  show = function(id) {
+    $.ajax({
+      url: form_url.replace("__ITEM__", id),
+      success: function(data) {
+          $("#g-edit-permissions-form").html(data);
+          $(".g-active").removeClass("g-active");
+          $("#item-" + id).addClass("g-active");
+      }
+    });
+  }
+
+  var action_url =
+    "<?= url::site("permissions/change/__CMD__/__GROUP__/__PERM__/__ITEM__?csrf=$csrf") ?>";
+  set = function(cmd, group_id, perm_id, item_id) {
+    $.ajax({
+      url: action_url.replace("__CMD__", cmd).replace("__GROUP__", group_id).
+           replace("__PERM__", perm_id).replace("__ITEM__", item_id),
+      success: function(data) {
+        $("#g-edit-permissions-form").load(form_url.replace("__ITEM__", item_id));
+      }
+    });
+  }
+</script>
+<div id="g-permissions">
+  <? if (!$htaccess_works): ?>
+  <ul id="g-action-status" class="g-message-block">
+    <li class="g-error">
+      <?= t("Oh no!  Your server needs a configuration change in order for you to hide photos!  Ask your server administrator to enable <a %mod_rewrite_attrs>mod_rewrite</a> and set <a %apache_attrs><i>AllowOverride FileInfo Options</i></a> to fix this.",
+            array("mod_rewrite_attrs" => html::mark_clean('href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html" target="_blank"'),
+                  "apache_attrs" => html::mark_clean('href="http://httpd.apache.org/docs/2.0/mod/core.html#allowoverride" target="_blank"'))) ?>
+    </li>
+  </ul>
+  <? endif ?>
+
+  <p><?= t("Edit permissions for album:") ?></p>
+
+  <ul class="g-breadcrumbs">
+    <? $i = 0 ?>
+    <? foreach ($parents as $parent): ?>
+    <li id="item-<?= $parent->id ?>"<? if ($i == 0) print " class=\"g-first\"" ?>>
+      <? if (access::can("edit", $parent)): ?>
+      <a href="javascript:show(<?= $parent->id ?>)"> <?= html::purify($parent->title) ?> </a>
+      <? else: ?>
+      <?= html::purify($parent->title) ?>
+      <? endif ?>
+    </li>
+    <? $i++ ?>
+    <? endforeach ?>
+    <li class="g-active" id="item-<?= $item->id ?>">
+      <a href="javascript:show(<?= $item->id ?>)">
+        <?= html::purify($item->title) ?>
+      </a>
+    </li>
+  </ul>
+
+  <div id="g-edit-permissions-form">
+    <?= $form ?>
+  </div>
+</div>
diff --git a/modules/gallery/views/permissions_form.html.php b/modules/gallery/views/permissions_form.html.php
new file mode 100644
index 0000000..f171411
--- /dev/null
+++ b/modules/gallery/views/permissions_form.html.php
@@ -0,0 +1,92 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<fieldset>
+  <legend> <?= t('Edit Permissions') ?> </legend>
+  <table>
+    <tr>
+      <th> </th>
+      <? foreach ($groups as $group): ?>
+      <th> <?= html::clean($group->name) ?> </th>
+      <? endforeach ?>
+    </tr>
+
+    <? foreach ($permissions as $permission): ?>
+    <tr>
+  <td> <?= t($permission->display_name) ?>
+ </td>
+      <? foreach ($groups as $group): ?>
+        <? $intent = access::group_intent($group, $permission->name, $item) ?>
+        <? $allowed = access::group_can($group, $permission->name, $item) ?>
+        <? $lock = access::locked_by($group, $permission->name, $item) ?>
+
+        <? if ($lock): ?>
+          <td class="g-denied">
+            <img src="<?= url::file(gallery::find_file("images", "ico-denied.png")) ?>"
+                 title="<?= t('denied and locked through parent album')->for_html_attr() ?>"
+                 alt="<?= t('denied icon')->for_html_attr() ?>" />
+            <a href="javascript:show(<?= $lock->id ?>)" title="<?= t('click to go to parent album')->for_html_attr() ?>">
+              <img src="<?= url::file(gallery::find_file("images", "ico-lock.png")) ?>" alt="<?= t('locked icon')->for_html_attr() ?>" />
+            </a>
+          </td>
+        <? else: ?>
+          <? if ($intent === access::INHERIT): ?>
+            <? if ($allowed): ?>
+              <td class="g-allowed">
+                <a href="javascript:set('allow',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)" title="<?= t('allowed through parent album, click to allow explicitly')->for_html_attr() ?>">
+                  <img src="<?= url::file(gallery::find_file("images", "ico-success-passive.png")) ?>" alt="<?= t('passive allowed icon')->for_html_attr() ?>" />
+                </a>
+                <a href="javascript:set('deny',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)"
+                  title="<?= t('click to deny')->for_html_attr() ?>">
+                  <img src="<?= url::file(gallery::find_file("images", "ico-denied-inactive.png")) ?>" alt="<?= t('inactive denied icon')->for_html_attr() ?>" />
+                </a>
+              </td>
+            <? else: ?>
+              <td class="g-denied">
+                <a href="javascript:set('allow',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)"
+                  title="<?= t('click to allow')->for_html_attr() ?>">
+                  <img src="<?= url::file(gallery::find_file("images", "ico-success-inactive.png")) ?>" alt="<?= t('inactive allowed icon')->for_html_attr() ?>" />
+                </a>
+                <a href="javascript:set('deny',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)"
+                  title="<?= t('denied through parent album, click to deny explicitly')->for_html_attr() ?>">
+                  <img src="<?= url::file(gallery::find_file("images", "ico-denied-passive.png")) ?>" alt="<?= t('passive denied icon')->for_html_attr() ?>" />
+                </a>
+              </td>
+            <? endif ?>
+
+          <? elseif ($intent === access::DENY): ?>
+            <td class="g-denied">
+              <a href="javascript:set('allow',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)"
+                title="<?= t('click to allow')->for_html_attr() ?>">
+                <img src="<?= url::file(gallery::find_file("images", "ico-success-inactive.png")) ?>" alt="<?= t('inactive allowed icon')->for_html_attr() ?>" />
+              </a>
+              <? if ($item->id == 1): ?>
+                <img src="<?= url::file(gallery::find_file("images", "ico-denied.png")) ?>" alt="<?= t('denied icon')->for_html_attr() ?>" title="<?= t('denied')->for_html_attr() ?>"/>
+              <? else: ?>
+                <a href="javascript:set('reset',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)"
+                  title="<?= t('denied, click to reset')->for_html_attr() ?>">
+                  <img src="<?= url::file(gallery::find_file("images", "ico-denied.png")) ?>" alt="<?= t('denied icon')->for_html_attr() ?>" />
+                </a>
+              <? endif ?>
+            </td>
+          <? elseif ($intent === access::ALLOW): ?>
+            <td class="g-allowed">
+              <? if ($item->id == 1): ?>
+                <img src="<?= url::file(gallery::find_file("images", "ico-success.png")) ?>" title="<?= t("allowed")->for_html_attr() ?>" alt="<?= t('allowed icon')->for_html_attr() ?>" />
+              <? else: ?>
+                <a href="javascript:set('reset',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)"
+                  title="<?= t('allowed, click to reset')->for_html_attr() ?>">
+                  <img src="<?= url::file(gallery::find_file("images", "ico-success.png")) ?>" alt="<?= t('allowed icon')->for_html_attr() ?>" />
+                </a>
+              <? endif ?>
+              <a href="javascript:set('deny',<?= $group->id ?>,<?= $permission->id ?>,<?= $item->id ?>)"
+                title="<?= t('click to deny')->for_html_attr() ?>">
+                <img src="<?= url::file(gallery::find_file("images", "ico-denied-inactive.png")) ?>" alt="<?= t('inactive denied icon')->for_html_attr() ?>" />
+              </a>
+            </td>
+          <? endif ?>
+        <? endif ?>
+      </td>
+      <? endforeach ?>
+    </tr>
+    <? endforeach ?>
+  </table>
+</fieldset>
diff --git a/modules/gallery/views/quick_delete_confirm.html.php b/modules/gallery/views/quick_delete_confirm.html.php
new file mode 100644
index 0000000..176ffb9
--- /dev/null
+++ b/modules/gallery/views/quick_delete_confirm.html.php
@@ -0,0 +1,12 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="ui-helper-clearfix">
+  <p>
+  <? if ($item->is_album()): ?>
+    <?= t("Delete the album <b>%title</b>? All photos and movies in the album will also be deleted.",
+          array("title" => html::purify($item->title))) ?>
+  <? else: ?>
+    <?= t("Are you sure you want to delete <b>%title</b>?", array("title" => html::purify($item->title))) ?>
+  <? endif ?>
+  </p>
+  <?= $form ?>
+</div>
diff --git a/modules/gallery/views/reauthenticate.html.php b/modules/gallery/views/reauthenticate.html.php
new file mode 100644
index 0000000..9a6696f
--- /dev/null
+++ b/modules/gallery/views/reauthenticate.html.php
@@ -0,0 +1,15 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div>
+  <p>
+    <?= t("The administration session has expired, please re-authenticate to access the administration area.") ?>
+  </p>
+  <p>
+    <?= t("You are currently logged in as %user_name.", array("user_name" => $user_name)) ?>
+  </p>
+  <?= $form ?>
+  <script type="text/javascript">
+  $("#g-reauthenticate-form").ready(function() {
+    $("#g-password").focus();
+  });
+  </script>
+</div>
\ No newline at end of file
diff --git a/modules/gallery/views/upgrade_checker_block.html.php b/modules/gallery/views/upgrade_checker_block.html.php
new file mode 100644
index 0000000..c984d99
--- /dev/null
+++ b/modules/gallery/views/upgrade_checker_block.html.php
@@ -0,0 +1,55 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<p>
+  <?= t("Gallery can check to see if there is a new version available for you to use.  It is a good idea to upgrade your Gallery to get the latest features and security fixes.  Your privacy is important so no information about your Gallery is shared during this process.  You can disable this feature below.") ?>
+</p>
+
+<p>
+  <? if (gallery::RELEASE_CHANNEL == "release"): ?>
+  <?= t("You are using the official Gallery %version release, code named <i>%code_name</i>.", array("version" => gallery::VERSION, "code_name" => gallery::CODE_NAME)) ?>
+  <? elseif (isset($build_number)): ?>
+  <?= t("You are using an experimental snapshot of Gallery %version (build %build_number on branch %branch).", array("version" => gallery::VERSION, "branch" => gallery::RELEASE_BRANCH, "build_number" => $build_number)) ?>
+  <? else: ?>
+  <?= t("You are using an experimental snapshot of Gallery %version (branch %branch) but your gallery3/.build_number file is missing so we don't know what build you have.  You should probably upgrade so that you have that file.", array("version" => gallery::VERSION, "branch" => gallery::RELEASE_BRANCH, "build_number" => $build_number)) ?>
+  <? endif ?>
+</p>
+
+<? if ($new_version): ?>
+<ul class="g-message-block">
+  <li class="g-message g-info">
+    <?= $new_version ?>
+  </li>
+</ul>
+<? endif ?>
+
+<p>
+  <a class="g-button ui-state-default ui-corner-all"
+     href="<?= url::site("admin/upgrade_checker/check_now?csrf=$csrf") ?>">
+    <?= t("Check now") ?>
+  </a>
+  <? if ($auto_check_enabled): ?>
+  <a class="g-button ui-state-default ui-corner-all"
+     href="<?= url::site("admin/upgrade_checker/set_auto/0?csrf=$csrf") ?>">
+    <?= t("Disable automatic checking") ?>
+  </a>
+  <? else: ?>
+  <a class="g-button ui-state-default ui-corner-all"
+     href="<?= url::site("admin/upgrade_checker/set_auto/1?csrf=$csrf") ?>">
+    <?= t("Enable automatic checking") ?>
+  </a>
+  <? endif ?>
+</p>
+
+<p class="g-text-small">
+  <? if ($auto_check_enabled): ?>
+  <?= t("Automatic upgrade checking is enabled.") ?>
+  <? else: ?>
+  <?= t("Automatic upgrade checking is disabled.") ?>
+  <? endif ?>
+  <? if (!$version_info): ?>
+  <?= t("No upgrade checks have been made yet.") ?>
+  <? else: ?>
+  <?= t("The last upgrade check was made on %date.",
+        array("date" => gallery::date_time($version_info->timestamp))) ?>
+  <? endif ?>
+</p>
+
diff --git a/modules/gallery/views/upgrader.html.php b/modules/gallery/views/upgrader.html.php
new file mode 100644
index 0000000..4c611f7
--- /dev/null
+++ b/modules/gallery/views/upgrader.html.php
@@ -0,0 +1,163 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+  <head>
+    <title><?= t("Gallery 3 upgrader") ?></title>
+    <link rel="stylesheet" type="text/css" href="<?= url::file("modules/gallery/css/upgrader.css") ?>"
+          media="screen,print,projection" />
+    <script src="<?= url::file("lib/jquery.js") ?>" type="text/javascript"></script>
+  </head>
+  <body<? if (locales::is_rtl()) { echo ' class="rtl"'; } ?>>
+    <div id="outer">
+      <img id="logo" src="<?= url::file("modules/gallery/images/gallery.png") ?>" />
+      <div id="inner">
+        <? if ($can_upgrade): ?>
+        <div id="dialog" style="visibility: hidden">
+          <a id="dialog_close_link" style="display: none" onclick="$('#dialog').fadeOut(); return false;" href="#" class="close">[x]</a>
+          <div id="busy" style="display: none">
+            <h1>
+              <img width="16" height="16" src="<?= url::file("themes/wind/images/loading-small.gif") ?>"/>
+              <?= t("Upgrade in progress!") ?>
+            </h1>
+            <p>
+              <?= t("Please don't refresh or leave the page.") ?>
+            </p>
+          </div>
+          <div id="done" style="display: none">
+            <h1> <?= t("That's it!") ?> </h1>
+            <p>
+              <?= t("Your Gallery is up to date.<br/><a href=\"%url\">Return to your Gallery</a>",
+                    array("url" => html::mark_clean(url::base()))) ?>
+            </p>
+          </div>
+          <div id="failed" style="display: none">
+            <h1> <?= t("Some modules failed to upgrade!") ?> </h1>
+            <p>
+              <?= t("Failed modules are <span class=\"failed\">highlighted</span>.  Try getting newer versions or <a href=\"%admin_modules\">deactivating those modules</a>.", array("admin_modules" => url::site("admin/modules"))) ?>
+            </p>
+          </div>
+        </div>
+        <script type="text/javascript">
+          $(document).ready(function() {
+            $("#dialog").css("left", Math.round(($(window).width() - $("#dialog").width()) / 2));
+            $("#dialog").css("top", Math.round(($(window).height() - $("#dialog").height()) / 2));
+            $("#upgrade_link").click(function(event) { show_busy() });
+
+            <? if ($done): ?>
+            show_done();
+            <? endif ?>
+
+            <? if ($failed): ?>
+            show_failed();
+            <? endif ?>
+          });
+
+          var show_busy = function() {
+            $("#dialog").css("visibility", "visible");
+            $("#busy").show();
+            $("#upgrade_link").parent().removeClass("button-active");
+            $("#upgrade_link").replaceWith($("#upgrade_link").html())
+          }
+
+          var show_done = function() {
+            $("#dialog").css("visibility", "visible");
+            $("#done").show();
+            $("#dialog_close_link").show();
+          }
+
+          var show_failed = function() {
+            $("#dialog").css("visibility", "visible");
+            $("#failed").show();
+            $("#dialog_close_link").show();
+          }
+        </script>
+        <div id="welcome_message">
+          <p class="<?= $done ? "muted" : "" ?>">
+            <?= t("Welcome to the Gallery upgrader.  One click and you're done!") ?>
+          </p>
+        </div>
+
+        <? if ($done): ?>
+        <div id="upgrade_button" class="button muted">
+          <?= t("Upgrade all") ?>
+        </div>
+        <? else: ?>
+        <div id="upgrade_button" class="button button-active">
+          <a id="upgrade_link" href="<?= url::site("upgrader/upgrade?csrf=" . access::csrf_token()) ?>">
+            <?= t("Upgrade all") ?>
+          </a>
+        </div>
+        <? endif ?>
+
+        <? if ($obsolete_modules_message): ?>
+        <div id="obsolete_modules_message">
+          <p>
+            <span class="failed"><?= t("Warning!") ?></span>
+            <?= $obsolete_modules_message ?>
+          </p>
+        </div>
+        <? endif ?>
+
+        <table>
+          <tr class="<?= $done ? "muted" : "" ?>">
+            <th class="name"> <?= t("Module name") ?> </th>
+            <th> <?= t("Installed version") ?> </th>
+            <th> <?= t("Available version") ?> </th>
+          </tr>
+
+          <? foreach ($available as $id => $module): ?>
+          <? if ($module->active): ?>
+          <tr class="<?= $module->version == $module->code_version ? "current" : "upgradeable" ?> <?= in_array($id, $failed) ? "failed" : "" ?>" >
+            <td class="name <?= $id ?>">
+              <?= t($module->name) ?>
+            </td>
+            <td>
+              <?= $module->version ?>
+            </td>
+            <td>
+              <?= $module->code_version ?>
+            </td>
+          </tr>
+          <? else: ?>
+          <? @$inactive++ ?>
+          <? endif ?>
+          <? endforeach ?>
+        </table>
+
+        <? if (@$inactive): ?>
+        <p class="<?= $done ? "muted" : "" ?>">
+          <?= t("The following modules are inactive and don't require an upgrade.") ?>
+        </p>
+        <ul class="<?= $done ? "muted" : "" ?>">
+          <? foreach ($available as $module): ?>
+          <? if (!$module->active): ?>
+          <li>
+            <?= t($module->name) ?>
+          </li>
+          <? endif ?>
+          <? endforeach ?>
+        </ul>
+        <? endif ?>
+        <? else: // can_upgrade ?>
+        <h1> <?= t("Who are you?") ?> </h1>
+        <p>
+          <?= t("You're not logged in as an administrator, so we have to verify you to make sure it's ok for you to do an upgrade.  To prove you can run an upgrade, create a file called <b> %name </b> in your <b>%tmp_dir_path</b> directory.",
+                array("name" => "$upgrade_token",
+                      "tmp_dir_path" => "gallery3/var/tmp")) ?>
+        </p>
+        <a href="<?= url::site("upgrader?") ?>"><?= t("Ok, I've done that") ?></a>
+        <? endif // can_upgrade ?>
+      </div>
+      <div id="footer">
+        <p>
+          <em>
+            <?= t("Did something go wrong? Try the <a href=\"%faq_url\">FAQ</a> or ask in the <a href=\"%forums_url\">Gallery forums</a>.",
+                array("faq_url" => "http://codex.galleryproject.org/Gallery3:FAQ",
+                      "forums_url" => "http://galleryproject.org/forum")) ?>
+          </em>
+        </p>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/modules/gallery/views/user_languages_block.html.php b/modules/gallery/views/user_languages_block.html.php
new file mode 100644
index 0000000..3776ca1
--- /dev/null
+++ b/modules/gallery/views/user_languages_block.html.php
@@ -0,0 +1,19 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?= form::dropdown("g-select-session-locale", $installed_locales, $selected) ?>
+<script type="text/javascript">
+  $("select[name=g-select-session-locale]").change(function() {
+    var old_locale_preference = <?= html::js_string($selected) ?>;
+    var locale = $(this).val();
+    if (old_locale_preference == locale) {
+      return;
+    }
+
+    var expires = -1;
+    if (locale) {
+      expires = 365;
+    }
+    $.cookie("g_locale", locale, {"expires": expires, "path": "/"});
+    window.location.reload(true);
+  });
+</script>
+
diff --git a/modules/gallery/views/user_profile.html.php b/modules/gallery/views/user_profile.html.php
new file mode 100644
index 0000000..257bd7c
--- /dev/null
+++ b/modules/gallery/views/user_profile.html.php
@@ -0,0 +1,47 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  $(document).ready(function() {
+    $("#g-profile-return").click(function(event) {
+      history.go(-1);
+      return false;
+    })
+  });
+</script>
+<div id="g-user-profile">
+  <div class="ui-helper-clearfix">
+    <a id="g-profile-return" class="g-button g-right ui-state-default ui-corner-all" href="#">
+      <?= t("Return") ?>
+    </a>
+    <? if ($editable): ?>
+    <a class="g-button g-right ui-state-default ui-corner-all g-dialog-link" href="<?= url::site("users/form_change_email/{$user->id}") ?>">
+      <?= t("Change email") ?>
+    </a>
+    <a class="g-button g-right ui-state-default ui-corner-all g-dialog-link" href="<?= url::site("users/form_change_password/{$user->id}") ?>">
+      <?= t("Change password") ?>
+    </a>
+    <a class="g-button g-right ui-state-default ui-corner-all g-dialog-link" href="<?= url::site("form/edit/users/{$user->id}") ?>">
+      <?= t("Edit") ?>
+    </a>
+    <? endif ?>
+    <? if ($contactable): ?>
+    <a class="g-button g-right ui-state-default ui-corner-all g-dialog-link"
+       href="<?= url::site("user_profile/contact/{$user->id}") ?>">
+      <?= t("Contact") ?>
+    </a>
+    <? endif ?>
+  </div>
+  <h1>
+    <img src="<?= $user->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>"
+       alt="<?= html::clean_attribute($user->display_name()) ?>"
+       class="g-avatar g-left" width="40" height="40" />
+    <?= t("User profile: %name", array("name" => $user->display_name())) ?>
+  </h1>
+  <? foreach ($info_parts as $info): ?>
+  <div class="g-block">
+    <h2><?= html::purify($info->title) ?></h2>
+    <div class="g-block-content">
+    <?= $info->view ?>
+    </div>
+  </div>
+  <? endforeach ?>
+</div>
diff --git a/modules/gallery/views/user_profile_info.html.php b/modules/gallery/views/user_profile_info.html.php
new file mode 100644
index 0000000..e559abd
--- /dev/null
+++ b/modules/gallery/views/user_profile_info.html.php
@@ -0,0 +1,9 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<table>
+  <? foreach ($user_profile_data as $label => $value): ?>
+  <tr>
+    <th><?= html::clean($label) ?></th>
+    <td><?= html::purify($value) ?></td>
+  </tr>
+  <? endforeach ?>
+</table>
diff --git a/modules/gallery/views/welcome_message.html.php b/modules/gallery/views/welcome_message.html.php
new file mode 100644
index 0000000..bb6b4a8
--- /dev/null
+++ b/modules/gallery/views/welcome_message.html.php
@@ -0,0 +1,36 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-welcome-message">
+  <h1 style="display: none">
+    <?= t("Welcome to Gallery 3!") ?>
+  </h1>
+
+  <p>
+    <h2>
+      <?= t("Congratulations on choosing Gallery to host your photos.  You're going to have a great experience!") ?>
+    </h2>
+  </p>
+
+  <p>
+    <?= t("First things first.  You're logged in to the <b>%user_name</b> account.  You should change your password to something that you'll remember.", array("user_name" => $user->name)) ?>
+  </p>
+
+  <p>
+    <a href="<?= url::site("admin/users/edit_user_form/{$user->id}") ?>"
+      title="<?= t("Edit your profile")->for_html_attr() ?>"
+      id="g-after-install-change-password-link"
+      class="g-button ui-state-default ui-corner-all">
+      <?= t("Change password and email now") ?>
+    </a>
+    <script type="text/javascript">
+      $("#g-after-install-change-password-link").gallery_dialog();
+    </script>
+  </p>
+
+  <p>
+    <?= t("Want to learn more? The <a href=\"%url\">Gallery website</a> has news and information about the Gallery project and community.", array("url" => "http://galleryproject.org")) ?>
+  </p>
+
+  <p>
+    <?= t("Having problems? There's lots of information in our <a href=\"%codex_url\">documentation site</a> or you can <a href=\"%forum_url\">ask for help in the forums!</a>", array("codex_url" => "http://codex.galleryproject.org/Main_Page", "forum_url" => "http://galleryproject.org/forum")) ?>
+  </p>
+</div>
diff --git a/modules/gallery/views/welcome_message_loader.html.php b/modules/gallery/views/welcome_message_loader.html.php
new file mode 100644
index 0000000..d1ff2f3
--- /dev/null
+++ b/modules/gallery/views/welcome_message_loader.html.php
@@ -0,0 +1,7 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<span id="g-welcome-message-link"
+      title="<?= t("Welcome to Gallery 3")->for_html_attr() ?>"
+      href="<?= url::site("welcome_message") ?>"/>
+<script type="text/javascript">
+  $(document).ready(function(){$("#g-welcome-message-link").gallery_dialog({immediate: true});});
+</script>
diff --git a/modules/greydragon/changelog.txt b/modules/greydragon/changelog.txt
new file mode 100644
index 0000000..ae8baf9
--- /dev/null
+++ b/modules/greydragon/changelog.txt
@@ -0,0 +1,11 @@
+GreyDragon Shared Module Changelog
+
+version 1.3:
+- Added check to detect situation when CURL is not installed to disable Auto Update feature
+- Improved CURL logic to properly handle redirects
+
+version 1.2:
+- Fixed issue with some installations not taking relative path for CSS
+
+version 1.1:
+- Initial release
\ No newline at end of file
diff --git a/modules/greydragon/css/gd_common.css b/modules/greydragon/css/gd_common.css
new file mode 100644
index 0000000..32b780b
--- /dev/null
+++ b/modules/greydragon/css/gd_common.css
@@ -0,0 +1,59 @@
+/**
+ * Gallery 3 Grey Dragon Common Module
+ * Copyright (C) 2012 Serguei Dosyukov
+ *
+ * CSS rules for admin section
+ */
+
+body { min-width: 1200px; }
+
+#g-content { font-size: 1em; margin-bottom: 0; width: auto; padding-left: 1em; padding-right: 1em; }
+#g-content ul { margin-bottom: 0; }
+
+#g-content h3 { color: #d54e21; border-bottom: #a2bdbf 1px solid; margin-top: 0.3em; margin-bottom: 0.3em; }
+#g-content p  { color: #333; }
+#g-content table { margin-bottom: 0; }
+
+#g-content input     { display: inline; float: left; margin-right: 0.8em; color: #555555; border: 1px solid #ccc; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }
+#g-content textarea  { height: 6em; color: #555555; border: 1px solid #ccc; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }
+#g-content select    { display: inline; float: left; margin-right: 0.8em; width: 50.6%; color: #555555; border: 1px solid #ccc; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }
+
+#g-content input[type='checkbox'] { border: none; }
+#g-content input[type='text'] { width: 50%; }
+
+#g-content input.submit { display: inline-block; min-width: 100px; padding: 4px 10px 4px; font-size: 13px; line-height: 18px; color:#333333; text-align: center; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); background-color: #fafafa; background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-repeat: no-repeat; filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); border: 1px solid #ccc; border-bottom-color: #bbb; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05); cursor: pointer; *margin-left: .3em; }
+#g-content input.submit:first-child { *margin-left: 0; }
+#g-content input.submit:hover { color: #333333; text-decoration: none; background-color: #e6e6e6; background-position: 0 -15px; -webkit-transition: background-position 0.1s linear; -moz-transition: background-position 0.1s linear; -ms-transition: background-position 0.1s linear; -o-transition: background-position 0.1s linear; transition: background-position 0.1s linear; }
+
+#g-content input.g-error   { padding-left: 30px; border: none; }
+#g-content input.g-success { background-color: transparent; }
+#g-content input.g-warning { background-color: transparent; border: none; }
+
+#g-content p.g-error       { padding-left: 30px; border: none; margin-bottom: 0; background-image: none; }
+
+#gd-admin-header { padding: 7px 0; margin: 4px 0 0 0; background-color: #fbfbfb; background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); background-image:- ms-linear-gradient(top, #ffffff, #f5f5f5); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); background-image: linear-gradient(top, #ffffff, #f5f5f5); background-repeat: repeat-x; filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); border: 1px solid #ddd; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; display: inline-block;  width: 100%; }
+#gd-admin-header .divider{padding:0 5px;color:#999999;}
+#gd-admin-header .active a{color:#333333;}
+
+#gd-admin-version, 
+#gd-admin-version-2 { margin-top: 4px; padding: 7px 14px; background-color: rgb(217, 237, 247); border: 1px solid #bce8f1; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; }
+
+#gd-admin-title     { float: left; padding-left: 10px; color: #333v42; font-weight: bold; font-size: 1.4em; text-shadow: #deeefa 0 1px 0; display: inline-block; }
+#gd-admin-hlinks    { float: right; padding-right: 10px; }
+#gd-admin-hlinks li { list-style-type: none; float: left; color: #618299; display: inline; text-shadow: 0 1px 0 #ffffff; }
+#gd-admin-hlinks a  { line-height: 1.6em; }
+#gd-admin-hlinks a[disabled="disabled"], #gd-admin-hlinks a[disabled="disabled"]:hover { text-decoration: none; cursor: default; }
+
+#g-autoupdate-config { display: none; border: 1px solid #ddd; border-top: none; width: 45%; height: 2.5em; margin-left: 54%; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; }
+#g-autoupdate-config.visible { min-height: 30px; display: inline-block;  }
+#g-autoupdate-config ul { float: right; margin: 6px 10px;}
+#g-autoupdate-config li { float: left; display: inline; line-height: 1.5em; }
+
+#g-admin-container          { margin-top: 14px; font-size: 0.9em; line-height: 1.6em; }
+#g-admin-container .column1 { float: left; width: 53%; min-width: 610px; }
+#g-admin-container .column2 { float: right; width: 46%; min-width: 529px; }
+
+#g-admin-container fieldset { position: relative; border-top-left-radius: 0.4em; border-top-right-radius: 0.4em; overflow: hidden; }
+#g-admin-container legend   { position: absolute; left: 0; width: 100%; padding: 0.4em 0.8em; background: url(../images/blue-grad.png) #d5e6f2 repeat-x left top; border-bottom: #dfdfdf 1px solid;  }
+#g-admin-container fieldset ul { margin-top: 34px; }
+
diff --git a/modules/greydragon/images/blue-grad.png b/modules/greydragon/images/blue-grad.png
new file mode 100644
index 0000000..868a657
Binary files /dev/null and b/modules/greydragon/images/blue-grad.png differ
diff --git a/modules/greydragon/module.info b/modules/greydragon/module.info
new file mode 100644
index 0000000..4a65e8c
--- /dev/null
+++ b/modules/greydragon/module.info
@@ -0,0 +1,9 @@
+name        = "GreyDragon Shared"
+description = "Shared content for modules from GreyDragon. Need to be activated.<br />Version 1.3 | By <a href=http://blog.dragonsoft.us>Serguei Dosyukov</a>"
+version     = 13
+author_name = "Serguei Dosyukov"
+author_url  = "http://blog.dragonsoft.us/gallery-3/"
+info_url    = ""
+discuss_url = ""
+
+
diff --git a/modules/greydragon/views/gd_admin_include.html.php b/modules/greydragon/views/gd_admin_include.html.php
new file mode 100644
index 0000000..73962cb
--- /dev/null
+++ b/modules/greydragon/views/gd_admin_include.html.php
@@ -0,0 +1,180 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<style>   
+  @import "<?= url::file("modules/greydragon/css/gd_common.css"); ?>";
+</style>
+
+<script>
+  $(document).ready( function() { 
+    $('form').submit( function() { $('input[type=submit]', this).attr('disabled', 'disabled'); });
+    
+    var objAutoUpdate = $('#g-autoupdate-config');
+    var objAutoHidden = $('input[name="g_auto_delay"]');
+    var objAutoEdit   = $('#g-auto-delay-edit');
+    function showSidebar(){ objAutoEdit.val(objAutoHidden.val());	objAutoUpdate.slideDown('fast', function() { objAutoUpdate.addClass('visible'); }); };
+    function hideSidebar(){ objAutoHidden.val(objAutoEdit.val());	objAutoUpdate.slideUp('fast',   function() { objAutoUpdate.removeClass('visible'); }); };
+
+		objAutoEdit.keyup( function() { objAutoHidden.val($(this).val());	});
+		objAutoEdit.keydown(function(event) {       
+			// Allow: backspace, delete, tab and escape 
+      if ( event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 ||  
+        // Allow: Ctrl+A 
+        (event.keyCode == 65 && event.ctrlKey === true) ||  
+        // Allow: home, end, left, right 
+        (event.keyCode >= 35 && event.keyCode <= 39)) { 
+          // let it happen, don't do anything 
+          return; 
+      } else { 
+        // Ensure that it is a number and stop the keypress 
+        if ((event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105 )) { 
+          event.preventDefault();  
+        }    
+      } 
+    }); 
+ 
+    $('.g-link-autoupdate').click(function(e){ e.preventDefault(); if ( objAutoUpdate.hasClass('visible') ){ hideSidebar(); } else { showSidebar(); }});
+  });
+</script>
+
+<?
+
+function isCurlInstalled() {
+	if (in_array('curl', get_loaded_extensions())) {
+		return true;
+	}	else {
+		return false;
+	}
+} 
+
+// -1 - cannot get version info
+// 0 - current
+// + - newer is avaialble, version is returned
+function checkVersionInfo($downloadid, $version) {
+  if (!isset($downloadid)):
+    return -1;
+  endif;
+
+  try {                                                                                        
+    $call = "http://blog.dragonsoft.us/downloadversion/" . $downloadid; 
+    $ch = curl_init();
+    curl_setopt($ch, CURLOPT_URL, $call);
+    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
+    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
+    curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
+    $output=curl_exec($ch);
+    $json = json_decode($output);
+  
+    if ($json->id == $downloadid):
+      $newversion = $json->version;
+      if ($json->version > $version):
+        return $json->version;
+      else:
+        return 0;
+      endif;      
+    else:
+      return -1;
+    endif;
+  } catch (Exception $e) {
+    return -1;
+  }
+}
+
+if ($is_module):
+  $admin_info = new ArrayObject(parse_ini_file(MODPATH   . $name . "/module.info"), ArrayObject::ARRAY_AS_PROPS);
+  $version = number_format($admin_info->version / 10, 1, '.', '');
+  $lastupdate = module::get_var($name, "last_update", time());
+	$checkInDays = module::get_var($name, "auto_delay", 30);
+else:
+  $admin_info = new ArrayObject(parse_ini_file(THEMEPATH . $name . "/theme.info"), ArrayObject::ARRAY_AS_PROPS);
+  $version = $admin_info->version;
+  $lastupdate = module::get_var("th_" . $name, "last_update", time());
+	$checkInDays = module::get_var("th_" . $name, "auto_delay", 30);
+endif;
+
+if (isCurlInstalled() && ($checkInDays > 0) && ((time() - $lastupdate) > ($checkInDays * 24 * 60 * 60))): // Check version every N days
+  $admin_info2 = new ArrayObject(parse_ini_file(MODPATH   . "greydragon/module.info"), ArrayObject::ARRAY_AS_PROPS);
+  $version2 = number_format($admin_info2->version / 10, 1, '.', '');
+  
+  $versionCheck  = checkVersionInfo($downloadid, $version);
+  $versionCheck2 = checkVersionInfo(15, $version2);
+  
+  if (($versionCheck == 0) && ($versionCheck2 == 0)):
+    if ($is_module):
+      module::set_var($name, "last_update", time());
+    else:
+      module::set_var("th_" . $name, "last_update", time());
+    endif;
+  endif;
+else:
+  $versionCheck = 0;
+  $versionCheck2 = 0;
+endif;
+?>
+
+<div id="gd-admin-header">
+  <div id="gd-admin-title"><?= t($admin_info->name) ?> - <?= $version ?></div>
+  <div id="gd-admin-hlinks">
+    <ul style="float: right;"><li><a href="http://blog.dragonsoft.us/gallery-3/" target="_blank"><?= t("Home") ?></a>&nbsp;|&nbsp;</li>
+      <? if (isset($admin_info->discuss_url)): ?>
+      <li><a href="<?= $admin_info->discuss_url;  ?>" target="_blank"><?= t("Support") ?></a>&nbsp;|&nbsp;</li>
+      <? endif; ?>
+      <? if (isset($admin_info->info_url)): ?>
+	      <li><a href="<?= $admin_info->info_url; ?>" target="_blank"><?= t("Download") ?></a>&nbsp;|&nbsp;</li>
+      <? endif; ?>
+      <? if (isset($admin_info->vote)): ?>
+	      <li><a href="<?= $admin_info->vote;     ?>" target="_blank"><?= t("Vote") ?></a>&nbsp;|&nbsp;</li>
+      <? endif; ?>
+      <li><a href="http://twitter.com/greydragon_th" target="_blank" title="<?= t("Follow Us on Twitter") ?>"><?= t("Follow Us") ?></a>&nbsp;|&nbsp;</li>
+      <li><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9MWBSVJMWMJEU" target="_blank" ><?= t("Coffee Fund") ?></a>&nbsp;|&nbsp;</li>
+      <li><a href="#" class="g-link-autoupdate" <?= (isCurlInstalled())? null : "disabled=\"disabled\""; ?> ><?= t("Auto Update"); ?></a></li>
+    </ul>
+  </div>
+</div>
+<div id="g-autoupdate-config">
+  <ul><li><?= t("Check every"); ?>&nbsp;&nbsp;</li>
+    <li><input id="g-auto-delay-edit" type="text" size="2" value="30"></li>
+    <li><?=t("days (set to 0 to disable)"); ?></li>
+<? if (($versionCheck == 0) && ($versionCheck2 == 0)): ?>
+    <li>&nbsp;&nbsp;|&nbsp;&nbsp;<?= t("Last check:"); ?>&nbsp;<?= date("Y-m-d H:i:s", $lastupdate); ?></li>
+<? endif; ?>  
+  </ul>
+</div>
+
+<? if ($versionCheck == -1): ?>
+  <div id="gd-admin-version"><?= t("Version check is incomplete. No version information has been found."); ?> <?= $versionCheck; ?> : <?= $downloadid; ?></div>
+<? elseif ($versionCheck == 0): ?>
+<? else: ?>
+  <div id="gd-admin-version"><?= t("Newer version") ?> <?= $versionCheck; ?> <?= t("is available. Click Download link for more info.") ?></div>
+<? endif; ?>
+<? if (($versionCheck2 == -1) || ($versionCheck2 == 0)): ?>
+<? else: ?>
+  <div id="gd-admin-version-2"><?= t("Newer version") ?> <?= $versionCheck2; ?> <?= t("of GreyDragon Shared Module is available. Click") . ' <a href="http://codex.gallery2.org/Gallery3:Modules:greydragon" target="_blank">' . t("here") . '</a> ' . t("for more info.") ?></div>
+<? endif; ?>
+<div id="g-admin-container">
+<? if (isset($help)): ?>
+	<div class="column1">
+	  <?= $form ?>
+	</div>
+	<div class="column2">
+    <?= $help ?>
+	</div>
+<? else: ?>
+  <?= $form ?>
+<? endif; ?>
+</div>
diff --git a/modules/html5_uploader/controllers/uploader.php b/modules/html5_uploader/controllers/uploader.php
new file mode 100644
index 0000000..8f839a0
--- /dev/null
+++ b/modules/html5_uploader/controllers/uploader.php
@@ -0,0 +1,126 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Uploader_Controller extends Controller {
+  public function index($id) {
+    $album = ORM::factory("item", $id);
+    access::required("view", $album);
+    access::required("add", $album);
+    if (!$album->is_album()) {
+      $album = $album->parent();
+    }
+
+    print $this->_get_add_form($album);
+  }
+
+  public function add($id) {
+    $album = ORM::factory("item", $id);
+    access::required("view", $album);
+    access::required("add", $album);
+    access::verify_csrf();
+
+    $form = $this->_get_add_form($album);
+    if ($form->validate()) {
+      batch::start();
+
+      $count = 0;
+      $added_a_movie = false;
+      $added_a_photo = false;
+
+      $files_list=$_FILES['files'];
+      foreach (array_keys($files_list['name']) as $index) {
+        try {
+          $temp_filename = $files_list['tmp_name'][$index];
+          $item = ORM::factory("item");
+          $item->name = basename($files_list['name'][$index]);
+          $item->title = item::convert_filename_to_title($item->name);
+          $item->parent_id = $album->id;
+          $item->set_data_file($temp_filename);
+
+          $path_info = @pathinfo($item->name);
+          if (array_key_exists("extension", $path_info) &&
+              in_array(strtolower($path_info["extension"]), array("flv", "mp4", "m4v"))) {
+            $item->type = "movie";
+            $item->save();
+            $added_a_movie = true;
+            log::success("content", t("Added a movie"),
+                         html::anchor("movies/$item->id", t("view movie")));
+          } else {
+            $item->type = "photo";
+            $item->save();
+            $added_a_photo = true;
+            log::success("content", t("Added a photo"),
+                         html::anchor("photos/$item->id", t("view photo")));
+          }
+          $count++;
+          module::event("add_photos_form_completed", $item, $form);
+        } catch (Exception $e) {
+          // Lame error handling for now.  Just record the exception and move on
+          Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+
+          // Ugh.  I hate to use instanceof, But this beats catching the exception separately since
+          // we mostly want to treat it the same way as all other exceptions
+          if ($e instanceof ORM_Validation_Exception) {
+            Kohana_Log::add("error", "Validation errors: " . print_r($e->validation->errors(), 1));
+          }
+        }
+
+        if (file_exists($temp_filename)) {
+          unlink($temp_filename);
+        }
+      }
+      batch::stop();
+      if ($count) {
+        if ($added_a_photo && $added_a_movie) {
+          message::success(t("Added %count photos and movies", array("count" => $count)));
+        } else if ($added_a_photo) {
+          message::success(t2("Added one photo", "Added %count photos", $count));
+        } else {
+          message::success(t2("Added one movie", "Added %count movies", $count));
+        }
+      }
+      json::reply(array("result" => "success"));
+    } else {
+      json::reply(array("result" => "error", "html" => (string) $form));
+    }
+
+    // Override the application/json mime type.  The dialog based HTML uploader uses an iframe to
+    // buffer the reply, and on some browsers (Firefox 3.6) it does not know what to do with the
+    // JSON that it gets back so it puts up a dialog asking the user what to do with it.  So force
+    // the encoding type back to HTML for the iframe.
+    // See: http://jquery.malsup.com/form/#file-upload
+    header("Content-Type: text/html; charset=" . Kohana::CHARSET);
+  }
+
+  private function _get_add_form($album) {
+    $form = new Forge("uploader/add/{$album->id}", "", "post", array("id" => "g-add-photos-form"));
+    $group = $form->group("add_photos")
+      ->label(t("Add photos to %album_title", array("album_title" => html::purify($album->title))));
+    $group->input("files[]")->type("file")->multiple();
+
+    $form->input("FOO")->type("hidden")->label(sprintf("Es k&ouml;nnen mehrere Bilder auf einmal hochgeladen werden. Dies dauert allerdings etwas - ohne extra Ladebalken. Also Geduld bewahren. Max. upload size of all pictures: %.0f MB.", ini_get("upload_max_filesize")));
+
+    module::event("add_photos_form", $album, $form);
+
+    $group = $form->group("buttons")->label("");
+    $group->submit("")->value(t("Upload"));
+
+    return $form;
+  }
+}
diff --git a/modules/html5_uploader/module.info b/modules/html5_uploader/module.info
new file mode 100644
index 0000000..542de3e
--- /dev/null
+++ b/modules/html5_uploader/module.info
@@ -0,0 +1,7 @@
+name = "HTML5 Uploader"
+description = "Simple HTML uploader that replaces the Flash based uploader"
+version = 1
+author_name = ""
+author_url = ""
+info_url = "http://codex.gallery2.org/Gallery3:Modules:html_uploader"
+discuss_url = "http://gallery.menalto.com/forum_module_html_uploader"
diff --git a/modules/image_block/controllers/image_block.php b/modules/image_block/controllers/image_block.php
new file mode 100644
index 0000000..3198970
--- /dev/null
+++ b/modules/image_block/controllers/image_block.php
@@ -0,0 +1,27 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Image_Block_Controller extends Controller {
+  public function random($item_id) {
+    $item = ORM::factory("item", $item_id);
+    access::required("view", $item);
+    item::set_display_context_callback("Albums_Controller::get_display_context");
+    url::redirect($item->abs_url());
+  }
+}
diff --git a/modules/image_block/helpers/image_block_block.php b/modules/image_block/helpers/image_block_block.php
new file mode 100644
index 0000000..37e5b4c
--- /dev/null
+++ b/modules/image_block/helpers/image_block_block.php
@@ -0,0 +1,56 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class image_block_block_Core {
+  static function get_site_list() {
+    return array("random_image" => t("Random image"));
+  }
+
+  static function get($block_id, $theme) {
+    $block = "";
+    switch ($block_id) {
+    case "random_image":
+      // The random_query approach is flawed and doesn't always return a
+      // result when there actually is one. Retry a *few* times.
+      // @todo Consider another fallback if further optimizations are necessary.
+      $image_count = module::get_var("image_block", "image_count");
+      $items = array();
+      for ($i = 0; $i < $image_count; $i++) {
+        $attempts = 0;
+        $item = null;
+        do {
+          $item = item::random_query()->where("type", "!=", "album")->find_all(1)->current();
+        } while (!$item && $attempts++ < 3);
+        if ($item) {
+          $items[] = $item;
+        }
+      }
+      if ($items) {
+        $block = new Block();
+        $block->css_id = "g-image-block";
+        $block->title = t2("Random image", "Random images", $image_count);
+        $block->content = new View("image_block_block.html");
+        $block->content->items = $items;
+      }
+      break;
+    }
+
+    return $block;
+  }
+}
diff --git a/modules/image_block/helpers/image_block_installer.php b/modules/image_block/helpers/image_block_installer.php
new file mode 100644
index 0000000..b177b97
--- /dev/null
+++ b/modules/image_block/helpers/image_block_installer.php
@@ -0,0 +1,43 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class image_block_installer {
+
+  static function install() {
+    module::set_var("image_block", "image_count", "1");
+  }
+
+  static function upgrade($version) {
+    $db = Database::instance();
+    if ($version == 1) {
+      module::set_var("image_block", "image_count", "1");
+      module::set_version("image_block", $version = 2);
+    }
+
+    // Oops, there was a bug in the installer for version 2 resulting
+    // in some folks not getting the image_count variable set.  Bump
+    // to version 3 and fix it.
+    if ($version == 2) {
+      if (module::get_var("image_block", "image_count", 0) === 0) {
+        module::set_var("image_block", "image_count", "1");
+      }
+      module::set_version("image_block", $version = 3);
+    }
+  }
+}
diff --git a/modules/image_block/module.info b/modules/image_block/module.info
new file mode 100644
index 0000000..25b89e6
--- /dev/null
+++ b/modules/image_block/module.info
@@ -0,0 +1,7 @@
+name = "Image Block"
+description = "Display a random image in the sidebar"
+version = 3
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:image_block"
+discuss_url = "http://galleryproject.org/forum_module_image_block"
diff --git a/modules/image_block/views/image_block_block.html.php b/modules/image_block/views/image_block_block.html.php
new file mode 100644
index 0000000..6f68e5b
--- /dev/null
+++ b/modules/image_block/views/image_block_block.html.php
@@ -0,0 +1,8 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? foreach ($items as $item): ?>
+<div class="g-image-block">
+  <a href="<?= url::site("image_block/random/" . $item->id); ?>">
+   <?= $item->thumb_img(array("class" => "g-thumbnail")) ?>
+  </a>
+</div>
+<? endforeach ?>
diff --git a/modules/info/helpers/info_block.php b/modules/info/helpers/info_block.php
new file mode 100644
index 0000000..e4b5adf
--- /dev/null
+++ b/modules/info/helpers/info_block.php
@@ -0,0 +1,93 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class info_block_Core {
+  static function get_site_list() {
+    return array("metadata" => t("Metadata"));
+  }
+
+  static function get($block_id, $theme) {
+    $block = "";
+    switch ($block_id) {
+    case "metadata":
+      if ($theme->item()) {
+        $block = new Block();
+        $block->css_id = "g-metadata";
+        $block->title = $theme->item()->is_album() ? t("Album info") :
+          ($theme->item()->is_movie() ? t("Movie info") : t("Photo info"));
+        $block->content = new View("info_block.html");
+        if ($theme->item->title && module::get_var("info", "show_title")) {
+          $info["title"] = array(
+            "label" => t("Title:"),
+            "value" => html::purify($theme->item->title)
+          );
+        }
+        if ($theme->item->description && module::get_var("info", "show_description")) {
+          $info["description"] = array(
+            "label" => t("Description:"),
+            "value" => nl2br(html::purify($theme->item->description))
+          );
+        }
+        if (!$theme->item->is_album() && module::get_var("info", "show_name")) {
+          $info["file_name"] = array(
+            "label" => t("File name:"),
+            "value" => html::clean($theme->item->name)
+          );
+        }
+        if ($theme->item->captured && module::get_var("info", "show_captured")) {
+          $info["captured"] = array(
+            "label" => t("Captured:"),
+            "value" => gallery::date_time($theme->item->captured)
+          );
+        }
+        if ($theme->item->owner && module::get_var("info", "show_owner")) {
+          $display_name = $theme->item->owner->display_name();
+          if ($theme->item->owner->url) {
+            $info["owner"] = array(
+              "label" => t("Owner:"),
+              "value" => html::anchor(
+                html::clean($theme->item->owner->url),
+                html::clean($display_name))
+            );
+          } else {
+            $info["owner"] = array(
+              "label" => t("Owner:"),
+              "value" => html::clean($display_name)
+            );
+          }
+        }
+        if (($theme->item->width && $theme->item->height) &&
+            module::get_var("info", "show_dimensions")) {
+          $info["size"] = array(
+            "label" => t("Dimensions:"),
+            "value" => t(
+              "%width x %height px",
+              array("width" => $theme->item->width, "height" => $theme->item->height))
+            );
+        }
+
+        $block->content->metadata = $info;
+
+        module::event("info_block_get_metadata", $block, $theme->item);
+      }
+      break;
+    }
+    return $block;
+  }
+}
\ No newline at end of file
diff --git a/modules/info/helpers/info_installer.php b/modules/info/helpers/info_installer.php
new file mode 100644
index 0000000..2d06a0e
--- /dev/null
+++ b/modules/info/helpers/info_installer.php
@@ -0,0 +1,45 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class info_installer {
+
+  static function install() {
+    module::set_var("info", "show_title", 1);
+    module::set_var("info", "show_description", 1);
+    module::set_var("info", "show_owner", 1);
+    module::set_var("info", "show_name", 1);
+    module::set_var("info", "show_captured", 1);
+    module::set_var("info", "show_dimensions", 1);
+  }
+
+  static function upgrade($version) {
+    if ($version == 1) {
+      module::set_var("info", "show_title", 1);
+      module::set_var("info", "show_description", 1);
+      module::set_var("info", "show_owner", 1);
+      module::set_var("info", "show_name", 1);
+      module::set_var("info", "show_captured", 1);
+      module::set_version("info", $version = 2);
+    }
+    if ($version == 2) {
+      module::set_var("info", "show_dimensions", 1);
+      module::set_version("info", $version = 3);
+    }
+  }
+}
diff --git a/modules/info/helpers/info_theme.php b/modules/info/helpers/info_theme.php
new file mode 100644
index 0000000..457d330
--- /dev/null
+++ b/modules/info/helpers/info_theme.php
@@ -0,0 +1,41 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class info_theme_Core {
+  static function thumb_info($theme, $item) {
+    $results = "";
+    if ($item->view_count) {
+      $results .= "<li>";
+      $results .= t("Views: %view_count", array("view_count" => $item->view_count));
+      $results .= "</li>";
+    }
+    if ($item->owner) {
+      $results .= "<li>";
+      if ($item->owner->url) {
+        $results .= t("By: <a href=\"%owner_url\">%owner_name</a>",
+                      array("owner_name" => $item->owner->display_name(),
+                            "owner_url" => $item->owner->url));
+      } else {
+        $results .= t("By: %owner_name", array("owner_name" => $item->owner->display_name()));
+      }
+      $results .= "</li>";
+    }
+    return $results;
+  }
+}
\ No newline at end of file
diff --git a/modules/info/module.info b/modules/info/module.info
new file mode 100644
index 0000000..33b1622
--- /dev/null
+++ b/modules/info/module.info
@@ -0,0 +1,7 @@
+name = "Info"
+description = "Display extra information about photos and albums"
+version = 3
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:info"
+discuss_url = "http://galleryproject.org/forum_module_info"
diff --git a/modules/info/views/info_block.html.php b/modules/info/views/info_block.html.php
new file mode 100644
index 0000000..b296fa1
--- /dev/null
+++ b/modules/info/views/info_block.html.php
@@ -0,0 +1,8 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul class="g-metadata">
+  <? foreach($metadata as $info): ?>
+  <li>
+    <strong class="caption"><?= $info["label"] ?></strong> <?= $info["value"] ?>
+  </li>
+  <?  endforeach; ?>
+</ul>
diff --git a/modules/kbd_nav/changelog.txt b/modules/kbd_nav/changelog.txt
new file mode 100644
index 0000000..148e1e5
--- /dev/null
+++ b/modules/kbd_nav/changelog.txt
@@ -0,0 +1,47 @@
+Kbd Navigation Changelog
+
+version 2.1:
+- Fixed issue with jQuery extension not always initialized
+- New Shortcodes:
+    Shift + C - Go to Calendar Page - Album/Photo page
+    Shift + E - Open Edit Dialog - Album/Photo page
+    Shift + F - Open Full Size - Photo page
+    Shift + I - Open Exif Info dialog - Photo page
+    Shift + S - Go to Search Box
+    Shift + V - Thumb/Photo Click to open Slideshow, where supported
+
+version 2.0:
+- Module info adjusted to match new format in G3 3.0.2+
+- Added support for ColorBox
+
+version 1.9:
+- Code adjusments to comply with new G3 requirements
+
+version 1.8:
+- Added logic to prevent navigation when Fancybox is opened.
+
+version 1.7:
+- Added logic further protecting user input activities (ex: comments)
+
+version 1.6:
+- Added logic to prevent navigation when dialogs are opened.
+- Changed detection of Shadowbox preview overlay
+
+version 1.5:
+- Fix for RTL detection
+- Added support for Wind theme
+
+version 1.4:
+- Added RTL detection
+
+version 1.3:
+- Internal revision
+
+version 1.2:
+- Added support for GreyDragon Photo Slideshow navigation - in Photo SB slideshow mode, key navigation is superseded by slideshow navigation. 
+
+version 1.1:
+- Internal revision
+
+version 1.0:
+- Initial release
\ No newline at end of file
diff --git a/modules/kbd_nav/helpers/kbd_nav_theme.php b/modules/kbd_nav/helpers/kbd_nav_theme.php
new file mode 100644
index 0000000..c539570
--- /dev/null
+++ b/modules/kbd_nav/helpers/kbd_nav_theme.php
@@ -0,0 +1,7 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+
+class Kbd_Nav_theme_Core {
+  static function head($theme) {
+    return $theme->script("kbd_nav.js");
+  }
+}
\ No newline at end of file
diff --git a/modules/kbd_nav/js/kbd_nav.js b/modules/kbd_nav/js/kbd_nav.js
new file mode 100644
index 0000000..8a22d98
--- /dev/null
+++ b/modules/kbd_nav/js/kbd_nav.js
@@ -0,0 +1,120 @@
+/**
+*
+* Copyright (c) 2010-2012 Serguei Dosyukov, http://blog.dragonsoft.us
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+*/
+
+(function($) {
+  $.fn.KbdNavigation = function(options, callback) {
+    this.options = options || {};
+    var opt = this.options;
+    this.callback = callback || null;
+    var clbk = this.callback;
+  
+    $(this).bind("keydown", function(event) {
+      if (event.target.type) { return true; }
+      if (($('div#sb-overlay').is(':visible')) || ($('div#fancybox-overlay').is(':visible')) || ($('div.ui-widget-overlay').is(':visible')) || ($('div#cboxOverlay').is(':visible'))) { return true; }
+  
+      var direction = "ltr";
+      if (document.body) {
+        if (window.getComputedStyle) {
+          direction = window.getComputedStyle(document.body, null).direction;
+        } else if (document.body.currentStyle) {
+          direction = document.body.currentStyle.direction;
+        }
+      }
+
+      var lnk = "";
+      var lnk_first, lnk_prev, lnk_parent, lnk_next, lnk_last;
+
+      if(opt.first)  { lnk_first  = opt.first;  } else { lnk_first  = $("#g-navi-first").attr("href");  }
+      if(opt.prev)   { lnk_prev   = opt.prev;   } else { lnk_prev   = $("#g-navi-prev").attr("href");   }
+      if(opt.parent) { lnk_parent = opt.parent; } else { lnk_parent = $("#g-navi-parent").attr("href"); }
+      if(opt.next)   { lnk_next   = opt.next;   } else { lnk_next   = $("#g-navi-next").attr("href");   }
+      if(opt.last)   { lnk_last   = opt.last;   } else { lnk_last   = $("#g-navi-last").attr("href");   }
+
+      // Support for standard Wind Theme tags
+      if(!lnk_first) { lnk_first = $(".g-paginator .ui-icon-seek-first").parent().attr("href"); }
+      if(!lnk_prev)  { lnk_prev  = $(".g-paginator .ui-icon-seek-prev").parent().attr("href"); }
+      if(!lnk_next)  { lnk_next  = $(".g-paginator .ui-icon-seek-next").parent().attr("href");  }
+      if(!lnk_last)  { lnk_last  = $(".g-paginator .ui-icon-seek-end").parent().attr("href");  }
+
+      var keyCode = event.keyCode;
+
+      if (direction == "rtl") {
+        switch(keyCode) {
+          case 0x25: // Left
+            keyCode = 0x27;
+            break;
+          case 0x27: // Right
+            keyCode = 0x25;
+            break;
+        }
+      }
+      
+      switch(keyCode) {
+        case 0x25: // Ctr+Left/Left
+          if(event.ctrlKey) { lnk = lnk_first; } else { lnk = lnk_prev; }
+          break;  
+        case 0x26: // Ctrl+Up
+          if(event.ctrlKey) { lnk = lnk_parent; }
+          break; 
+        case 0x27: // Ctrl+Right/Right
+          if(event.ctrlKey) { lnk = lnk_last; } else { lnk = lnk_next; }
+          break;
+        case 0x43: // Shift + C - Go to Calendar Page - Album/Photo page
+          if(event.shiftKey) { lnk = $('#g-view-menu a#g-calendarview-link').attr("href"); }
+          break;
+        case 0x45: // Shift + E - Open Edit Dialog - Album/Photo page
+          if(event.shiftKey) { $('#g-site-menu li a.ui-icon-pencil').click(); return false; }
+          break;
+        case 0x46: // Shift + F - Open Full Size - Photo page
+          if(event.shiftKey) { $('#g-view-menu a.g-fullsize-link').click(); return false; }
+          break;
+        case 0x49: // Shift + I - Open Exif Info dialog - Photo page
+          if(event.shiftKey) { $('#g-view-menu a#g-exifdata-link').click(); return false; }
+          break;
+        case 0x53: // Shift + S - Go to Search Box
+          if(event.shiftKey) { $('#g-quick-search-form input[name="q"]').focus(); return false; }
+          break;
+        case 0x56: // Shift + V - Thumb/Photo Click to open Slideshow, where supported
+          if(event.shiftKey) { 
+            $('ul#g-album-grid a.g-sb-preview:visible:first').click(); 
+            $('#g-photo a.g-sb-preview:not(.g-hide)').click();
+            return false;
+          }
+          break;                                                 
+      }
+
+      if(lnk) {
+        if(typeof clbk == 'function') {
+          clbk();
+          return false;
+        } else {
+          window.location = lnk;
+          return true;
+        }
+      } 
+      return true;
+    });
+
+    return this;
+  }
+})(jQuery);
+
+$(document).ready( function() {
+  $(document).KbdNavigation({});
+  if ($('#sb-content').is(':visible')) { return true; }
+});
\ No newline at end of file
diff --git a/modules/kbd_nav/module.info b/modules/kbd_nav/module.info
new file mode 100644
index 0000000..dd18692
--- /dev/null
+++ b/modules/kbd_nav/module.info
@@ -0,0 +1,8 @@
+name        = "Kbd Navigation"
+description = "Adds keyboard navigation to the gallery.<br />Version 2.1 | By <a href=http://blog.dragonsoft.us>Serguei Dosyukov</a> | <a href=http://codex.gallery2.org/Gallery3:Modules:kbd_nav>Visit plugin Site</a> | <a href=http://gallery.menalto.com/node/95438>Support</a>"
+version     = 21
+author_name = "Serguei Dosyukov"
+author_url  = "http://blog.dragonsoft.us/gallery-3/"
+info_url    = "http://codex.gallery2.org/Gallery3:Modules:kbd_nav";
+discuss_url = "http://gallery.menalto.com/node/95438";
+
diff --git a/modules/kohana23_compat/config/pagination.php b/modules/kohana23_compat/config/pagination.php
new file mode 100644
index 0000000..174bc23
--- /dev/null
+++ b/modules/kohana23_compat/config/pagination.php
@@ -0,0 +1,27 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+$config["default"] = array(
+  "directory"      => "pagination",
+  "style"          => "classic",
+  "uri_segment"    => 3,
+  "query_string"   => "",
+  "items_per_page" => 20,
+  "auto_hide"      => FALSE
+);
diff --git a/modules/kohana23_compat/libraries/MY_Database_Builder.php b/modules/kohana23_compat/libraries/MY_Database_Builder.php
new file mode 100644
index 0000000..4a09b20
--- /dev/null
+++ b/modules/kohana23_compat/libraries/MY_Database_Builder.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Database_Builder extends Database_Builder_Core {
+  /**
+   * Merge in a series of where clause tuples and call where() on each one.
+   * @chainable
+   */
+  public function merge_where($tuples) {
+    if ($tuples) {
+      foreach ($tuples as $tuple) {
+        $this->where($tuple[0], $tuple[1], $tuple[2]);
+      }
+    }
+    return $this;
+  }
+
+  /**
+   * Merge in a series of where clause tuples and call or_where() on each one.
+   * @chainable
+   */
+  public function merge_or_where($tuples) {
+    if ($tuples) {
+      foreach ($tuples as $tuple) {
+        $this->or_where($tuple[0], $tuple[1], $tuple[2]);
+      }
+    }
+    return $this;
+  }
+
+  public function compile() {
+    return parent::compile();
+  }
+}
\ No newline at end of file
diff --git a/modules/kohana23_compat/libraries/Pagination.php b/modules/kohana23_compat/libraries/Pagination.php
new file mode 100644
index 0000000..bd74a34
--- /dev/null
+++ b/modules/kohana23_compat/libraries/Pagination.php
@@ -0,0 +1,252 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+/**
+ * Pagination library.
+ *
+ * $Id: Pagination.php 3769 2008-12-15 00:48:56Z zombor $
+ *
+ * @package    Core
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2008 Kohana Team
+ * @license    http://kohanaphp.com/license.html
+ */
+class Pagination_Core {
+
+        // Config values
+        protected $base_url       = '';
+        protected $directory      = 'pagination';
+        protected $style          = 'classic';
+        protected $uri_segment    = 3;
+        protected $query_string   = '';
+        protected $items_per_page = 20;
+        protected $total_items    = 0;
+        protected $auto_hide      = FALSE;
+
+        // Autogenerated values
+        protected $url;
+        protected $current_page;
+        protected $total_pages;
+        protected $current_first_item;
+        protected $current_last_item;
+        protected $first_page;
+        protected $last_page;
+        protected $previous_page;
+        protected $next_page;
+        protected $sql_offset;
+        protected $sql_limit;
+
+        /**
+         * Constructs and returns a new Pagination object.
+         *
+         * @param   array   configuration settings
+         * @return  object
+         */
+        public function factory($config = array())
+        {
+                return new Pagination($config);
+        }
+
+        /**
+         * Constructs a new Pagination object.
+         *
+         * @param   array  configuration settings
+         * @return  void
+         */
+        public function __construct($config = array())
+        {
+                // No custom group name given
+                if ( ! isset($config['group']))
+                {
+                        $config['group'] = 'default';
+                }
+
+                // Pagination setup
+                $this->initialize($config);
+        }
+
+        /**
+         * Sets config values.
+         *
+         * @throws  Kohana_Exception
+         * @param   array  configuration settings
+         * @return  void
+         */
+        public function initialize($config = array())
+        {
+                // Load config group
+                if (isset($config['group']))
+                {
+                        // Load and validate config group
+                        if ( ! is_array($group_config = Kohana::config('pagination.'.$config['group'])))
+                                throw new Kohana_Exception('pagination.undefined_group: ' . $config['group']);
+
+                        // All pagination config groups inherit default config group
+                        if ($config['group'] !== 'default')
+                        {
+                                // Load and validate default config group
+                                if ( ! is_array($default_config = Kohana::config('pagination.default')))
+                                        throw new Kohana_Exception('pagination.undefined_group: default');
+
+                                // Merge config group with default config group
+                                $group_config += $default_config;
+                        }
+
+                        // Merge custom config items with config group
+                        $config += $group_config;
+                }
+
+                // Assign config values to the object
+                foreach ($config as $key => $value)
+                {
+                        if (property_exists($this, $key))
+                        {
+                                $this->$key = $value;
+                        }
+                }
+
+                // Clean view directory
+                $this->directory = trim($this->directory, '/').'/';
+
+                // Build generic URL with page in query string
+                if ($this->query_string !== '')
+                {
+                        // Extract current page
+                        $this->current_page = isset($_GET[$this->query_string]) ? (int) $_GET[$this->query_string] : 1;
+
+                        // Insert {page} placeholder
+                        $_GET[$this->query_string] = '{page}';
+
+                        // Create full URL
+                        $base_url = ($this->base_url === '') ? Router::$current_uri : $this->base_url;
+                        $this->url = url::site($base_url).'?'.str_replace('%7Bpage%7D', '{page}', http_build_query($_GET));
+
+                        // Reset page number
+                        $_GET[$this->query_string] = $this->current_page;
+                }
+
+                // Build generic URL with page as URI segment
+                else
+                {
+                        // Use current URI if no base_url set
+                        $this->url = ($this->base_url === '') ? Router::$segments : explode('/', trim($this->base_url, '/'));
+
+                        // Convert uri 'label' to corresponding integer if needed
+                        if (is_string($this->uri_segment))
+                        {
+                                if (($key = array_search($this->uri_segment, $this->url)) === FALSE)
+                                {
+                                        // If uri 'label' is not found, auto add it to base_url
+                                        $this->url[] = $this->uri_segment;
+                                        $this->uri_segment = count($this->url) + 1;
+                                }
+                                else
+                                {
+                                        $this->uri_segment = $key + 2;
+                                }
+                        }
+
+                        // Insert {page} placeholder
+                        $this->url[$this->uri_segment - 1] = '{page}';
+
+                        // Create full URL
+                        $this->url = url::site(implode('/', $this->url)).Router::$query_string;
+
+                        // Extract current page
+                        $this->current_page = URI::instance()->segment($this->uri_segment);
+                }
+
+                // Core pagination values
+                $this->total_items        = (int) max(0, $this->total_items);
+                $this->items_per_page     = (int) max(1, $this->items_per_page);
+                $this->total_pages        = (int) ceil($this->total_items / $this->items_per_page);
+                $this->current_page       = (int) min(max(1, $this->current_page), max(1, $this->total_pages));
+                $this->current_first_item = (int) min((($this->current_page - 1) * $this->items_per_page) + 1, $this->total_items);
+                $this->current_last_item  = (int) min($this->current_first_item + $this->items_per_page - 1, $this->total_items);
+
+                // If there is no first/last/previous/next page, relative to the
+                // current page, value is set to FALSE. Valid page number otherwise.
+                $this->first_page         = ($this->current_page === 1) ? FALSE : 1;
+                $this->last_page          = ($this->current_page >= $this->total_pages) ? FALSE : $this->total_pages;
+                $this->previous_page      = ($this->current_page > 1) ? $this->current_page - 1 : FALSE;
+                $this->next_page          = ($this->current_page < $this->total_pages) ? $this->current_page + 1 : FALSE;
+
+                // SQL values
+                $this->sql_offset         = (int) ($this->current_page - 1) * $this->items_per_page;
+                $this->sql_limit          = sprintf(' LIMIT %d OFFSET %d ', $this->items_per_page, $this->sql_offset);
+        }
+
+        /**
+         * Generates the HTML for the chosen pagination style.
+         *
+         * @param   string  pagination style
+         * @return  string  pagination html
+         */
+        public function render($style = NULL)
+        {
+                // Hide single page pagination
+                if ($this->auto_hide === TRUE AND $this->total_pages <= 1)
+                        return '';
+
+                if ($style === NULL)
+                {
+                        // Use default style
+                        $style = $this->style;
+                }
+
+                // Return rendered pagination view
+                return View::factory($this->directory.$style, get_object_vars($this))->render();
+        }
+
+        /**
+         * Magically converts Pagination object to string.
+         *
+         * @return  string  pagination html
+         */
+        public function __toString()
+        {
+                return $this->render();
+        }
+
+        /**
+         * Magically gets a pagination variable.
+         *
+         * @param   string  variable key
+         * @return  mixed   variable value if the key is found
+         * @return  void    if the key is not found
+         */
+        public function __get($key)
+        {
+                if (isset($this->$key))
+                        return $this->$key;
+        }
+
+        /**
+         * Adds a secondary interface for accessing properties, e.g. $pagination->total_pages().
+         * Note that $pagination->total_pages is the recommended way to access properties.
+         *
+         * @param   string  function name
+         * @return  string
+         */
+        public function __call($func, $args = NULL)
+        {
+                return $this->__get($func);
+        }
+
+} // End Pagination Class
\ No newline at end of file
diff --git a/modules/localprint/controllers/admin_localprint.php b/modules/localprint/controllers/admin_localprint.php
new file mode 100644
index 0000000..ba792fe
--- /dev/null
+++ b/modules/localprint/controllers/admin_localprint.php
@@ -0,0 +1,26 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Localprint_Controller extends Admin_Controller {
+  public function index() {
+    $v = new Admin_View("admin.html");
+    $v->content = new View("admin_localprint.html");
+    print $v;
+  }
+}
\ No newline at end of file
diff --git a/modules/localprint/css/localprint_menu.css b/modules/localprint/css/localprint_menu.css
new file mode 100644
index 0000000..1048d09
--- /dev/null
+++ b/modules/localprint/css/localprint_menu.css
@@ -0,0 +1,16 @@
+#g-view-menu #g-localprint-link {
+  background-image: url('../images/localprint_logo.png');
+}
+@media screen {
+  .printimage {
+	display: none;
+  }
+}
+@media print {
+  body * {
+    display: none;
+  }
+  .printimage {
+     display: block;
+  }
+}
\ No newline at end of file
diff --git a/modules/localprint/helpers/localprint_event.php b/modules/localprint/helpers/localprint_event.php
new file mode 100644
index 0000000..5fd9bf2
--- /dev/null
+++ b/modules/localprint/helpers/localprint_event.php
@@ -0,0 +1,39 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class localprint_event_Core {
+  static function admin_menu($menu, $theme) {
+    $menu->get("settings_menu")
+      ->append(Menu::factory("link")
+        ->id("localprint_menu")
+        ->label(t("Local print"))
+        ->url(url::site("admin/localprint")));
+  }
+
+  static function photo_menu($menu, $theme) {
+	if (access::can("view_full", $theme->item)) {
+    	$item = $theme->item();
+    	$menu->append(Menu::factory("link")
+                  ->id("localprint")
+                  ->label(t("Print with local printer"))
+                  ->url("#")
+                  ->css_id("g-localprint-link"));
+	}
+  }
+}
diff --git a/modules/localprint/helpers/localprint_installer.php b/modules/localprint/helpers/localprint_installer.php
new file mode 100644
index 0000000..7d45603
--- /dev/null
+++ b/modules/localprint/helpers/localprint_installer.php
@@ -0,0 +1,35 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class localprint_installer {
+  static function install() {
+    module::set_var("localprint", "username", "");
+    module::set_version("localprint", 1);
+  }
+
+  static function upgrade($version) {
+    if ($version == 1) {
+      module::set_version("localprint", $version = 1);
+    }
+  }
+
+  static function uninstall() {
+    module::delete("localprint");
+  }
+}
diff --git a/modules/localprint/helpers/localprint_theme.php b/modules/localprint/helpers/localprint_theme.php
new file mode 100644
index 0000000..d2c29d2
--- /dev/null
+++ b/modules/localprint/helpers/localprint_theme.php
@@ -0,0 +1,27 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class localprint_theme_Core {
+  static function head($theme) {
+   $theme->css("localprint_menu.css");
+  }
+  static function photo_bottom($theme) {
+	return new View("localprint_code.html");	
+  }
+}
diff --git a/modules/localprint/images/localprint_logo.png b/modules/localprint/images/localprint_logo.png
new file mode 100644
index 0000000..3022b09
Binary files /dev/null and b/modules/localprint/images/localprint_logo.png differ
diff --git a/modules/localprint/js/localprint.js b/modules/localprint/js/localprint.js
new file mode 100644
index 0000000..6f4ab22
--- /dev/null
+++ b/modules/localprint/js/localprint.js
@@ -0,0 +1,8 @@
+$(document).ready(function(){
+ alert('One');
+     $("#g-localprint-link").click(function() {
+       alert('The two of them');
+          $("body").append("<img src='<?= $item->file_url(true) ?>' class='printimage' >");
+          window.print();
+     });
+});
\ No newline at end of file
diff --git a/modules/localprint/module.info b/modules/localprint/module.info
new file mode 100644
index 0000000..558e3ba
--- /dev/null
+++ b/modules/localprint/module.info
@@ -0,0 +1,3 @@
+name = "Local print"
+description = "Adds a print button for users to print to a local printer."
+version = 1
diff --git a/modules/localprint/views/admin_localprint.html.php b/modules/localprint/views/admin_localprint.html.php
new file mode 100644
index 0000000..81bff35
--- /dev/null
+++ b/modules/localprint/views/admin_localprint.html.php
@@ -0,0 +1,4 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="g-block">
+  some stuff for the future
+</div>
diff --git a/modules/localprint/views/localprint_code.html.php b/modules/localprint/views/localprint_code.html.php
new file mode 100644
index 0000000..5e2541d
--- /dev/null
+++ b/modules/localprint/views/localprint_code.html.php
@@ -0,0 +1,9 @@
+<script language="javascript" type="text/javascript">
+$(document).ready(function(){
+     $("#g-localprint-link").click(function() {
+          $("body").append("<img src='<?= $item->file_url(true) ?>' class='printimage' >");
+          alert("Verify print settings.");
+          window.print();
+     });
+});
+</script>
\ No newline at end of file
diff --git a/modules/notification/controllers/notification.php b/modules/notification/controllers/notification.php
new file mode 100644
index 0000000..67f8ed3
--- /dev/null
+++ b/modules/notification/controllers/notification.php
@@ -0,0 +1,36 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Notification_Controller extends Controller {
+  function watch($id) {
+    access::verify_csrf();
+
+    $item = ORM::factory("item", $id);
+    access::required("view", $item);
+
+    if (notification::is_watching($item)) {
+      notification::remove_watch($item);
+      message::success(sprintf(t("You are no longer watching %s"), html::purify($item->title)));
+    } else {
+      notification::add_watch($item);
+      message::success(sprintf(t("You are now watching %s"), html::purify($item->title)));
+    }
+    url::redirect($item->abs_url());
+  }
+}
diff --git a/modules/notification/helpers/notification.php b/modules/notification/helpers/notification.php
new file mode 100644
index 0000000..96493a2
--- /dev/null
+++ b/modules/notification/helpers/notification.php
@@ -0,0 +1,218 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class notification {
+  static function get_subscription($item_id, $user=null) {
+    if (empty($user)) {
+      $user = identity::active_user();
+    }
+
+    return ORM::factory("subscription")
+      ->where("item_id", "=", $item_id)
+      ->where("user_id", "=", $user->id)
+      ->find();
+  }
+
+  static function is_watching($item, $user=null) {
+    if (empty($user)) {
+      $user = identity::active_user();
+    }
+
+    return ORM::factory("subscription")
+      ->where("item_id", "=", $item->id)
+      ->where("user_id", "=", $user->id)
+      ->find()
+      ->loaded();
+  }
+
+  static function add_watch($item, $user=null) {
+    if ($item->is_album()) {
+      if (empty($user)) {
+        $user = identity::active_user();
+      }
+      $subscription = ORM::factory("subscription");
+      $subscription->item_id = $item->id;
+      $subscription->user_id = $user->id;
+      $subscription->save();
+    }
+  }
+
+  static function remove_watch($item, $user=null) {
+    if ($item->is_album()) {
+      if (empty($user)) {
+        $user = identity::active_user();
+      }
+
+      $subscription = ORM::factory("subscription")
+        ->where("item_id", "=", $item->id)
+        ->where("user_id", "=", $user->id)
+        ->find()->delete();
+    }
+  }
+
+  static function get_subscribers($item) {
+    $subscriber_ids = array();
+    foreach (ORM::factory("subscription")
+             ->select("user_id")
+             ->join("items", "subscriptions.item_id", "items.id")
+             ->where("items.left_ptr", "<=", $item->left_ptr)
+             ->where("items.right_ptr", ">", $item->right_ptr)
+             ->find_all()
+             ->as_array() as $subscriber) {
+      $subscriber_ids[] = $subscriber->user_id;
+    }
+
+    if (empty($subscriber_ids)) {
+      return array();
+    }
+    $users = identity::get_user_list($subscriber_ids);
+
+    $subscribers = array();
+    foreach ($users as $user) {
+      if (access::user_can($user, "view", $item) && !empty($user->email)) {
+        $subscribers[$user->email] = $user->locale;
+      }
+    }
+    return $subscribers;
+  }
+
+  static function send_item_updated($original, $item) {
+    foreach (self::get_subscribers($item) as $email => $locale) {
+      $v = new View("item_updated.html");
+      $v->original = $original;
+      $v->item = $item;
+      $v->subject = $item->is_album() ?
+        t("Album \"%title\" updated", array("title" => $original->title, "locale" => $locale)) :
+        ($item->is_photo() ?
+         t("Photo \"%title\" updated", array("title" => $original->title, "locale" => $locale))
+         : t("Movie \"%title\" updated", array("title" => $original->title, "locale" => $locale)));
+      self::_notify($email, $locale, $item, $v->render(), $v->subject);
+    }
+  }
+
+  static function send_item_add($item) {
+    $parent = $item->parent();
+    foreach (self::get_subscribers($item) as $email => $locale) {
+      $v = new View("item_added.html");
+      $v->item = $item;
+      $v->subject = $item->is_album() ?
+        t("Album \"%title\" added to \"%parent_title\"",
+          array("title" => $item->title, "parent_title" => $parent->title, "locale" => $locale)) :
+        ($item->is_photo() ?
+         t("Photo \"%title\" added to \"%parent_title\"",
+           array("title" => $item->title, "parent_title" => $parent->title, "locale" => $locale)) :
+         t("Movie \"%title\" added to \"%parent_title\"",
+           array("title" => $item->title, "parent_title" => $parent->title, "locale" => $locale)));
+      self::_notify($email, $locale, $item, $v->render(), $v->subject);
+    }
+  }
+
+  static function send_item_deleted($item) {
+    $parent = $item->parent();
+    foreach (self::get_subscribers($item) as $email => $locale) {
+      $v = new View("item_deleted.html");
+      $v->item = $item;
+      $v->subject = $item->is_album() ?
+        t("Album \"%title\" removed from \"%parent_title\"",
+          array("title" => $item->title, "parent_title" => $parent->title, "locale" => $locale)) :
+        ($item->is_photo() ?
+         t("Photo \"%title\" removed from \"%parent_title\"",
+           array("title" => $item->title, "parent_title" => $parent->title, "locale" => $locale))
+         : t("Movie \"%title\" removed from \"%parent_title\"",
+             array("title" => $item->title, "parent_title" => $parent->title,
+                   "locale" => $locale)));
+      self::_notify($email, $locale, $item, $v->render(), $v->subject);
+    }
+  }
+
+  static function send_comment_published($comment) {
+    $item = $comment->item();
+    foreach (self::get_subscribers($item) as $email => $locale) {
+      $v = new View("comment_published.html");
+      $v->comment = $comment;
+      $v->subject = $item->is_album() ?
+        t("A new comment was published for album \"%title\"",
+          array("title" => $item->title, "locale" => $locale)) :
+      ($item->is_photo() ?
+       t("A new comment was published for photo \"%title\"",
+         array("title" => $item->title, "locale" => $locale))
+       : t("A new comment was published for movie \"%title\"",
+           array("title" => $item->title, "locale" => $locale)));
+      self::_notify($email, $locale, $item, $v->render(), $v->subject);
+    }
+  }
+
+  static function send_pending_notifications() {
+    foreach (db::build()
+             ->select(db::expr("DISTINCT `email`"))
+             ->from("pending_notifications")
+             ->execute() as $row) {
+      $email = $row->email;
+      $result = ORM::factory("pending_notification")
+        ->where("email", "=", $email)
+        ->find_all();
+      if ($result->count() == 1) {
+        $pending = $result->current();
+        Sendmail::factory()
+          ->to($email)
+          ->subject($pending->subject)
+          ->header("Mime-Version", "1.0")
+          ->header("Content-Type", "text/html; charset=UTF-8")
+          ->message($pending->text)
+          ->send();
+        $pending->delete();
+      } else {
+        $text = "";
+        $locale = null;
+        foreach ($result as $pending) {
+          $text .= $pending->text;
+          $locale = $pending->locale;
+          $pending->delete();
+        }
+        Sendmail::factory()
+          ->to($email)
+          ->subject(t("New activity for %site_name",
+                      array("site_name" => item::root()->title, "locale" => $locale)))
+          ->header("Mime-Version", "1.0")
+          ->header("Content-Type", "text/html; charset=UTF-8")
+          ->message($text)
+          ->send();
+      }
+    }
+  }
+
+  private static function _notify($email, $locale, $item, $text, $subject) {
+    if (!batch::in_progress()) {
+      Sendmail::factory()
+        ->to($email)
+        ->subject($subject)
+        ->header("Mime-Version", "1.0")
+        ->header("Content-Type", "text/html; charset=UTF-8")
+        ->message($text)
+        ->send();
+    } else {
+      $pending = ORM::factory("pending_notification");
+      $pending->subject = $subject;
+      $pending->text = $text;
+      $pending->email = $email;
+      $pending->locale = $locale;
+      $pending->save();
+    }
+  }
+}
diff --git a/modules/notification/helpers/notification_event.php b/modules/notification/helpers/notification_event.php
new file mode 100644
index 0000000..264ec55
--- /dev/null
+++ b/modules/notification/helpers/notification_event.php
@@ -0,0 +1,149 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class notification_event_Core {
+  // The assumption is that the exception was logged at a lower level, but we
+  // don't want to screw up the processing that was generating the notification
+  // so we don't pass the exception up the call stack
+  static function item_created($item) {
+    try {
+      notification::send_item_add($item);
+    } catch (Exception $e) {
+      Kohana_Log::add("error", "@todo notification_event::item_created() failed");
+      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+    }
+  }
+
+  static function item_deleted($item) {
+    try {
+      notification::send_item_deleted($item);
+
+      if (notification::is_watching($item)) {
+        notification::remove_watch($item);
+      }
+    } catch (Exception $e) {
+      Kohana_Log::add("error", "@todo notification_event::item_deleted() failed");
+      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+    }
+  }
+
+  static function user_deleted($user) {
+    db::build()
+      ->delete("subscriptions")
+      ->where("user_id", "=", $user->id)
+      ->execute();
+  }
+
+  static function identity_provider_changed($old_provider, $new_provider) {
+    db::build()
+      ->delete("subscriptions")
+      ->execute();
+  }
+
+  static function comment_created($comment) {
+    try {
+      if ($comment->state == "published") {
+        notification::send_comment_published($comment);
+      }
+    } catch (Exception $e) {
+      Kohana_Log::add("error", "@todo notification_event::comment_created() failed");
+      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+    }
+  }
+
+  static function comment_updated($original, $new) {
+    try {
+      if ($new->state == "published" && $original->state != "published") {
+        notification::send_comment_published($new);
+      }
+    } catch (Exception $e) {
+      Kohana_Log::add("error", "@todo notification_event::comment_updated() failed");
+      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+    }
+  }
+
+  static function user_before_delete($user) {
+    try {
+      db::build()
+        ->delete("subscriptions")
+        ->where("user_id", "=", $user->id)
+        ->execute();
+    } catch (Exception $e) {
+      Kohana_Log::add("error", "@todo notification_event::user_before_delete() failed");
+      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+    }
+  }
+
+  static function batch_complete() {
+    try {
+      notification::send_pending_notifications();
+    } catch (Exception $e) {
+      Kohana_Log::add("error", "@todo notification_event::batch_complete() failed");
+      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+    }
+  }
+
+  static function site_menu($menu, $theme) {
+    if (!identity::active_user()->guest) {
+      $item = $theme->item();
+
+      if ($item && $item->is_album() && access::can("view", $item)) {
+        $watching = notification::is_watching($item);
+
+        $label = $watching ? t("Remove notifications") : t("Enable notifications");
+
+        $menu->get("options_menu")
+          ->append(Menu::factory("link")
+                   ->id("watch")
+                   ->label($label)
+                   ->css_id("g-notify-link")
+                   ->url(url::site("notification/watch/$item->id?csrf=" . access::csrf_token())));
+      }
+    }
+  }
+
+  static function show_user_profile($data) {
+    // Guests don't see comment listings
+    if (identity::active_user()->guest) {
+      return;
+    }
+
+    // Only logged in users can see their comment listings
+    if (identity::active_user()->id != $data->user->id) {
+      return;
+    }
+
+    $view = new View("user_profile_notification.html");
+    $view->subscriptions = array();
+    foreach(ORM::factory("subscription")
+            ->where("user_id", "=", $data->user->id)
+            ->find_all() as $subscription) {
+      $item = ORM::factory("item")
+          ->where("id", "=", $subscription->item_id)
+          ->find();
+      if ($item->loaded()) {
+        $view->subscriptions[] = (object)array("id" => $subscription->id, "title" => $item->title,
+                                               "url" => $item->url());
+      }
+    }
+    if (count($view->subscriptions) > 0) {
+      $data->content[] = (object)array("title" => t("Watching"), "view" => $view);
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/notification/helpers/notification_installer.php b/modules/notification/helpers/notification_installer.php
new file mode 100644
index 0000000..f6b05c1
--- /dev/null
+++ b/modules/notification/helpers/notification_installer.php
@@ -0,0 +1,54 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class notification_installer {
+  static function install() {
+    $db = Database::instance();
+    $db->query("CREATE TABLE IF NOT EXISTS {subscriptions} (
+               `id` int(9) NOT NULL auto_increment,
+               `item_id` int(9) NOT NULL,
+               `user_id` int(9) NOT NULL,
+               PRIMARY KEY (`id`),
+               UNIQUE KEY (`item_id`, `user_id`),
+               UNIQUE KEY (`user_id`, `item_id`))
+               DEFAULT CHARSET=utf8;");
+    $db->query("CREATE TABLE IF NOT EXISTS {pending_notifications} (
+               `id` int(9) NOT NULL auto_increment,
+               `locale` char(10) default NULL,
+               `email` varchar(128) NOT NULL,
+               `subject` varchar(255) NOT NULL,
+               `text` text,
+               PRIMARY KEY (`id`))
+               DEFAULT CHARSET=utf8;");
+  }
+
+  static function upgrade($version) {
+    $db = Database::instance();
+    if ($version == 1) {
+      $db->query("ALTER TABLE {pending_notifications} ADD COLUMN `locale` char(10) default NULL");
+      module::set_version("notification", $version = 2);
+    }
+  }
+
+  static function uninstall() {
+    $db = Database::instance();
+    $db->query("DROP TABLE IF EXISTS {subscriptions};");
+    $db->query("DROP TABLE IF EXISTS {pending_notifications};");
+  }
+}
diff --git a/modules/notification/models/pending_notification.php b/modules/notification/models/pending_notification.php
new file mode 100644
index 0000000..4033aed
--- /dev/null
+++ b/modules/notification/models/pending_notification.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Pending_Notification_Model_Core extends ORM {
+}
\ No newline at end of file
diff --git a/modules/notification/models/subscription.php b/modules/notification/models/subscription.php
new file mode 100644
index 0000000..64996b6
--- /dev/null
+++ b/modules/notification/models/subscription.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Subscription_Model_Core extends ORM {
+}
\ No newline at end of file
diff --git a/modules/notification/module.info b/modules/notification/module.info
new file mode 100644
index 0000000..0e2cdb6
--- /dev/null
+++ b/modules/notification/module.info
@@ -0,0 +1,7 @@
+name = "Notification"
+description = "Send notifications to users when changes are made to watched albums."
+version = 2
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:notification"
+discuss_url = "http://galleryproject.org/forum_module_notification"
diff --git a/modules/notification/views/comment_published.html.php b/modules/notification/views/comment_published.html.php
new file mode 100644
index 0000000..ac36a2c
--- /dev/null
+++ b/modules/notification/views/comment_published.html.php
@@ -0,0 +1,35 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<html>
+  <head>
+    <title><?= html::clean($subject) ?> </title>
+  </head>
+  <body>
+    <h2><?= html::clean($subject) ?></h2>
+    <table>
+      <tr>
+        <td><?= t("Comment:") ?></td>
+  <td><?= nl2br(html::purify($comment->text)) ?></td>
+      </tr>
+      <tr>
+        <td><?= t("Author name:") ?></td>
+        <td><?= html::clean($comment->author_name()) ?></td>
+      </tr>
+      <tr>
+        <td><?= t("Author email:") ?></td>
+        <td><?= html::clean($comment->author_email()) ?></td>
+      </tr>
+      <tr>
+        <td><?= t("Author URL:") ?></td>
+        <td><?= html::clean($comment->author_url()) ?></td>
+      </tr>
+      <tr>
+        <td><?= t("Url:") ?></td>
+        <td>
+          <a href="<?= $comment->item()->abs_url() ?>#comments">
+            <?= $comment->item()->abs_url() ?>#comments
+          </a>
+        </td>
+      </tr>
+    </table>
+  </body>
+</html>
diff --git a/modules/notification/views/item_added.html.php b/modules/notification/views/item_added.html.php
new file mode 100644
index 0000000..1ea3720
--- /dev/null
+++ b/modules/notification/views/item_added.html.php
@@ -0,0 +1,29 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<html>
+  <head>
+    <title><?= html::clean($subject) ?> </title>
+  </head>
+  <body>
+    <h2><?= html::clean($subject) ?></h2>
+    <table>
+      <tr>
+        <td><?= t("Title:") ?></td>
+        <td><?= html::purify($item->title) ?></td>
+      </tr>
+      <tr>
+        <td><?= t("Url:") ?></td>
+        <td>
+          <a href="<?= $item->abs_url() ?>">
+            <?= $item->abs_url() ?>
+          </a>
+        </td>
+      </tr>
+      <? if ($item->description): ?>
+      <tr>
+        <td><?= t("Description:") ?></td>
+         <td><?= nl2br(html::purify($item->description)) ?></td>
+      </tr>
+      <? endif ?>
+    </table>
+  </body>
+</html>
diff --git a/modules/notification/views/item_deleted.html.php b/modules/notification/views/item_deleted.html.php
new file mode 100644
index 0000000..a95cdd8
--- /dev/null
+++ b/modules/notification/views/item_deleted.html.php
@@ -0,0 +1,25 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<html>
+  <head>
+    <title><?= html::clean($subject) ?> </title>
+  </head>
+  <body>
+    <h2><?= html::clean($subject) ?></h2>
+    <table>
+      <tr>
+        <td colspan="2">
+          <?= t("To view the changed album %title use the link below.",
+              array("title" => html::purify($item->parent()->title))) ?>
+        </td>
+      </tr>
+      <tr>
+        <td><?= t("Url:") ?></td>
+        <td>
+          <a href="<?= $item->parent()->abs_url() ?>">
+            <?= $item->parent()->abs_url() ?>
+          </a>
+        </td>
+      </tr>
+    </table>
+  </body>
+</html>
diff --git a/modules/notification/views/item_updated.html.php b/modules/notification/views/item_updated.html.php
new file mode 100644
index 0000000..7020fd5
--- /dev/null
+++ b/modules/notification/views/item_updated.html.php
@@ -0,0 +1,35 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<html>
+  <head>
+    <title><?= html::clean($subject) ?> </title>
+  </head>
+  <body>
+    <h2> <?= html::clean($subject) ?> </h2>
+    <table>
+      <tr>
+        <? if ($original->title != $item->title): ?>
+        <td><?= t("New title:") ?></td>
+        <td><?= html::clean($item->title) ?></td>
+        <? else: ?>
+        <td><?= t("Title:") ?></td>
+        <td><?= html::clean($item->title) ?></td>
+        <? endif ?>
+      </tr>
+      <tr>
+        <td><?= t("Url:") ?></td>
+        <td><a href="<?= $item->abs_url() ?>"><?= $item->abs_url() ?></a></td>
+      </tr>
+      <? if ($original->description != $item->description): ?>
+      <tr>
+        <td><?= t("New description:") ?></td>
+        <td><?= html::clean($item->description) ?></td>
+      </tr>
+      <? elseif (!empty($item->description)): ?>
+      <tr>
+        <td><?= t("Description:") ?></td>
+        <td><?= html::clean($item->description) ?></td>
+      </tr>
+      <? endif ?>
+    </table>
+  </body>
+</html>
diff --git a/modules/notification/views/user_profile_notification.html.php b/modules/notification/views/user_profile_notification.html.php
new file mode 100644
index 0000000..8864f0c
--- /dev/null
+++ b/modules/notification/views/user_profile_notification.html.php
@@ -0,0 +1,12 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-notification-detail">
+<ul>
+  <? foreach ($subscriptions as $subscription): ?>
+  <li id="g-watch-<?= $subscription->id ?>">
+    <a href="<?= $subscription->url ?>">
+      <?= html::purify($subscription->title) ?>
+    </a>
+  </li>
+  <? endforeach ?>
+</ul>
+</div>
diff --git a/modules/organize/controllers/organize.php b/modules/organize/controllers/organize.php
new file mode 100644
index 0000000..ba73ae7
--- /dev/null
+++ b/modules/organize/controllers/organize.php
@@ -0,0 +1,228 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Organize_Controller extends Controller {
+  function frame($album_id) {
+    $album = ORM::factory("item", $album_id);
+    access::required("view", $album);
+    access::required("edit", $album);
+
+    $v = new View("organize_frame.html");
+    $v->album = $album;
+    print $v;
+  }
+
+  function dialog($album_id) {
+    $album = ORM::factory("item", $album_id);
+    access::required("view", $album);
+    access::required("edit", $album);
+
+    $v = new View("organize_dialog.html");
+    $v->album = $album;
+    print $v;
+  }
+
+  function tree($selected_album_id) {
+    $root = ORM::factory("item", Input::instance()->post("root_id", 1));
+    $selected_album = ORM::factory("item", $selected_album_id);
+    access::required("view", $root);
+    access::required("view", $selected_album);
+
+    $tree = $this->_get_tree($root, $selected_album);
+    json::reply($tree);
+  }
+
+  function album_info($album_id) {
+    $album = ORM::factory("item", $album_id);
+    access::required("view", $album);
+
+    $data = array(
+      "sort_column" => $album->sort_column,
+      "sort_order" => $album->sort_order,
+      "editable" => access::can("edit", $album),
+      "title" => (string)html::clean($album->title),
+      "children" => array());
+
+    foreach ($album->viewable()->children() as $child) {
+      $dims = $child->scale_dimensions(120);
+      $data["children"][] = array(
+        "id" => $child->id,
+        "thumb_url" => $child->has_thumb() ? $child->thumb_url() : null,
+        "width" => $dims[1],
+        "height" => $dims[0],
+        "type" => $child->type,
+        "title" => (string)html::clean($child->title));
+    }
+    json::reply($data);
+  }
+
+  function reparent() {
+    access::verify_csrf();
+
+    $input = Input::instance();
+    $new_parent = ORM::factory("item", $input->post("target_id"));
+    access::required("edit", $new_parent);
+
+    foreach (explode(",", $input->post("source_ids")) as $source_id) {
+      $source = ORM::factory("item", $source_id);
+      if (!$source->loaded()) {
+        continue;
+      }
+      access::required("edit", $source->parent());
+
+      if ($source->contains($new_parent) || $source->id == $new_parent->id) {
+        // Can't move an item into its own hierarchy.  Silently skip this,
+        // since the UI shouldn't even allow this operation.
+        continue;
+      }
+
+      $source->parent_id = $new_parent->id;
+      $source->save();
+    }
+    json::reply(null);
+  }
+
+  function set_sort($album_id) {
+    access::verify_csrf();
+    $album = ORM::factory("item", $album_id);
+    access::required("view", $album);
+    access::required("edit", $album);
+
+    foreach (array("sort_column", "sort_order") as $key) {
+      if ($val = Input::instance()->post($key)) {
+        $album->$key = $val;
+      }
+    }
+    $album->save();
+
+    json::reply(null);
+  }
+
+  function rearrange() {
+    access::verify_csrf();
+
+    $input = Input::instance();
+    $target = ORM::factory("item", $input->post("target_id"));
+    if (!$target->loaded()) {
+      json::reply(null);
+      return;
+    }
+
+    $album = $target->parent();
+    access::required("edit", $album);
+
+    if ($album->sort_column != "weight") {
+      // Force all the weights into the current order before changing the order to manual
+      // @todo: consider making this a trigger in the Item_Model.
+      item::resequence_child_weights($album);
+      $album->sort_column = "weight";
+      $album->sort_order = "ASC";
+      $album->save();
+    }
+
+    $source_ids = explode(",", $input->post("source_ids"));
+    $base_weight = $target->weight;
+    if ($input->post("relative") == "after") {
+      $base_weight++;
+    }
+
+    if ($source_ids) {
+      // Make a hole the right size
+      db::build()
+        ->update("items")
+        ->set("weight", db::expr("`weight` + " . count($source_ids)))
+        ->where("parent_id", "=", $album->id)
+        ->where("weight", ">=", $base_weight)
+        ->execute();
+
+      // Move all the source items to the right spots.
+      for ($i = 0; $i < count($source_ids); $i++) {
+        $source = ORM::factory("item", $source_ids[$i]);
+        if ($source->parent_id == $album->id) {
+          $source->weight = $base_weight + $i;
+          $source->save();
+        }
+      }
+    }
+    json::reply(null);
+  }
+
+  function delete() {
+    access::verify_csrf();
+
+    $input = Input::instance();
+
+    foreach (explode(",", $input->post("item_ids")) as $item_id) {
+      $item = ORM::factory("item", $item_id);
+      if (access::can("edit", $item)) {
+        $item->delete();
+      }
+    }
+
+    json::reply(null);
+  }
+
+  function tag() {
+    access::verify_csrf();
+    $input = Input::instance();
+
+    foreach (explode(",", $input->post("item_ids")) as $item_id) {
+      $item = ORM::factory("item", $item_id);
+      if (access::can("edit", $item)) {
+        // Assuming the user can view/edit the current item, loop
+        // through each tag that was submitted and apply it to
+        // the current item.
+        foreach (explode(",", $input->post("tag_names")) as $tag_name) {
+          $tag_name = trim($tag_name);
+          if ($tag_name) {
+            tag::add($item, $tag_name);
+          }
+        }
+      }
+    }
+
+    json::reply(null);
+  }
+
+  private function _get_tree($item, $selected) {
+    $tree = array();
+    $children = $item->viewable()
+      ->children(null, null, array(array("type", "=", "album")))
+      ->as_array();
+    foreach ($children as $child) {
+      $node = array(
+        "allowDrag" => false,
+        "allowDrop" => access::can("edit", $child),
+        "editable" => false,
+        "expandable" => false,
+        "id" => $child->id,
+        "leaf" => $child->children_count(array(array("type", "=", "album"))) == 0,
+        "text" => (string)html::clean($child->title),
+        "nodeType" => "async");
+
+      // If the child is in the selected path, open it now.  Else, mark it async.
+      if ($child->contains($selected)) {
+        $node["children"] = $this->_get_tree($child, $selected);
+        $node["expanded"] = true;
+      }
+      $tree[] = $node;
+    }
+    return $tree;
+  }
+}
diff --git a/modules/organize/css/organize_dialog.css b/modules/organize/css/organize_dialog.css
new file mode 100644
index 0000000..2b39cdf
--- /dev/null
+++ b/modules/organize/css/organize_dialog.css
@@ -0,0 +1,17 @@
+#g-organize-frame {
+  border: 0px;
+  width: 100%;
+  height: 100%;
+}
+
+#g-organize-app-loading {
+  display: block;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 16px;
+  height: 16px;
+  background-image: url(../vendor/ext/images/default/tree/loading.gif);
+  background-position: center center;
+  background-repeat: no-repeat;
+}
diff --git a/modules/organize/css/organize_frame.css b/modules/organize/css/organize_frame.css
new file mode 100644
index 0000000..12bc609
--- /dev/null
+++ b/modules/organize/css/organize_frame.css
@@ -0,0 +1,118 @@
+.g-organize {
+  font-family: 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+}
+
+.g-organize div.thumb {
+  padding: 8px;
+  width: 128px;
+  height: 128px;
+  vertical-align: middle;
+  float: left;
+}
+
+.g-organize div.selected {
+  background: #C9D8EB;
+}
+
+.g-organize div.thumb {
+  border: 4px solid white;
+  text-align: center;
+}
+
+.g-organize div.thumb-missing span {
+  display: block;
+  background: #eee;
+  width: 120px;
+  height: 120px;
+  padding-top: 8px;
+  text-align: center;
+  font: 14px arial, tahoma;
+  border: 1px solid #ddd;
+  font-style: italic;
+}
+
+.g-organize div.thumb:hover {
+  border: 2px solid #eee;
+  margin: 2px;
+  cursor: pointer;
+}
+
+.g-organize div.thumb div.icon {
+  position: relative;
+  padding: 0px;
+  margin: 0px;
+  visibility: hidden;
+  width: 16px;
+  height: 16px;
+  top: -16px;
+  margin-bottom: -16px;
+  padding-bottom: -16px;
+}
+
+.g-organize div.thumb-album div.icon {
+  visibility: visible;
+}
+
+.g-organize div.drag-ghost {
+  width: 300px;
+  height: 180px;
+}
+
+.g-organize div.drag-ghost div {
+  width: 72px;
+  height: 72px;
+  vertical-align: baseline;
+  float: left;
+}
+
+.g-organize div.drop-target {
+  background: #eee;
+}
+
+.g-organize div.active-left {
+  border-left: 4px solid #C9D8EB;
+}
+
+.g-organize div.active-right {
+  border-right: 4px solid #C9D8EB;
+}
+
+.g-organize label.sort {
+  font: 12px arial, tahoma;
+  vertical-align: middle;
+  font-weight: bold;
+  height: 22px;
+  text-align: center;
+  padding: 4px;
+}
+
+.loading div {
+  font-size: 1.1em;
+  padding-left: 24px;
+  background-color: white;
+  background-image: url(../vendor/ext/images/default/tree/loading.gif);
+  background-position: 4px 8px;
+  background-repeat: no-repeat;
+}
+
+button.delete {
+  background-image: url(../vendor/ext/images/fam/delete.gif);
+  background-position: 10px 8px;
+  background-repeat: no-repeat;
+}
+
+/* IE specific overrides */
+body.ext-ie div.thumb {
+  width: 150px;
+  height: 150px;
+}
+
+/* ExtJS overrides */
+.x-tree-node-el {
+  font-size: 12px;
+  line-height: 20px;
+}
+
+.x-tree-node-leaf .x-tree-node-icon {
+  background-image:url(../vendor/ext/images/default/tree/folder.gif);
+}
diff --git a/modules/organize/helpers/organize_event.php b/modules/organize/helpers/organize_event.php
new file mode 100644
index 0000000..2ca9e9b
--- /dev/null
+++ b/modules/organize/helpers/organize_event.php
@@ -0,0 +1,54 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class organize_event_Core {
+  static function site_menu($menu, $theme) {
+    $item = $theme->item();
+
+    if ($item && $item->is_album() && access::can("edit", $item)) {
+      $menu->get("options_menu")
+        ->append(Menu::factory("dialog")
+                 ->id("organize")
+                 ->label(t("Organize album"))
+                 ->css_id("g-organize-link")
+                 ->url(url::site("organize/dialog/{$item->id}")));
+    }
+  }
+
+  static function context_menu($menu, $theme, $item) {
+    if (access::can("edit", $item)) {
+      if ($item->is_album()) {
+        $menu->get("options_menu")
+          ->append(Menu::factory("dialog")
+                   ->id("organize")
+                   ->label(t("Organize album"))
+                   ->css_class("ui-icon-folder-open g-organize-link")
+                   ->url(url::site("organize/dialog/{$item->id}")));
+      } else {
+        $parent = $item->parent();
+        $menu->get("options_menu")
+          ->append(Menu::factory("dialog")
+                   ->id("move")
+                   ->label(t("Move to another album"))
+                   ->css_class("ui-icon-folder-open g-organize-link")
+                   ->url(url::site("organize/dialog/{$parent->id}?selected_id={$item->id}")));
+      }
+    }
+  }
+}
diff --git a/modules/organize/helpers/organize_installer.php b/modules/organize/helpers/organize_installer.php
new file mode 100644
index 0000000..a2a0744
--- /dev/null
+++ b/modules/organize/helpers/organize_installer.php
@@ -0,0 +1,28 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class organize_installer {
+  static function upgrade($version) {
+    if ($version < 4) {
+      // No longer necessary, make sure that it's cleared.
+      site_status::clear("organize_needs_rest");
+      module::set_version("organize", $version = 4);
+    }
+  }
+}
diff --git a/modules/organize/module.info b/modules/organize/module.info
new file mode 100644
index 0000000..4d4560b
--- /dev/null
+++ b/modules/organize/module.info
@@ -0,0 +1,7 @@
+name = "Organize"
+description = "Visually rearrange and move photos in your gallery"
+version = 4
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:organize"
+discuss_url = "http://galleryproject.org/forum_module_organize"
diff --git a/modules/organize/vendor/ext/css/ext-all.css b/modules/organize/vendor/ext/css/ext-all.css
new file mode 100644
index 0000000..afef980
--- /dev/null
+++ b/modules/organize/vendor/ext/css/ext-all.css
@@ -0,0 +1,6969 @@
+/*!
+ * Ext JS Library 3.3.1
+ * Copyright(c) 2006-2010 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+html,body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}img,body,html{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}
+
+.ext-forced-border-box, .ext-forced-border-box * {
+    -moz-box-sizing: border-box;
+    -ms-box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+}
+.ext-el-mask {
+    z-index: 100;
+    position: absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity: .50;
+    filter: alpha(opacity=50);
+    width: 100%;
+    height: 100%;
+    zoom: 1;
+}
+
+.ext-el-mask-msg {
+    z-index: 20001;
+    position: absolute;
+    top: 0;
+    left: 0;
+    border:1px solid;
+    background:repeat-x 0 -16px;
+    padding:2px;
+}
+
+.ext-el-mask-msg div {
+    padding:5px 10px 5px 10px;
+    border:1px solid;
+    cursor:wait;
+}
+
+.ext-shim {
+    position:absolute;
+    visibility:hidden;
+    left:0;
+    top:0;
+    overflow:hidden;
+}
+
+.ext-ie .ext-shim {
+    filter: alpha(opacity=0);
+}
+
+.ext-ie6 .ext-shim {
+    margin-left: 5px;
+    margin-top: 3px;
+}
+
+.x-mask-loading div {
+    padding:5px 10px 5px 25px;
+    background:no-repeat 5px 5px;
+    line-height:16px;
+}
+
+/* class for hiding elements without using display:none */
+.x-hidden, .x-hide-offsets {
+    position:absolute !important;
+    left:-10000px;
+    top:-10000px;
+    visibility:hidden;
+}
+
+.x-hide-display {
+    display:none !important;
+}
+
+.x-hide-nosize,
+.x-hide-nosize *    /* Emulate display:none for children */
+ {
+   height:0px!important;
+   width:0px!important;
+   visibility:hidden!important;
+   border:none!important;
+   zoom:1;
+}
+
+.x-hide-visibility {
+    visibility:hidden !important;
+}
+
+.x-masked {
+    overflow: hidden !important;
+}
+.x-masked-relative {
+    position: relative !important;
+}
+
+.x-masked select, .x-masked object, .x-masked embed {
+    visibility: hidden;
+}
+
+.x-layer {
+    visibility: hidden;
+}
+
+.x-unselectable, .x-unselectable * {
+    -moz-user-select: none;
+    -khtml-user-select: none;
+    -webkit-user-select:ignore;
+}
+
+.x-repaint {
+    zoom: 1;
+    background-color: transparent;
+    -moz-outline: none;
+    outline: none;
+}
+
+.x-item-disabled {
+    cursor: default;
+    opacity: .6;
+    -moz-opacity: .6;
+    filter: alpha(opacity=60);
+}
+
+.x-item-disabled * {
+    cursor: default !important;
+}
+
+.x-form-radio-group .x-item-disabled {
+    filter: none;
+}
+
+.x-splitbar-proxy {
+    position: absolute;
+    visibility: hidden;
+    z-index: 20001;
+    zoom: 1;
+    line-height: 1px;
+    font-size: 1px;
+    overflow: hidden;
+}
+
+.x-splitbar-h, .x-splitbar-proxy-h {
+    cursor: e-resize;
+    cursor: col-resize;
+}
+
+.x-splitbar-v, .x-splitbar-proxy-v {
+    cursor: s-resize;
+    cursor: row-resize;
+}
+
+.x-color-palette {
+    width: 150px;
+    height: 92px;
+    cursor: pointer;
+}
+
+.x-color-palette a {
+    border: 1px solid;
+    float: left;
+    padding: 2px;
+    text-decoration: none;
+    -moz-outline: 0 none;
+    outline: 0 none;
+    cursor: pointer;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border: 1px solid;
+}
+
+.x-color-palette em {
+    display: block;
+    border: 1px solid;
+}
+
+.x-color-palette em span {
+    cursor: pointer;
+    display: block;
+    height: 10px;
+    line-height: 10px;
+    width: 10px;
+}
+
+.x-ie-shadow {
+    display: none;
+    position: absolute;
+    overflow: hidden;
+    left:0;
+    top:0;
+    zoom:1;
+}
+
+.x-shadow {
+    display: none;
+    position: absolute;
+    overflow: hidden;
+    left:0;
+    top:0;
+}
+
+.x-shadow * {
+    overflow: hidden;
+}
+
+.x-shadow * {
+    padding: 0;
+    border: 0;
+    margin: 0;
+    clear: none;
+    zoom: 1;
+}
+
+/* top  bottom */
+.x-shadow .xstc, .x-shadow .xsbc {
+    height: 6px;
+    float: left;
+}
+
+/* corners */
+.x-shadow .xstl, .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbr {
+    width: 6px;
+    height: 6px;
+    float: left;
+}
+
+/* sides */
+.x-shadow .xsc {
+    width: 100%;
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    width: 6px;
+    float: left;
+    height: 100%;
+}
+
+.x-shadow .xsmc {
+    float: left;
+    height: 100%;
+    background-color: transparent;
+}
+
+.x-shadow .xst, .x-shadow .xsb {
+    height: 6px;
+    overflow: hidden;
+    width: 100%;
+}
+
+.x-shadow .xsml {
+    background: transparent repeat-y 0 0;
+}
+
+.x-shadow .xsmr {
+    background: transparent repeat-y -6px 0;
+}
+
+.x-shadow .xstl {
+    background: transparent no-repeat 0 0;
+}
+
+.x-shadow .xstc {
+    background: transparent repeat-x 0 -30px;
+}
+
+.x-shadow .xstr {
+    background: transparent repeat-x 0 -18px;
+}
+
+.x-shadow .xsbl {
+    background: transparent no-repeat 0 -12px;
+}
+
+.x-shadow .xsbc {
+    background: transparent repeat-x 0 -36px;
+}
+
+.x-shadow .xsbr {
+    background: transparent repeat-x 0 -6px;
+}
+
+.loading-indicator {
+    background: no-repeat left;
+    padding-left: 20px;
+    line-height: 16px;
+    margin: 3px;
+}
+
+.x-text-resize {
+    position: absolute;
+    left: -1000px;
+    top: -1000px;
+    visibility: hidden;
+    zoom: 1;
+}
+
+.x-drag-overlay {
+    width: 100%;
+    height: 100%;
+    display: none;
+    position: absolute;
+    left: 0;
+    top: 0;
+    background-image:url(../images/default/s.gif);
+    z-index: 20000;
+}
+
+.x-clear {
+    clear:both;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+
+.x-spotlight {
+    z-index: 8999;
+    position: absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity: .50;
+    filter: alpha(opacity=50);
+    width:0;
+    height:0;
+    zoom: 1;
+}
+
+#x-history-frame {
+    position:absolute;
+    top:-1px;
+    left:0;
+	width:1px;
+    height:1px;
+    visibility:hidden;
+}
+
+#x-history-field {
+    position:absolute;
+    top:0;
+    left:-1px;
+	width:1px;
+    height:1px;
+    visibility:hidden;
+}
+.x-resizable-handle {
+    position:absolute;
+    z-index:100;
+    /* ie needs these */
+    font-size:1px;
+    line-height:6px;
+    overflow:hidden;
+	filter:alpha(opacity=0);
+	opacity:0;
+	zoom:1;
+}
+
+.x-resizable-handle-east{
+    width:6px;
+    cursor:e-resize;
+    right:0;
+    top:0;
+    height:100%;
+}
+
+.ext-ie .x-resizable-handle-east {
+    margin-right:-1px; /*IE rounding error*/
+}
+
+.x-resizable-handle-south{
+    width:100%;
+    cursor:s-resize;
+    left:0;
+    bottom:0;
+    height:6px;
+}
+
+.ext-ie .x-resizable-handle-south {
+    margin-bottom:-1px; /*IE rounding error*/
+}
+
+.x-resizable-handle-west{
+    width:6px;
+    cursor:w-resize;
+    left:0;
+    top:0;
+    height:100%;
+}
+
+.x-resizable-handle-north{
+    width:100%;
+    cursor:n-resize;
+    left:0;
+    top:0;
+    height:6px;
+}
+
+.x-resizable-handle-southeast{
+    width:6px;
+    cursor:se-resize;
+    right:0;
+    bottom:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-northwest{
+    width:6px;
+    cursor:nw-resize;
+    left:0;
+    top:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-northeast{
+    width:6px;
+    cursor:ne-resize;
+    right:0;
+    top:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-handle-southwest{
+    width:6px;
+    cursor:sw-resize;
+    left:0;
+    bottom:0;
+    height:6px;
+    z-index:101;
+}
+
+.x-resizable-over .x-resizable-handle, .x-resizable-pinned .x-resizable-handle{
+    filter:alpha(opacity=100);
+	opacity:1;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+	background-position: left;
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-position: top;
+}
+
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-position: top left;
+}
+
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-position:bottom right;
+}
+
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-position: bottom left;
+}
+
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-position: top right;
+}
+
+.x-resizable-proxy{
+    border: 1px dashed;
+    position:absolute;
+    overflow:hidden;
+    display:none;
+	left:0;
+    top:0;
+    z-index:50000;
+}
+
+.x-resizable-overlay{
+    width:100%;
+	height:100%;
+	display:none;
+	position:absolute;
+	left:0;
+	top:0;
+	z-index:200000;
+	-moz-opacity: 0;
+    opacity:0;
+    filter: alpha(opacity=0);
+}
+.x-tab-panel {
+    overflow:hidden;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border: 1px solid;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header {
+	border: 1px solid;
+	padding-bottom: 2px;
+}
+
+.x-tab-panel-footer {
+	border: 1px solid;
+	padding-top: 2px;
+}
+
+.x-tab-strip-wrap {
+	width:100%;
+    overflow:hidden;
+    position:relative;
+    zoom:1;
+}
+
+ul.x-tab-strip {
+	display:block;
+    width:5000px;
+    zoom:1;
+}
+
+ul.x-tab-strip-top{
+	padding-top: 1px;
+	background: repeat-x bottom;
+	border-bottom: 1px solid;
+}
+
+ul.x-tab-strip-bottom{
+	padding-bottom: 1px;
+	background: repeat-x top;
+	border-top: 1px solid;
+	border-bottom: 0 none;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-top {
+    background:transparent !important;
+    padding-top:0 !important;
+}
+
+.x-tab-panel-header-plain {
+    background:transparent !important;
+    border-width:0 !important;
+    padding-bottom:0 !important;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border:1px solid;
+    height:2px;
+    font-size:1px;
+    line-height:1px;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer {
+    border-top: 0 none;
+}
+
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-bottom: 0 none;
+}
+
+.x-tab-panel-footer-plain .x-tab-strip-bottom {
+    background:transparent !important;
+    padding-bottom:0 !important;
+}
+
+.x-tab-panel-footer-plain {
+    background:transparent !important;
+    border-width:0 !important;
+    padding-top:0 !important;
+}
+
+.ext-border-box .x-tab-panel-header-plain .x-tab-strip-spacer,
+.ext-border-box .x-tab-panel-footer-plain .x-tab-strip-spacer {
+    height:3px;
+}
+
+ul.x-tab-strip li {
+    float:left;
+    margin-left:2px;
+}
+
+ul.x-tab-strip li.x-tab-edge {
+    float:left;
+    margin:0 !important;
+    padding:0 !important;
+    border:0 none !important;
+    font-size:1px !important;
+    line-height:1px !important;
+    overflow:hidden;
+    zoom:1;
+    background:transparent !important;
+    width:1px;
+}
+
+.x-tab-strip a, .x-tab-strip span, .x-tab-strip em {
+	display:block;
+}
+
+.x-tab-strip a {
+	text-decoration:none !important;
+	-moz-outline: none;
+	outline: none;
+	cursor:pointer;
+}
+
+.x-tab-strip-inner {
+    overflow:hidden;
+	text-overflow: ellipsis;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	white-space: nowrap;
+	cursor:pointer;
+    padding:4px 0;
+}
+
+.x-tab-strip-top .x-tab-with-icon .x-tab-right {
+    padding-left:6px;
+}
+
+.x-tab-strip .x-tab-with-icon span.x-tab-strip-text {
+	padding-left:20px;
+    background-position: 0 3px;
+    background-repeat: no-repeat;
+}
+
+.x-tab-strip-active, .x-tab-strip-active a.x-tab-right {
+    cursor:default;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	cursor:default;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	cursor:default;
+}
+
+.x-tab-panel-body {
+    overflow:hidden;
+}
+
+.x-tab-panel-bwrap {
+    overflow:hidden;
+}
+
+.ext-ie .x-tab-strip .x-tab-right {
+    position:relative;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right {
+    margin-bottom:-1px;
+}
+
+/*
+ * Horrible hack for IE8 in quirks mode
+ */
+.ext-ie8 .x-tab-strip li {
+    position: relative;
+}
+.ext-border-box .ext-ie8 .x-tab-strip-top .x-tab-right {
+    top: 1px;
+}
+.ext-ie8 .x-tab-strip-top {
+    padding-top: 1;
+}
+.ext-border-box .ext-ie8 .x-tab-strip-top {
+    padding-top: 0;
+}
+.ext-ie8 .x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    top:3px;
+}
+.ext-border-box .ext-ie8 .x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    top:4px;
+}
+.ext-ie8 .x-tab-strip-bottom .x-tab-right{
+    top:0;
+}
+
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right span.x-tab-strip-text {
+    padding-bottom:5px;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+    margin-top:-1px;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right span.x-tab-strip-text {
+    padding-top:5px;
+}
+
+.x-tab-strip-top .x-tab-right {
+	background: transparent no-repeat 0 -51px;
+    padding-left:10px;
+}
+
+.x-tab-strip-top .x-tab-left {
+	background: transparent no-repeat right -351px;
+    padding-right:10px;
+}
+
+.x-tab-strip-top .x-tab-strip-inner {
+	background: transparent repeat-x 0 -201px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-right {
+	 background-position:0 -101px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-left {
+	 background-position:right -401px;
+}
+
+.x-tab-strip-top .x-tab-strip-over .x-tab-strip-inner {
+	 background-position:0 -251px;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-right {
+	background-position: 0 0;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-left {
+	background-position: right -301px;
+}
+
+.x-tab-strip-top .x-tab-strip-active .x-tab-strip-inner {
+	background-position: 0 -151px;
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background: no-repeat bottom right;
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background: no-repeat bottom left;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background: no-repeat bottom right;
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background: no-repeat bottom left;
+}
+
+.x-tab-strip-bottom .x-tab-left {
+    margin-right: 3px;
+    padding:0 10px;
+}
+
+.x-tab-strip-bottom .x-tab-right {
+    padding:0;
+}
+
+.x-tab-strip .x-tab-strip-close {
+    display:none;
+}
+
+.x-tab-strip-closable {
+    position:relative;
+}
+
+.x-tab-strip-closable .x-tab-left {
+    padding-right:19px;
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+    opacity:.6;
+    -moz-opacity:.6;
+    background-repeat:no-repeat;
+    display:block;
+	width:11px;
+    height:11px;
+    position:absolute;
+    top:3px;
+    right:3px;
+    cursor:pointer;
+    z-index:2;
+}
+
+.x-tab-strip .x-tab-strip-active a.x-tab-strip-close {
+    opacity:.8;
+    -moz-opacity:.8;
+}
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+    opacity:1;
+    -moz-opacity:1;
+}
+
+.x-tab-panel-body {
+    border: 1px solid;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background: transparent no-repeat -18px 0;
+    border-bottom: 1px solid;
+    width:18px;
+    position:absolute;
+    left:0;
+    top:0;
+    z-index:10;
+    cursor:pointer;
+}
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background: transparent no-repeat 0 0;
+    border-bottom: 1px solid;
+    width:18px;
+    position:absolute;
+    right:0;
+    top:0;
+    z-index:10;
+    cursor:pointer;
+}
+
+.x-tab-scroller-right-over {
+    background-position: -18px 0;
+}
+
+.x-tab-scroller-right-disabled {
+    background-position: 0 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scrolling-bottom .x-tab-scroller-left, .x-tab-scrolling-bottom .x-tab-scroller-right{
+    margin-top: 1px;
+}
+
+.x-tab-scrolling .x-tab-strip-wrap {
+    margin-left:18px;
+    margin-right:18px;
+}
+
+.x-tab-scrolling {
+    position:relative;    
+}
+
+.x-tab-panel-bbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-tab-panel-tbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}/* all fields */
+.x-form-field{
+    margin: 0 0 0 0;
+}
+
+.ext-webkit *:focus{
+    outline: none !important;
+}
+
+/* ---- text fields ---- */
+.x-form-text, textarea.x-form-field{
+    padding:1px 3px;
+    background:repeat-x 0 0;
+    border:1px solid;
+}
+
+textarea.x-form-field {
+    padding:2px 3px;
+}
+
+.x-form-text, .ext-ie .x-form-file {
+    height:22px;
+    line-height:18px;
+    vertical-align:middle;
+}
+
+.ext-ie6 .x-form-text, .ext-ie7 .x-form-text {
+    margin:-1px 0; /* ie bogus margin bug */
+    height:22px; /* ie quirks */
+    line-height:18px;
+}
+
+.ext-ie6 .x-form-field-wrap .x-form-file-btn, .ext-ie7 .x-form-field-wrap .x-form-file-btn {
+    top: -1px; /* because of all these margin hacks, these buttons are off by one pixel in IE6,7 */
+}
+
+.ext-ie6 textarea.x-form-field, .ext-ie7 textarea.x-form-field {
+    margin:-1px 0; /* ie bogus margin bug */
+}
+
+.ext-strict .x-form-text {
+    height:18px;
+}
+
+.ext-safari.ext-mac textarea.x-form-field {
+    margin-bottom:-2px; /* another bogus margin bug, safari/mac only */
+}
+
+/*
+.ext-strict .ext-ie8 .x-form-text, .ext-strict .ext-ie8 textarea.x-form-field {
+    margin-bottom: 1px;
+}
+*/
+
+.ext-gecko .x-form-text , .ext-ie8 .x-form-text {
+    padding-top:2px; /* FF won't center the text vertically */
+    padding-bottom:0;
+}
+
+.ext-ie6 .x-form-composite .x-form-text.x-box-item, .ext-ie7 .x-form-composite .x-form-text.x-box-item {
+    margin: 0 !important; /* clear ie bogus margin bug fix */
+}
+
+textarea {
+    resize: none;  /* Disable browser resizable textarea */
+}
+
+/* select boxes */
+.x-form-select-one {
+    height:20px;
+    line-height:18px;
+    vertical-align:middle;
+    border: 1px solid;
+}
+
+/* multi select boxes */
+
+/* --- TODO --- */
+
+/* 2.0.2 style */
+.x-form-check-wrap {
+    line-height:18px;
+    height: auto;
+}
+
+.ext-ie .x-form-check-wrap input {
+    width:15px;
+    height:15px;
+}
+
+.x-form-check-wrap input{
+    vertical-align: bottom;
+}
+
+.x-editor .x-form-check-wrap {
+    padding:3px;
+}
+
+.x-editor .x-form-checkbox {
+    height:13px;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid;
+    margin-bottom: 5px;
+    padding-left: 3px !important;
+    float: none !important;
+}
+
+/* wrapped fields and triggers */
+.x-form-field-wrap .x-form-trigger{
+    width:17px;
+    height:21px;
+    border:0;
+    background:transparent no-repeat 0 0;
+    cursor:pointer;
+    border-bottom: 1px solid;
+    position:absolute;
+    top:0;
+}
+
+.x-form-field-wrap .x-form-date-trigger, .x-form-field-wrap .x-form-clear-trigger, .x-form-field-wrap .x-form-search-trigger{
+    cursor:pointer;
+}
+
+.x-form-field-wrap .x-form-twin-triggers .x-form-trigger{
+    position:static;
+    top:auto;
+    vertical-align:top;
+}
+
+.x-form-field-wrap {
+    position:relative;
+    left:0;top:0;
+    text-align: left;
+    zoom:1;
+    white-space: nowrap;
+}
+
+.ext-strict .ext-ie8 .x-toolbar-cell .x-form-field-trigger-wrap .x-form-trigger {
+    right: 0; /* IE8 Strict mode trigger bug */
+}
+
+.x-form-field-wrap .x-form-trigger-over{
+    background-position:-17px 0;
+}
+
+.x-form-field-wrap .x-form-trigger-click{
+    background-position:-34px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    background-position:-51px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-over{
+    background-position:-68px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger-click{
+    background-position:-85px 0;
+}
+
+.x-trigger-wrap-focus .x-form-trigger{
+    border-bottom: 1px solid;
+}
+
+.x-item-disabled .x-form-trigger-over{
+    background-position:0 0 !important;
+    border-bottom: 1px solid;
+}
+
+.x-item-disabled .x-form-trigger-click{
+    background-position:0 0 !important;
+    border-bottom: 1px solid;
+}
+
+.x-trigger-noedit{
+    cursor:pointer;
+}
+
+/* field focus style */
+.x-form-focus, textarea.x-form-focus{
+    border: 1px solid;
+}
+
+/* invalid fields */
+.x-form-invalid, textarea.x-form-invalid{
+    background:repeat-x bottom;
+    border: 1px solid;
+}
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid{
+    background:repeat-x bottom;
+}
+
+/* editors */
+.x-editor {
+    visibility:hidden;
+    padding:0;
+    margin:0;
+}
+
+.x-form-grow-sizer {
+    left: -10000px;
+    padding: 8px 3px;
+    position: absolute;
+    visibility:hidden;
+    top: -10000px;
+    white-space: pre-wrap;
+    white-space: -moz-pre-wrap;
+    white-space: -pre-wrap;
+    white-space: -o-pre-wrap;
+    word-wrap: break-word;
+    zoom:1;
+}
+
+.x-form-grow-sizer p {
+    margin:0 !important;
+    border:0 none !important;
+    padding:0 !important;
+}
+
+/* Form Items CSS */
+
+.x-form-item {
+    display:block;
+    margin-bottom:4px;
+    zoom:1;
+}
+
+.x-form-item label.x-form-item-label {
+    display:block;
+    float:left;
+    width:100px;
+    padding:3px;
+    padding-left:0;
+    clear:left;
+    z-index:2;
+    position:relative;
+}
+
+.x-form-element {
+    padding-left:105px;
+    position:relative;
+}
+
+.x-form-invalid-msg {
+    padding:2px;
+    padding-left:18px;
+    background: transparent no-repeat 0 2px;
+    line-height:16px;
+    width:200px;
+}
+
+.x-form-label-left label.x-form-item-label {
+   text-align:left;
+}
+
+.x-form-label-right label.x-form-item-label {
+   text-align:right;
+}
+
+.x-form-label-top .x-form-item label.x-form-item-label {
+    width:auto;
+    float:none;
+    clear:none;
+    display:inline;
+    margin-bottom:4px;
+    position:static;
+}
+
+.x-form-label-top .x-form-element {
+    padding-left:0;
+    padding-top:4px;
+}
+
+.x-form-label-top .x-form-item {
+    padding-bottom:4px;
+}
+
+/* Editor small font for grid, toolbar and tree */
+.x-small-editor .x-form-text {
+    height:20px;
+    line-height:16px;
+    vertical-align:middle;
+}
+
+.ext-ie6 .x-small-editor .x-form-text, .ext-ie7 .x-small-editor .x-form-text {
+    margin-top:-1px !important; /* ie bogus margin bug */
+    margin-bottom:-1px !important;
+    height:20px !important; /* ie quirks */
+    line-height:16px !important;
+}
+
+.ext-strict .x-small-editor .x-form-text {
+    height:16px !important;
+}
+
+.ext-ie6 .x-small-editor .x-form-text, .ext-ie7 .x-small-editor .x-form-text {
+    height:20px;
+    line-height:16px;
+}
+
+.ext-border-box .x-small-editor .x-form-text {
+    height:20px;
+}
+
+.x-small-editor .x-form-select-one {
+    height:20px;
+    line-height:16px;
+    vertical-align:middle;
+}
+
+.x-small-editor .x-form-num-field {
+    text-align:right;
+}
+
+.x-small-editor .x-form-field-wrap .x-form-trigger{
+    height:19px;
+}
+
+.ext-webkit .x-small-editor .x-form-text{padding-top:3px;font-size:100%;}
+
+.x-form-clear {
+    clear:both;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+.x-form-clear-left {
+    clear:left;
+    height:0;
+    overflow:hidden;
+    line-height:0;
+    font-size:0;
+}
+
+.ext-ie6 .x-form-check-wrap input, .ext-border-box .x-form-check-wrap input{
+   margin-top: 3px;
+}
+
+.x-form-cb-label {
+    position: relative;
+    margin-left:4px;
+    top: 2px;
+}
+
+.ext-ie .x-form-cb-label{
+    top: 1px;
+}
+
+.ext-ie6 .x-form-cb-label, .ext-border-box .x-form-cb-label{
+    top: 3px;
+}
+
+.x-form-display-field{
+    padding-top: 2px;
+}
+
+.ext-gecko .x-form-display-field, .ext-strict .ext-ie7 .x-form-display-field{
+    padding-top: 1px;
+}
+
+.ext-ie .x-form-display-field{
+    padding-top: 3px;
+}
+
+.ext-strict .ext-ie8 .x-form-display-field{
+    padding-top: 0;
+}
+
+.x-form-column {
+    float:left;
+    padding:0;
+    margin:0;
+    width:48%;
+    overflow:hidden;
+    zoom:1;
+}
+
+/* buttons */
+.x-form .x-form-btns-ct .x-btn{
+    float:right;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns td {
+    border:0;
+    padding:0;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-right table{
+    float:right;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-left table{
+    float:left;
+    clear:none;
+}
+
+.x-form .x-form-btns-ct .x-form-btns-center{
+    text-align:center; /*ie*/
+}
+
+.x-form .x-form-btns-ct .x-form-btns-center table{
+    margin:0 auto; /*everyone else*/
+}
+
+.x-form .x-form-btns-ct table td.x-form-btn-td{
+    padding:3px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-left{
+    background-position:0 -147px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-right{
+    background-position:0 -168px;
+}
+
+.x-form .x-form-btns-ct .x-btn-focus .x-btn-center{
+    background-position:0 -189px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click .x-btn-center{
+    background-position:0 -126px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click  .x-btn-right{
+    background-position:0 -84px;
+}
+
+.x-form .x-form-btns-ct .x-btn-click .x-btn-left{
+    background-position:0 -63px;
+}
+
+.x-form-invalid-icon {
+    width:16px;
+    height:18px;
+    visibility:hidden;
+    position:absolute;
+    left:0;
+    top:0;
+    display:block;
+    background:transparent no-repeat 0 2px;
+}
+
+/* fieldsets */
+.x-fieldset {
+    border:1px solid;
+    padding:10px;
+    margin-bottom:10px;
+    display:block; /* preserve margins in IE */
+}
+
+/* make top of checkbox/tools visible in webkit */
+.ext-webkit .x-fieldset-header {
+    padding-top: 1px;
+}
+
+.ext-ie .x-fieldset legend {
+    margin-bottom:10px;
+}
+
+.ext-ie .x-fieldset {
+    padding-top: 0;
+    padding-bottom:10px;
+}
+
+.x-fieldset legend .x-tool-toggle {
+    margin-right:3px;
+    margin-left:0;
+    float:left !important;
+}
+
+.x-fieldset legend input {
+    margin-right:3px;
+    float:left !important;
+    height:13px;
+    width:13px;
+}
+
+fieldset.x-panel-collapsed {
+    padding-bottom:0 !important;
+    border-width: 1px 1px 0 1px !important;
+    border-left-color: transparent;
+    border-right-color: transparent;
+}
+
+.ext-ie6 fieldset.x-panel-collapsed{
+    padding-bottom:0 !important;
+    border-width: 1px 0 0 0 !important;
+    margin-left: 1px;
+    margin-right: 1px;
+}
+
+fieldset.x-panel-collapsed .x-fieldset-bwrap {
+    visibility:hidden;
+    position:absolute;
+    left:-1000px;
+    top:-1000px;
+}
+
+.ext-ie .x-fieldset-bwrap {
+    zoom:1;
+}
+
+.x-fieldset-noborder {
+    border:0px none transparent;
+}
+
+.x-fieldset-noborder legend {
+    margin-left:-3px;
+}
+
+/* IE legend positioning bug */
+.ext-ie .x-fieldset-noborder legend {
+    position: relative;
+    margin-bottom:23px;
+}
+.ext-ie .x-fieldset-noborder legend span {
+    position: absolute;
+    left:16px;
+}
+
+.ext-gecko .x-window-body .x-form-item {
+    -moz-outline: none;
+    outline: none;
+    overflow: auto;
+}
+
+.ext-mac.ext-gecko .x-window-body .x-form-item {
+    overflow:hidden;
+}
+
+.ext-gecko .x-form-item {
+    -moz-outline: none;
+    outline: none;
+}
+
+.x-hide-label label.x-form-item-label {
+     display:none;
+}
+
+.x-hide-label .x-form-element {
+     padding-left: 0 !important;
+}
+
+.x-form-label-top .x-hide-label label.x-form-item-label{
+    display: none;
+}
+
+.x-fieldset {
+    overflow:hidden;
+}
+
+.x-fieldset-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-fieldset-body {
+    overflow:hidden;
+}
+.x-btn{
+	cursor:pointer;
+	white-space: nowrap;
+}
+
+.x-btn button{
+    border:0 none;
+    background-color:transparent;
+    padding-left:3px;
+    padding-right:3px;
+    cursor:pointer;
+    margin:0;
+    overflow:visible;
+    width:auto;
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+* html .ext-ie .x-btn button {
+    width:1px;
+}
+
+.ext-gecko .x-btn button, .ext-webkit .x-btn button {
+    padding-left:0;
+    padding-right:0;
+}
+
+.ext-gecko .x-btn button::-moz-focus-inner {
+    padding:0;
+}
+
+.ext-ie .x-btn button {
+    padding-top:2px;
+}
+
+.x-btn td {
+    padding:0 !important;
+}
+
+.x-btn-text {
+    cursor:pointer;
+	white-space: nowrap;
+    padding:0;
+}
+
+/* icon placement and sizing styles */
+
+/* Only text */
+.x-btn-noicon .x-btn-small .x-btn-text{
+	height: 16px;
+}
+
+.x-btn-noicon .x-btn-medium .x-btn-text{
+    height: 24px;
+}
+
+.x-btn-noicon .x-btn-large .x-btn-text{
+    height: 32px;
+}
+
+/* Only icons */
+.x-btn-icon .x-btn-text{
+    background-position: center;
+	background-repeat: no-repeat;
+}
+
+.x-btn-icon .x-btn-small .x-btn-text{
+	height: 16px;
+	width: 16px;
+}
+
+.x-btn-icon .x-btn-medium .x-btn-text{
+    height: 24px;
+	width: 24px;
+}
+
+.x-btn-icon .x-btn-large .x-btn-text{
+    height: 32px;
+	width: 32px;
+}
+
+/* Icons and text */
+/* left */
+.x-btn-text-icon .x-btn-icon-small-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:18px;
+    height:16px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:26px;
+    height:24px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-left .x-btn-text{
+    background-position: 0 center;
+	background-repeat: no-repeat;
+    padding-left:34px;
+    height:32px;
+}
+
+/* top */
+.x-btn-text-icon .x-btn-icon-small-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:18px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:26px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-top .x-btn-text{
+    background-position: center 0;
+	background-repeat: no-repeat;
+    padding-top:34px;
+}
+
+/* right */
+.x-btn-text-icon .x-btn-icon-small-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:18px;
+    height:16px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:26px;
+    height:24px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-right .x-btn-text{
+    background-position: right center;
+	background-repeat: no-repeat;
+    padding-right:34px;
+    height:32px;
+}
+
+/* bottom */
+.x-btn-text-icon .x-btn-icon-small-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:18px;
+}
+
+.x-btn-text-icon .x-btn-icon-medium-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:26px;
+}
+
+.x-btn-text-icon .x-btn-icon-large-bottom .x-btn-text{
+    background-position: center bottom;
+	background-repeat: no-repeat;
+    padding-bottom:34px;
+}
+
+/* background positioning */
+.x-btn-tr i, .x-btn-tl i, .x-btn-mr i, .x-btn-ml i, .x-btn-br i, .x-btn-bl i{
+	font-size:1px;
+    line-height:1px;
+    width:3px;
+    display:block;
+    overflow:hidden;
+}
+
+.x-btn-tr i, .x-btn-tl i, .x-btn-br i, .x-btn-bl i{
+	height:3px;
+}
+
+.x-btn-tl{
+	width:3px;
+	height:3px;
+	background:no-repeat 0 0;
+}
+.x-btn-tr{
+	width:3px;
+	height:3px;
+	background:no-repeat -3px 0;
+}
+.x-btn-tc{
+	height:3px;
+	background:repeat-x 0 -6px;
+}
+
+.x-btn-ml{
+	width:3px;
+	background:no-repeat 0 -24px;
+}
+.x-btn-mr{
+	width:3px;
+	background:no-repeat -3px -24px;
+}
+
+.x-btn-mc{
+	background:repeat-x 0 -1096px;
+    vertical-align: middle;
+	text-align:center;
+	padding:0 5px;
+	cursor:pointer;
+	white-space:nowrap;
+}
+
+/* Fixes an issue with the button height */
+.ext-strict .ext-ie6 .x-btn-mc, .ext-strict .ext-ie7 .x-btn-mc {
+    height: 100%;
+}
+
+.x-btn-bl{
+	width:3px;
+	height:3px;
+	background:no-repeat 0 -3px;
+}
+
+.x-btn-br{
+	width:3px;
+	height:3px;
+	background:no-repeat -3px -3px;
+}
+
+.x-btn-bc{
+	height:3px;
+	background:repeat-x 0 -15px;
+}
+
+.x-btn-over .x-btn-tl{
+	background-position: -6px 0;
+}
+
+.x-btn-over .x-btn-tr{
+	background-position: -9px 0;
+}
+
+.x-btn-over .x-btn-tc{
+	background-position: 0 -9px;
+}
+
+.x-btn-over .x-btn-ml{
+	background-position: -6px -24px;
+}
+
+.x-btn-over .x-btn-mr{
+	background-position: -9px -24px;
+}
+
+.x-btn-over .x-btn-mc{
+	background-position: 0 -2168px;
+}
+
+.x-btn-over .x-btn-bl{
+	background-position: -6px -3px;
+}
+
+.x-btn-over .x-btn-br{
+	background-position: -9px -3px;
+}
+
+.x-btn-over .x-btn-bc{
+	background-position: 0 -18px;
+}
+
+.x-btn-click .x-btn-tl, .x-btn-menu-active .x-btn-tl, .x-btn-pressed .x-btn-tl{
+	background-position: -12px 0;
+}
+
+.x-btn-click .x-btn-tr, .x-btn-menu-active .x-btn-tr, .x-btn-pressed .x-btn-tr{
+	background-position: -15px 0;
+}
+
+.x-btn-click .x-btn-tc, .x-btn-menu-active .x-btn-tc, .x-btn-pressed .x-btn-tc{
+	background-position: 0 -12px;
+}
+
+.x-btn-click .x-btn-ml, .x-btn-menu-active .x-btn-ml, .x-btn-pressed .x-btn-ml{
+	background-position: -12px -24px;
+}
+
+.x-btn-click .x-btn-mr, .x-btn-menu-active .x-btn-mr, .x-btn-pressed .x-btn-mr{
+	background-position: -15px -24px;
+}
+
+.x-btn-click .x-btn-mc, .x-btn-menu-active .x-btn-mc, .x-btn-pressed .x-btn-mc{
+	background-position: 0 -3240px;
+}
+
+.x-btn-click .x-btn-bl, .x-btn-menu-active .x-btn-bl, .x-btn-pressed .x-btn-bl{
+	background-position: -12px -3px;
+}
+
+.x-btn-click .x-btn-br, .x-btn-menu-active .x-btn-br, .x-btn-pressed .x-btn-br{
+	background-position: -15px -3px;
+}
+
+.x-btn-click .x-btn-bc, .x-btn-menu-active .x-btn-bc, .x-btn-pressed .x-btn-bc{
+	background-position: 0 -21px;
+}
+
+.x-btn-disabled *{
+	cursor:default !important;
+}
+
+
+/* With a menu arrow */
+/* right */
+.x-btn-mc em.x-btn-arrow {
+    display:block;
+    background:transparent no-repeat right center;
+	padding-right:10px;
+}
+
+.x-btn-mc em.x-btn-split {
+    display:block;
+    background:transparent no-repeat right center;
+	padding-right:14px;
+}
+
+/* bottom */
+.x-btn-mc em.x-btn-arrow-bottom {
+    display:block;
+    background:transparent no-repeat center bottom;
+	padding-bottom:14px;
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    display:block;
+    background:transparent no-repeat center bottom;
+	padding-bottom:14px;
+}
+
+/* height adjustment class */
+.x-btn-as-arrow .x-btn-mc em {
+    display:block;
+    background-color:transparent;
+	padding-bottom:14px;
+}
+
+/* groups */
+.x-btn-group {
+    padding:1px;
+}
+
+.x-btn-group-header {
+    padding:2px;
+    text-align:center;
+}
+
+.x-btn-group-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+}
+
+.x-btn-group-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-tr {
+	background: transparent no-repeat right 0;
+	zoom:1;
+    padding-right:3px;
+}
+
+.x-btn-group-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-btn-group-bc .x-panel-footer {
+    zoom:1;
+}
+
+.x-btn-group-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-br {
+	background: transparent no-repeat right bottom;
+	padding-right:3px;
+    zoom:1;
+}
+
+.x-btn-group-mc {
+    border:0 none;
+    padding:1px 0 0 0;
+    margin:0;
+}
+
+.x-btn-group-mc .x-btn-group-body {
+    background-color:transparent;
+    border: 0 none;
+}
+
+.x-btn-group-ml {
+	background: transparent repeat-y 0 0;
+	padding-left:3px;
+    zoom:1;
+}
+
+.x-btn-group-mr {
+	background: transparent repeat-y right 0;
+	padding-right:3px;
+    zoom:1;
+}
+
+.x-btn-group-bc .x-btn-group-footer {
+    padding-bottom:6px;
+}
+
+.x-panel-nofooter .x-btn-group-bc {
+	height:3px;
+    font-size:0;
+    line-height:0;
+}
+
+.x-btn-group-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-btn-group-body {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+    height:2px;
+}.x-toolbar{
+    border-style:solid;
+    border-width:0 0 1px 0;
+    display: block;
+	padding:2px;
+    background:repeat-x top left;
+    position:relative;
+    left:0;
+    top:0;
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-toolbar-left {
+    width: 100%;
+}
+
+.x-toolbar .x-item-disabled .x-btn-icon {
+    opacity: .35;
+    -moz-opacity: .35;
+    filter: alpha(opacity=35);
+}
+
+.x-toolbar td {
+	vertical-align:middle;
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+	white-space: nowrap;
+}
+
+.x-toolbar .x-item-disabled {
+	cursor:default;
+	opacity:.6;
+	-moz-opacity:.6;
+	filter:alpha(opacity=60);
+}
+
+.x-toolbar .x-item-disabled * {
+	cursor:default;
+}
+
+.x-toolbar .x-toolbar-cell {
+    vertical-align:middle;
+}
+
+.x-toolbar .x-btn-tl, .x-toolbar .x-btn-tr, .x-toolbar .x-btn-tc, .x-toolbar .x-btn-ml, .x-toolbar .x-btn-mr,
+.x-toolbar .x-btn-mc, .x-toolbar .x-btn-bl, .x-toolbar .x-btn-br, .x-toolbar .x-btn-bc
+{
+	background-position: 500px 500px;
+}
+
+/* These rules are duplicated from button.css to give priority of x-toolbar rules above */
+.x-toolbar .x-btn-over .x-btn-tl{
+	background-position: -6px 0;
+}
+
+.x-toolbar .x-btn-over .x-btn-tr{
+	background-position: -9px 0;
+}
+
+.x-toolbar .x-btn-over .x-btn-tc{
+	background-position: 0 -9px;
+}
+
+.x-toolbar .x-btn-over .x-btn-ml{
+	background-position: -6px -24px;
+}
+
+.x-toolbar .x-btn-over .x-btn-mr{
+	background-position: -9px -24px;
+}
+
+.x-toolbar .x-btn-over .x-btn-mc{
+	background-position: 0 -2168px;
+}
+
+.x-toolbar .x-btn-over .x-btn-bl{
+	background-position: -6px -3px;
+}
+
+.x-toolbar .x-btn-over .x-btn-br{
+	background-position: -9px -3px;
+}
+
+.x-toolbar .x-btn-over .x-btn-bc{
+	background-position: 0 -18px;
+}
+
+.x-toolbar .x-btn-click .x-btn-tl, .x-toolbar .x-btn-menu-active .x-btn-tl, .x-toolbar .x-btn-pressed .x-btn-tl{
+	background-position: -12px 0;
+}
+
+.x-toolbar .x-btn-click .x-btn-tr, .x-toolbar .x-btn-menu-active .x-btn-tr, .x-toolbar .x-btn-pressed .x-btn-tr{
+	background-position: -15px 0;
+}
+
+.x-toolbar .x-btn-click .x-btn-tc, .x-toolbar .x-btn-menu-active .x-btn-tc, .x-toolbar .x-btn-pressed .x-btn-tc{
+	background-position: 0 -12px;
+}
+
+.x-toolbar .x-btn-click .x-btn-ml, .x-toolbar .x-btn-menu-active .x-btn-ml, .x-toolbar .x-btn-pressed .x-btn-ml{
+	background-position: -12px -24px;
+}
+
+.x-toolbar .x-btn-click .x-btn-mr, .x-toolbar .x-btn-menu-active .x-btn-mr, .x-toolbar .x-btn-pressed .x-btn-mr{
+	background-position: -15px -24px;
+}
+
+.x-toolbar .x-btn-click .x-btn-mc, .x-toolbar .x-btn-menu-active .x-btn-mc, .x-toolbar .x-btn-pressed .x-btn-mc{
+	background-position: 0 -3240px;
+}
+
+.x-toolbar .x-btn-click .x-btn-bl, .x-toolbar .x-btn-menu-active .x-btn-bl, .x-toolbar .x-btn-pressed .x-btn-bl{
+	background-position: -12px -3px;
+}
+
+.x-toolbar .x-btn-click .x-btn-br, .x-toolbar .x-btn-menu-active .x-btn-br, .x-toolbar .x-btn-pressed .x-btn-br{
+	background-position: -15px -3px;
+}
+
+.x-toolbar .x-btn-click .x-btn-bc, .x-toolbar .x-btn-menu-active .x-btn-bc, .x-toolbar .x-btn-pressed .x-btn-bc{
+	background-position: 0 -21px;
+}
+
+.x-toolbar div.xtb-text{
+    padding:2px 2px 0;
+    line-height:16px;
+    display:block;
+}
+
+.x-toolbar .xtb-sep {
+	background-position: center;
+	background-repeat: no-repeat;
+	display: block;
+	font-size: 1px;
+	height: 16px;
+	width:4px;
+	overflow: hidden;
+	cursor:default;
+	margin: 0 2px 0;
+	border:0;
+}
+
+.x-toolbar .xtb-spacer {
+    width:2px;
+}
+
+/* Paging Toolbar */
+.x-tbar-page-number{
+	width:30px;
+	height:14px;
+}
+
+.ext-ie .x-tbar-page-number{
+    margin-top: 2px;
+}
+
+.x-paging-info {
+    position:absolute;
+    top:5px;
+    right: 8px;
+}
+
+/* floating */
+.x-toolbar-ct {
+    width:100%;
+}
+
+.x-toolbar-right td {
+    text-align: center;
+}
+
+.x-panel-tbar, .x-panel-bbar, .x-window-tbar, .x-window-bbar, .x-tab-panel-tbar, .x-tab-panel-bbar, .x-plain-tbar, .x-plain-bbar {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-toolbar-more .x-btn-small .x-btn-text{
+	height: 16px;
+	width: 12px;
+}
+
+.x-toolbar-more em.x-btn-arrow {
+    display:inline;
+    background-color:transparent;
+	padding-right:0;
+}
+
+.x-toolbar-more .x-btn-mc em.x-btn-arrow {
+    background-image: none;
+}
+
+div.x-toolbar-no-items {
+    color:gray !important;
+    padding:5px 10px !important;
+}
+
+/* fix ie toolbar form items */
+.ext-border-box .x-toolbar-cell .x-form-text {
+    margin-bottom:-1px !important;
+}
+
+.ext-border-box .x-toolbar-cell .x-form-field-wrap .x-form-text {
+    margin:0 !important;
+}
+
+.ext-ie .x-toolbar-cell .x-form-field-wrap {
+    height:21px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-text {
+    position:relative;
+    top:-1px;
+}
+
+.ext-strict .ext-ie8 .x-toolbar-cell .x-form-field-trigger-wrap .x-form-text, .ext-strict .ext-ie .x-toolbar-cell .x-form-text {
+    top: 0px;
+}
+
+.x-toolbar-right td .x-form-field-trigger-wrap{
+    text-align: left;
+}
+
+.x-toolbar-cell .x-form-checkbox, .x-toolbar-cell .x-form-radio{
+    margin-top: 5px;
+}
+
+.x-toolbar-cell .x-form-cb-label{
+    vertical-align: bottom;
+    top: 1px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-checkbox, .ext-ie .x-toolbar-cell .x-form-radio{
+    margin-top: 4px;
+}
+
+.ext-ie .x-toolbar-cell .x-form-cb-label{
+    top: 0;
+}
+/* Grid3 styles */
+.x-grid3 {
+	position:relative;
+	overflow:hidden;
+}
+
+.x-grid-panel .x-panel-body {
+    overflow:hidden !important;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border:1px solid;
+}
+
+.x-grid3 table {
+    table-layout:fixed;
+}
+
+.x-grid3-viewport{
+	overflow:hidden;
+}
+
+.x-grid3-hd-row td, .x-grid3-row td, .x-grid3-summary-row td{
+    -moz-outline: none;
+    outline: none;
+	-moz-user-focus: normal;
+}
+
+.x-grid3-row td, .x-grid3-summary-row td {
+    line-height:13px;
+    vertical-align: top;
+	padding-left:1px;
+    padding-right:1px;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-cell{
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-hd-row td {
+    line-height:15px;
+    vertical-align:middle;
+    border-left:1px solid;
+    border-right:1px solid;
+}
+
+.x-grid3-hd-row .x-grid3-marker-hd {
+    padding:3px;
+}
+
+.x-grid3-row .x-grid3-marker {
+    padding:3px;
+}
+
+.x-grid3-cell-inner, .x-grid3-hd-inner{
+	overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    padding:3px 3px 3px 5px;
+    white-space: nowrap;
+}
+
+/* ActionColumn, reduce padding to accommodate 16x16 icons in normal row height */
+.x-action-col-cell .x-grid3-cell-inner {
+    padding-top: 1px;
+    padding-bottom: 1px;
+}
+
+.x-action-col-icon {
+    cursor: pointer;
+}
+
+.x-grid3-hd-inner {
+    position:relative;
+	cursor:inherit;
+	padding:4px 3px 4px 5px;
+}
+
+.x-grid3-row-body {
+    white-space:normal;
+}
+
+.x-grid3-body-cell {
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+/* IE Quirks to clip */
+.ext-ie .x-grid3-cell-inner, .ext-ie .x-grid3-hd-inner{
+	width:100%;
+}
+
+/* reverse above in strict mode */
+.ext-strict .x-grid3-cell-inner, .ext-strict .x-grid3-hd-inner{
+	width:auto;
+}
+
+.x-grid-row-loading {
+    background: no-repeat center center;
+}
+
+.x-grid-page {
+    overflow:hidden;
+}
+
+.x-grid3-row {
+	cursor: default;
+    border: 1px solid;
+    width:100%;
+}
+
+.x-grid3-row-over {
+	border:1px solid;
+    background: repeat-x left top;
+}
+
+.x-grid3-resize-proxy {
+	width:1px;
+    left:0;
+	cursor: e-resize;
+	cursor: col-resize;
+	position:absolute;
+	top:0;
+	height:100px;
+	overflow:hidden;
+	visibility:hidden;
+	border:0 none;
+	z-index:7;
+}
+
+.x-grid3-resize-marker {
+	width:1px;
+	left:0;
+	position:absolute;
+	top:0;
+	height:100px;
+	overflow:hidden;
+	visibility:hidden;
+	border:0 none;
+	z-index:7;
+}
+
+.x-grid3-focus {
+	position:absolute;
+	left:0;
+	top:0;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: text;
+    -khtml-user-select: text;
+    -webkit-user-select:ignore;
+}
+
+/* header styles */
+.x-grid3-header{
+	background: repeat-x 0 bottom;
+	cursor:default;
+    zoom:1;
+    padding:1px 0 0 0;
+}
+
+.x-grid3-header-pop {
+    border-left:1px solid;
+    float:right;
+    clear:none;
+}
+
+.x-grid3-header-pop-inner {
+    border-left:1px solid;
+    width:14px;
+    height:19px;
+    background: transparent no-repeat center center;
+}
+
+.ext-ie .x-grid3-header-pop-inner {
+    width:15px;
+}
+
+.ext-strict .x-grid3-header-pop-inner {
+    width:14px; 
+}
+
+.x-grid3-header-inner {
+    overflow:hidden;
+    zoom:1;
+    float:left;
+}
+
+.x-grid3-header-offset {
+    padding-left:1px;
+    text-align: left;
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left:1px solid;
+    border-right:1px solid;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background: repeat-x left bottom;
+
+}
+
+.x-grid3-sort-icon{
+	background-repeat: no-repeat;
+	display: none;
+	height: 4px;
+	width: 13px;
+	margin-left:3px;
+	vertical-align: middle;
+}
+
+.sort-asc .x-grid3-sort-icon, .sort-desc .x-grid3-sort-icon {
+	display: inline;
+}
+
+/* Header position fixes for IE strict mode */
+.ext-strict .ext-ie .x-grid3-header-inner, .ext-strict .ext-ie6 .x-grid3-hd {
+    position:relative;
+}
+
+.ext-strict .ext-ie6 .x-grid3-hd-inner{
+    position:static;
+}
+
+/* Body Styles */
+.x-grid3-body {
+	zoom:1;
+}
+
+.x-grid3-scroller {
+	overflow:auto;
+    zoom:1;
+    position:relative;
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	display: block;
+	padding: 3px 5px 3px 5px;
+	-moz-user-select: none;
+	-khtml-user-select: none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-split {
+	background-position: center;
+	background-repeat: no-repeat;
+	cursor: e-resize;
+	cursor: col-resize;
+	display: block;
+	font-size: 1px;
+	height: 16px;
+	overflow: hidden;
+	position: absolute;
+	top: 2px;
+	width: 6px;
+	z-index: 3;
+}
+
+/* Column Reorder DD */
+.x-dd-drag-proxy .x-grid3-hd-inner{
+	background: repeat-x left bottom;
+	width:120px;
+	padding:3px;
+	border:1px solid;
+	overflow:hidden;
+}
+
+.col-move-top, .col-move-bottom{
+	width:9px;
+	height:9px;
+	position:absolute;
+	top:0;
+	line-height:1px;
+	font-size:1px;
+	overflow:hidden;
+	visibility:hidden;
+	z-index:20000;
+    background:transparent no-repeat left top;
+}
+
+/* Selection Styles */
+.x-grid3-row-selected {
+	border:1px dotted;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background: repeat-x 0 bottom !important;
+    vertical-align:middle !important;
+    padding:0;
+    border-top:1px solid;
+    border-bottom:none !important;
+    border-right:1px solid !important;
+    text-align:center;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    padding:0 4px;
+    text-align:center;
+}
+
+/* dirty cells */
+.x-grid3-dirty-cell {
+    background: transparent no-repeat 0 0;
+}
+
+/* Grid Toolbars */
+.x-grid3-topbar, .x-grid3-bottombar{
+    overflow:hidden;
+	display:none;
+	zoom:1;
+    position:relative;
+}
+
+.x-grid3-topbar .x-toolbar{
+	border-right:0 none;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-right:0 none;
+	border-bottom:0 none;
+	border-top:1px solid;
+}
+
+/* Props Grid Styles */
+.x-props-grid .x-grid3-cell{
+	padding:1px;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background:transparent repeat-y -16px !important;
+    padding-left:12px;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    padding:1px;
+    padding-right:0;
+    border:0 none;
+    border-right:1px solid;
+}
+
+/* dd */
+.x-grid3-col-dd {
+    border:0 none;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-dd-drag-ghost .x-grid3-dd-wrap {
+    padding:1px 3px 3px 1px;
+}
+
+.x-grid3-hd {
+    -moz-user-select:none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-grid3-hd-btn {
+    display:none;
+    position:absolute;
+    width:14px;
+    background:no-repeat left center;
+    right:0;
+    top:0;
+    z-index:2;
+	cursor:pointer;
+}
+
+.x-grid3-hd-over .x-grid3-hd-btn, .x-grid3-hd-menu-open .x-grid3-hd-btn {
+    display:block;
+}
+
+a.x-grid3-hd-btn:hover {
+    background-position:-14px center;
+}
+
+/* Expanders */
+.x-grid3-body .x-grid3-td-expander {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-expander .x-grid3-cell-inner {
+    padding:0 !important;
+    height:100%;
+}
+
+.x-grid3-row-expander {
+    width:100%;
+    height:18px;
+    background-position:4px 2px;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-row-collapsed .x-grid3-row-expander {
+    background-position:4px 2px;
+}
+
+.x-grid3-row-expanded .x-grid3-row-expander {
+    background-position:-21px 2px;
+}
+
+.x-grid3-row-collapsed .x-grid3-row-body {
+    display:none !important;
+}
+
+.x-grid3-row-expanded .x-grid3-row-body {
+    display:block !important;
+}
+
+/* Checkers */
+.x-grid3-body .x-grid3-td-checker {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-checker .x-grid3-cell-inner, .x-grid3-header .x-grid3-td-checker .x-grid3-hd-inner {
+    padding:0 !important;
+    height:100%;
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    width:100%;
+    height:18px;
+    background-position:2px 2px;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-row .x-grid3-row-checker {
+    background-position:2px 2px;
+}
+
+.x-grid3-row-selected .x-grid3-row-checker, .x-grid3-hd-checker-on .x-grid3-hd-checker,.x-grid3-row-checked .x-grid3-row-checker {
+    background-position:-23px 2px;
+}
+
+.x-grid3-hd-checker {
+    background-position:2px 1px;
+}
+
+.ext-border-box .x-grid3-hd-checker {
+    background-position:2px 3px;
+}
+
+.x-grid3-hd-checker-on .x-grid3-hd-checker {
+    background-position:-23px 1px;
+}
+
+.ext-border-box .x-grid3-hd-checker-on .x-grid3-hd-checker {
+    background-position:-23px 3px;
+}
+
+/* Numberer */
+.x-grid3-body .x-grid3-td-numberer {
+    background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+    padding:3px 5px 0 0 !important;
+    text-align:right;
+}
+
+/* Row Icon */
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background:transparent repeat-y right;
+    vertical-align:top;
+    text-align:center;
+}
+
+.x-grid3-body .x-grid3-td-row-icon .x-grid3-cell-inner {
+    padding:0 !important;
+    background-position:center center;
+    background-repeat:no-repeat;
+    width:16px;
+    height:16px;
+    margin-left:2px;
+    margin-top:3px;
+}
+
+/* All specials */
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background:transparent repeat-y right;
+}
+
+.x-grid3-body .x-grid3-check-col-td .x-grid3-cell-inner {
+    padding: 1px 0 0 0 !important;
+}
+
+.x-grid3-check-col {
+    width:100%;
+    height:16px;
+    background-position:center center;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+.x-grid3-check-col-on {
+    width:100%;
+    height:16px;
+    background-position:center center;
+    background-repeat:no-repeat;
+    background-color:transparent;
+}
+
+/* Grouping classes */
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom: 2px solid;
+    cursor:pointer;
+    padding-top:6px;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background:transparent no-repeat 3px 3px;
+    padding:4px 4px 4px 17px;
+}
+
+.x-grid-group-collapsed .x-grid-group-body {
+    display:none;
+}
+
+.ext-ie6 .x-grid3 .x-editor .x-form-text, .ext-ie7 .x-grid3 .x-editor .x-form-text {
+    position:relative;
+    top:-1px;
+}
+
+.ext-ie .x-props-grid .x-editor .x-form-text {
+    position:static;
+    top:0;
+}
+
+.x-grid-empty {
+    padding:10px;
+}
+
+/* fix floating toolbar issue */
+.ext-ie7 .x-grid-panel .x-panel-bbar {
+    position:relative;
+}
+
+
+/* Reset position to static when Grid Panel has been framed */
+/* to resolve 'snapping' from top to bottom behavior. */
+/* @forumThread 86656 */
+.ext-ie7 .x-grid-panel .x-panel-mc .x-panel-bbar {
+    position: static;
+}
+
+.ext-ie6 .x-grid3-header {
+    position: relative;
+}
+
+/* Fix WebKit bug in Grids */
+.ext-webkit .x-grid-panel .x-panel-bwrap{
+    -webkit-user-select:none;
+}
+.ext-webkit .x-tbar-page-number{
+    -webkit-user-select:ignore;
+}
+/* end*/
+
+/* column lines */
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    padding-right:0;
+    border-right:1px solid;
+}
+.x-pivotgrid .x-grid3-header-offset table {
+    width: 100%;
+    border-collapse: collapse;
+}
+
+.x-pivotgrid .x-grid3-header-offset table td {
+    padding: 4px 3px 4px 5px;
+    text-align: center;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    font-size: 11px;
+    line-height: 13px;
+    font-family: tahoma;
+}
+
+.x-pivotgrid .x-grid3-row-headers {
+    display: block;
+    float: left;
+}
+
+.x-pivotgrid .x-grid3-row-headers table {
+    height: 100%;
+    width: 100%;
+    border-collapse: collapse;
+}
+
+.x-pivotgrid .x-grid3-row-headers table td {
+    height: 18px;
+    padding: 2px 7px 0 0;
+    text-align: right;
+    text-overflow: ellipsis;
+    font-size: 11px;
+    font-family: tahoma;
+}
+
+.ext-gecko .x-pivotgrid .x-grid3-row-headers table td {
+    height: 21px;
+}
+
+.x-grid3-header-title {
+    top: 0%;
+    left: 0%;
+    position: absolute;
+    text-align: center;
+    vertical-align: middle;
+    font-family: tahoma;
+    font-size: 11px;
+    padding: auto 1px;
+    display: table-cell;
+}
+
+.x-grid3-header-title span {
+    position: absolute;
+    top: 50%;
+    left: 0%;
+    width: 100%;
+    margin-top: -6px;
+}.x-dd-drag-proxy{
+	position:absolute;
+	left:0;
+    top:0;
+	visibility:hidden;
+	z-index:15000;
+}
+
+.x-dd-drag-ghost{
+	-moz-opacity: 0.85;
+    opacity:.85;
+    filter: alpha(opacity=85);
+    border: 1px solid;
+	padding:3px;
+	padding-left:20px;
+	white-space:nowrap;
+}
+
+.x-dd-drag-repair .x-dd-drag-ghost{
+	-moz-opacity: 0.4;
+    opacity:.4;
+    filter: alpha(opacity=40);
+	border:0 none;
+	padding:0;
+	background-color:transparent;
+}
+
+.x-dd-drag-repair .x-dd-drop-icon{
+	visibility:hidden;
+}
+
+.x-dd-drop-icon{
+    position:absolute;
+	top:3px;
+	left:3px;
+	display:block;
+	width:16px;
+	height:16px;
+	background-color:transparent;
+	background-position: center;
+	background-repeat: no-repeat;
+	z-index:1;
+}
+
+.x-view-selector {
+    position:absolute;
+    left:0;
+    top:0;
+    width:0;
+    border:1px dotted;
+	opacity: .5;
+    -moz-opacity: .5;
+    filter:alpha(opacity=50);
+    zoom:1;
+}.ext-strict .ext-ie .x-tree .x-panel-bwrap{
+    position:relative;
+    overflow:hidden;
+}
+
+.x-tree-icon, .x-tree-ec-icon, .x-tree-elbow-line, .x-tree-elbow, .x-tree-elbow-end, .x-tree-elbow-plus, .x-tree-elbow-minus, .x-tree-elbow-end-plus, .x-tree-elbow-end-minus{
+	border: 0 none;
+	height: 18px;
+	margin: 0;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+    background-repeat: no-repeat;
+}
+
+.x-tree-node-collapsed .x-tree-node-icon, .x-tree-node-expanded .x-tree-node-icon, .x-tree-node-leaf .x-tree-node-icon{
+	border: 0 none;
+	height: 18px;
+	margin: 0;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+	background-position:center;
+    background-repeat: no-repeat;
+}
+
+.ext-ie .x-tree-node-indent img, .ext-ie .x-tree-node-icon, .ext-ie .x-tree-ec-icon {
+    vertical-align: middle !important;
+}
+
+.ext-strict .ext-ie8 .x-tree-node-indent img, .ext-strict .ext-ie8 .x-tree-node-icon, .ext-strict .ext-ie8 .x-tree-ec-icon {
+    vertical-align: top !important;
+}
+
+/* checkboxes */
+
+input.x-tree-node-cb {
+    margin-left:1px;
+    height: 19px;
+	vertical-align: bottom;
+}
+
+.ext-ie input.x-tree-node-cb {
+    margin-left:0;
+    margin-top: 1px;
+    width: 16px;
+    height: 16px;
+    vertical-align: middle;
+}
+
+.ext-strict .ext-ie8 input.x-tree-node-cb{
+    margin: 1px 1px;
+    height: 14px;
+    vertical-align: bottom;
+}
+
+.ext-strict .ext-ie8 input.x-tree-node-cb + a{
+    vertical-align: bottom;
+}
+
+.ext-opera input.x-tree-node-cb {
+    height: 14px;
+    vertical-align: middle;
+}
+
+.x-tree-noicon .x-tree-node-icon{
+	width:0; height:0;
+}
+
+/* No line styles */
+.x-tree-no-lines .x-tree-elbow{
+	background-color:transparent;
+}
+
+.x-tree-no-lines .x-tree-elbow-end{
+	background-color:transparent;
+}
+
+.x-tree-no-lines .x-tree-elbow-line{
+	background-color:transparent;
+}
+
+/* Arrows */
+.x-tree-arrows .x-tree-elbow{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background:transparent no-repeat 0 0;
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background:transparent no-repeat -16px 0;
+}
+
+.x-tree-arrows .x-tree-elbow-end{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background:transparent no-repeat 0 0;
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background:transparent no-repeat -16px 0;
+}
+
+.x-tree-arrows .x-tree-elbow-line{
+	background-color:transparent;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-plus{
+    background-position:-32px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-minus{
+    background-position:-48px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-end-plus{
+    background-position:-32px 0;
+}
+
+.x-tree-arrows .x-tree-ec-over .x-tree-elbow-end-minus{
+    background-position:-48px 0;
+}
+
+.x-tree-elbow-plus, .x-tree-elbow-minus, .x-tree-elbow-end-plus, .x-tree-elbow-end-minus{
+	cursor:pointer;
+}
+
+.ext-ie ul.x-tree-node-ct{
+    font-size:0;
+    line-height:0;
+    zoom:1;
+}
+
+.x-tree-node{
+	white-space: nowrap;
+}
+
+.x-tree-node-el {
+    line-height:18px;
+    cursor:pointer;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	text-decoration:none;
+	-khtml-user-select:none;
+	-moz-user-select:none;
+    -webkit-user-select:ignore;
+    -kthml-user-focus:normal;
+    -moz-user-focus:normal;
+    -moz-outline: 0 none;
+    outline:0 none;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	text-decoration:none;
+	padding:1px 3px 1px 2px;
+}
+
+.x-tree-node .x-tree-node-disabled .x-tree-node-icon{
+	-moz-opacity: 0.5;
+   opacity:.5;
+   filter: alpha(opacity=50);
+}
+
+.x-tree-node .x-tree-node-inline-icon{
+	background-color:transparent;
+}
+
+.x-tree-node a:hover, .x-dd-drag-ghost a:hover{
+	text-decoration:none;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom:1px dotted;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top:1px dotted;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom:0 none;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above{
+	 border-top:0 none;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom:2px solid;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top:2px solid;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 border:1px dotted;
+}
+
+.x-dd-drag-ghost .x-tree-node-indent, .x-dd-drag-ghost .x-tree-ec-icon{
+	display:none !important;
+}
+
+/* Fix for ie rootVisible:false issue */
+.x-tree-root-ct {
+    zoom:1;
+}
+.x-date-picker {
+    border: 1px solid;
+    border-top:0 none;
+	position:relative;
+}
+
+.x-date-picker a {
+    -moz-outline:0 none;
+    outline:0 none;
+}
+
+.x-date-inner, .x-date-inner td, .x-date-inner th{
+    border-collapse:separate;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background: repeat-x 0 -83px;
+	overflow:hidden;
+}
+
+.x-date-middle .x-btn-tc,.x-date-middle .x-btn-tl,.x-date-middle .x-btn-tr,
+.x-date-middle .x-btn-mc,.x-date-middle .x-btn-ml,.x-date-middle .x-btn-mr,
+.x-date-middle .x-btn-bc,.x-date-middle .x-btn-bl,.x-date-middle .x-btn-br{
+	background:transparent !important;
+    vertical-align:middle;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background:transparent no-repeat right 0;
+}
+
+.x-date-right, .x-date-left {
+    width:18px;
+}
+
+.x-date-right{
+    text-align:right;
+}
+
+.x-date-middle {
+    padding-top:2px;
+    padding-bottom:2px;
+    width:130px; /* FF3 */
+}
+
+.x-date-right a, .x-date-left a{
+    display:block;
+    width:16px;
+	height:16px;
+	background-position: center;
+	background-repeat: no-repeat;
+	cursor:pointer;
+    -moz-opacity: 0.6;
+    opacity:.6;
+    filter: alpha(opacity=60);
+}
+
+.x-date-right a:hover, .x-date-left a:hover{
+    -moz-opacity: 1;
+    opacity:1;
+    filter: alpha(opacity=100);
+}
+
+.x-item-disabled .x-date-right a:hover, .x-item-disabled .x-date-left a:hover{
+    -moz-opacity: 0.6;
+    opacity:.6;
+    filter: alpha(opacity=60);
+}
+
+.x-date-right a {
+    margin-right:2px;
+    text-decoration:none !important;
+}
+
+.x-date-left a{
+    margin-left:2px;
+    text-decoration:none !important;
+}
+
+table.x-date-inner {
+    width: 100%;
+    table-layout:fixed;
+}
+
+.ext-webkit table.x-date-inner{
+    /* Fix for webkit browsers */
+    width: 175px;
+}
+
+
+.x-date-inner th {
+    width:25px;
+}
+
+.x-date-inner th {
+    background: repeat-x left top;
+    text-align:right !important;
+	border-bottom: 1px solid;
+	cursor:default;
+    padding:0;
+    border-collapse:separate;
+}
+
+.x-date-inner th span {
+    display:block;
+    padding:2px;
+    padding-right:7px;
+}
+
+.x-date-inner td {
+    border: 1px solid;
+	text-align:right;
+    padding:0;
+}
+
+.x-date-inner a {
+    padding:2px 5px;
+    display:block;
+	text-decoration:none;
+    text-align:right;
+    zoom:1;
+}
+
+.x-date-inner .x-date-active{
+	cursor:pointer;
+	color:black;
+}
+
+.x-date-inner .x-date-selected a{
+	background: repeat-x left top;
+	border:1px solid;
+    padding:1px 4px;
+}
+
+.x-date-inner .x-date-today a{
+	border: 1px solid;
+    padding:1px 4px;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+    text-decoration:none !important;
+}
+
+.x-date-bottom {
+    padding:4px;
+    border-top: 1px solid;
+    background: repeat-x left top;
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    text-decoration:none !important;
+}
+
+.x-item-disabled .x-date-inner a:hover{
+    background: none;
+}
+
+.x-date-inner .x-date-disabled a {
+	cursor:default;
+}
+
+.x-date-menu .x-menu-item {
+	padding:1px 24px 1px 4px;
+	white-space: nowrap;
+}
+
+.x-date-menu .x-menu-item .x-menu-item-icon {
+    width:10px;
+    height:10px;
+    margin-right:5px;
+    background-position:center -4px !important;
+}
+
+.x-date-mp {
+	position:absolute;
+	left:0;
+	top:0;
+	display:none;
+}
+
+.x-date-mp td {
+    padding:2px;
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+td.x-date-mp-month,td.x-date-mp-year,td.x-date-mp-ybtn {
+    border: 0 none;
+	text-align:center;
+	vertical-align: middle;
+	width:25%;
+}
+
+.x-date-mp-ok {
+	margin-right:3px;
+}
+
+.x-date-mp-btns button {
+	text-decoration:none;
+	text-align:center;
+	text-decoration:none !important;
+	border:1px solid;
+	padding:1px 3px 1px;
+	cursor:pointer;
+}
+
+.x-date-mp-btns {
+	background: repeat-x left top;
+}
+
+.x-date-mp-btns td {
+	border-top: 1px solid;
+    text-align:center;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	display:block;
+	padding:2px 4px;
+	text-decoration:none;
+	text-align:center;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	text-decoration:none;
+	cursor:pointer;
+}
+
+td.x-date-mp-sel a {
+	padding:1px 3px;
+	background: repeat-x left top;
+	border:1px solid;
+}
+
+.x-date-mp-ybtn a {
+    overflow:hidden;
+    width:15px;
+    height:15px;
+    cursor:pointer;
+    background:transparent no-repeat;
+    display:block;
+    margin:0 auto;
+}
+
+.x-date-mp-ybtn a.x-date-mp-next {
+    background-position:0 -120px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-next:hover {
+    background-position:-15px -120px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-prev {
+    background-position:0 -105px;
+}
+
+.x-date-mp-ybtn a.x-date-mp-prev:hover {
+    background-position:-15px -105px;
+}
+
+.x-date-mp-ybtn {
+   text-align:center;
+}
+
+td.x-date-mp-sep {
+   border-right:1px solid;
+}.x-tip{
+	position: absolute;
+	top: 0;
+    left:0;
+    visibility: hidden;
+	z-index: 20002;
+    border:0 none;
+}
+
+.x-tip .x-tip-close{
+	height: 15px;
+	float:right;
+	width: 15px;
+    margin:0 0 2px 2px;
+    cursor:pointer;
+    display:none;
+}
+
+.x-tip .x-tip-tc {
+	background: transparent no-repeat 0 -62px;
+	padding-top:3px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-tr {
+	background: transparent no-repeat right 0;
+	padding-right:6px;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tip .x-tip-bc {
+	background: transparent no-repeat 0 -121px;
+	height:3px;
+    overflow:hidden;
+}
+
+.x-tip .x-tip-bl {
+	background: transparent no-repeat 0 -59px;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-br {
+	background: transparent no-repeat right -59px;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-mc {
+    border:0 none;
+}
+
+.x-tip .x-tip-ml {
+	background: no-repeat 0 -124px;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-tip .x-tip-mr {
+	background: transparent no-repeat right -124px;
+	padding-right:6px;
+    zoom:1;
+}
+
+.ext-ie .x-tip .x-tip-header,.ext-ie .x-tip .x-tip-tc {
+    font-size:0;
+    line-height:0;
+}
+
+.ext-border-box .x-tip .x-tip-header, .ext-border-box .x-tip .x-tip-tc{
+    line-height: 1px;
+}
+
+.x-tip .x-tip-header-text {
+    padding:0;
+    margin:0 0 2px 0;
+}
+
+.x-tip .x-tip-body {
+    margin:0 !important;
+    line-height:14px;
+    padding:0;
+}
+
+.x-tip .x-tip-body .loading-indicator {
+    margin:0;
+}
+
+.x-tip-draggable .x-tip-header,.x-tip-draggable .x-tip-header-text {
+    cursor:move;
+}
+
+.x-form-invalid-tip .x-tip-tc {
+	background: repeat-x 0 -12px;
+    padding-top:6px;
+}
+
+.x-form-invalid-tip .x-tip-bc {
+	background: repeat-x 0 -18px;
+    height:6px;
+}
+
+.x-form-invalid-tip .x-tip-bl {
+	background: no-repeat 0 -6px;
+}
+
+.x-form-invalid-tip .x-tip-br {
+	background: no-repeat right -6px;
+}
+
+.x-form-invalid-tip .x-tip-body {
+    padding:2px;
+}
+
+.x-form-invalid-tip .x-tip-body {
+    padding-left:24px;
+    background:transparent no-repeat 2px 2px;
+}
+
+.x-tip-anchor {
+    position: absolute;
+    width: 9px;
+    height: 10px;
+    overflow:hidden;
+    background: transparent no-repeat 0 0;
+    zoom:1;
+}
+.x-tip-anchor-bottom {
+    background-position: -9px 0;
+}
+.x-tip-anchor-right {
+    background-position: -18px 0;
+    width: 10px;
+}
+.x-tip-anchor-left {
+    background-position: -28px 0;
+    width: 10px;
+}.x-menu {
+	z-index: 15000;
+	zoom: 1;
+	background: repeat-y;
+}
+
+.x-menu-floating{
+    border: 1px solid;
+}
+
+.x-menu a {
+    text-decoration: none !important;
+}
+
+.ext-ie .x-menu {
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-menu-list{
+    padding: 2px;
+	background-color:transparent;
+	border:0 none;
+    overflow:hidden;
+    overflow-y: hidden;
+}
+
+.ext-strict .ext-ie .x-menu-list{
+    position: relative;
+}
+
+.x-menu li{
+	line-height:100%;
+}
+
+.x-menu li.x-menu-sep-li{
+	font-size:1px;
+	line-height:1px;
+}
+
+.x-menu-list-item{
+    white-space: nowrap;
+	display:block;
+	padding:1px;
+}
+
+.x-menu-item{
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+}
+
+.x-menu-item-arrow{
+	background:transparent no-repeat right;
+}
+
+.x-menu-sep {
+	display:block;
+	font-size:1px;
+	line-height:1px;
+	margin: 2px 3px;
+	border-bottom:1px solid;
+    overflow:hidden;
+}
+
+.x-menu-focus {
+	position:absolute;
+	left:-1px;
+	top:-1px;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+    overflow:hidden;
+    display:block;
+}
+
+a.x-menu-item {
+    cursor: pointer;
+    display: block;
+    line-height: 16px;
+    outline-color: -moz-use-text-color;
+    outline-style: none;
+    outline-width: 0;
+    padding: 3px 21px 3px 27px;
+    position: relative;
+    text-decoration: none;
+    white-space: nowrap;
+}
+
+.x-menu-item-active {
+    background-repeat: repeat-x;
+    background-position: left bottom;
+    border-style:solid;
+    border-width: 1px 0;
+    margin:0 1px;
+	padding: 0;
+}
+
+.x-menu-item-active a.x-menu-item {
+    border-style:solid;
+    border-width:0 1px;
+    margin:0 -1px;
+}
+
+.x-menu-item-icon {
+	border: 0 none;
+	height: 16px;
+	padding: 0;
+	vertical-align: top;
+	width: 16px;
+	position: absolute;
+    left: 3px;
+    top: 3px;
+    margin: 0;
+    background-position:center;
+}
+
+.ext-ie .x-menu-item-icon {
+    left: -24px;
+}
+.ext-strict .x-menu-item-icon {
+    left: 3px;
+}
+
+.ext-ie6 .x-menu-item-icon {
+    left: -24px;
+}
+
+.ext-ie .x-menu-item-icon {
+    vertical-align: middle;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background: transparent no-repeat center;
+}
+
+.x-menu-group-item .x-menu-item-icon{
+	background-color: transparent;
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background: transparent no-repeat center;
+}
+
+.x-date-menu .x-menu-list{
+    padding: 0;
+}
+
+.x-menu-date-item{
+	padding:0;
+}
+
+.x-menu .x-color-palette, .x-menu .x-date-picker{
+    margin-left: 26px;
+	margin-right:4px;
+}
+
+.x-menu .x-date-picker{
+    border:1px solid;
+    margin-top:2px;
+    margin-bottom:2px;
+}
+
+.x-menu-plain .x-color-palette, .x-menu-plain .x-date-picker{
+	 margin: 0;
+	 border: 0 none;
+}
+
+.x-date-menu {
+   padding:0 !important;
+}
+
+/*
+ * fixes separator visibility problem in IE 6
+ */
+.ext-strict .ext-ie6 .x-menu-sep-li {
+    padding: 3px 4px;
+}
+.ext-strict .ext-ie6 .x-menu-sep {
+    margin: 0;
+    height: 1px;
+}
+
+/*
+ * Fixes an issue with "fat" separators in webkit
+ */
+.ext-webkit .x-menu-sep{
+    height: 1px;
+}
+
+/*
+ * Ugly mess to remove the white border under the picker
+ */
+.ext-ie .x-date-menu{
+    height: 199px;
+}
+
+.ext-strict .ext-ie .x-date-menu, .ext-border-box .ext-ie8 .x-date-menu{
+    height: 197px;
+}
+
+.ext-strict .ext-ie7 .x-date-menu{
+    height: 195px;
+}
+
+.ext-strict .ext-ie8 .x-date-menu{
+    height: auto;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border:1px dotted !important;
+	padding:0;
+}
+
+.x-menu .x-menu-scroller {
+    width: 100%;
+	background-repeat:no-repeat;
+	background-position:center;
+	height:8px;
+    line-height: 8px;
+	cursor:pointer;
+    margin: 0;
+    padding: 0;
+}
+
+.x-menu .x-menu-scroller-active{
+    height: 6px;
+    line-height: 6px;
+}
+
+.x-menu-list-item-indent{
+    padding-left: 27px;
+}/*
+ Creates rounded, raised boxes like on the Ext website - the markup isn't pretty:
+  <div class="x-box-blue">
+        <div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>
+        <div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc">
+            <h3>YOUR TITLE HERE (optional)</h3>
+            <div>YOUR CONTENT HERE</div>
+        </div></div></div>
+        <div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>
+    </div>
+ */
+
+.x-box-tl {
+	background: transparent no-repeat 0 0;
+    zoom:1;
+}
+
+.x-box-tc {
+	height: 8px;
+	background: transparent repeat-x 0 0;
+	overflow: hidden;
+}
+
+.x-box-tr {
+	background: transparent no-repeat right -8px;
+}
+
+.x-box-ml {
+	background: transparent repeat-y 0;
+	padding-left: 4px;
+	overflow: hidden;
+    zoom:1;
+}
+
+.x-box-mc {
+	background: repeat-x 0 -16px;
+	padding: 4px 10px;
+}
+
+.x-box-mc h3 {
+	margin: 0 0 4px 0;
+    zoom:1;
+}
+
+.x-box-mr {
+	background: transparent repeat-y right;
+	padding-right: 4px;
+	overflow: hidden;
+}
+
+.x-box-bl {
+	background: transparent no-repeat 0 -16px;
+    zoom:1;
+}
+
+.x-box-bc {
+	background: transparent repeat-x 0 -8px;
+	height: 8px;
+	overflow: hidden;
+}
+
+.x-box-br {
+	background: transparent no-repeat right -24px;
+}
+
+.x-box-tl, .x-box-bl {
+	padding-left: 8px;
+	overflow: hidden;
+}
+
+.x-box-tr, .x-box-br {
+	padding-right: 8px;
+	overflow: hidden;
+}.x-combo-list {
+    border:1px solid;
+    zoom:1;
+    overflow:hidden;
+}
+
+.x-combo-list-inner {
+    overflow:auto;
+    position:relative; /* for calculating scroll offsets */
+    zoom:1;
+    overflow-x:hidden;
+}
+
+.x-combo-list-hd {
+    border-bottom:1px solid;
+    padding:3px;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom:1px solid;
+}
+
+.x-combo-list-item {
+    padding:2px;
+    border:1px solid;
+    white-space: nowrap;
+    overflow:hidden;
+    text-overflow: ellipsis;
+}
+
+.x-combo-list .x-combo-selected{
+	border:1px dotted !important;
+    cursor:pointer;
+}
+
+.x-combo-list .x-toolbar {
+    border-top:1px solid;
+    border-bottom:0 none;
+}.x-panel {
+    border-style: solid;
+    border-width:0;
+}
+
+.x-panel-header {
+    overflow:hidden;
+    zoom:1;
+    padding:5px 3px 4px 5px;
+    border:1px solid;
+    line-height: 15px;
+    background: transparent repeat-x 0 -1px;
+}
+
+.x-panel-body {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    position: relative; /* added for item scroll positioning */
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border:1px solid;
+    border-top:0 none;
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top:1px solid;
+    border-bottom: 0 none;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top:1px solid;
+}
+
+.x-panel-header {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-panel-tl .x-panel-header {
+    padding:5px 0 4px 0;
+    border:0 none;
+    background:transparent no-repeat;
+}
+
+.x-panel-tl .x-panel-icon, .x-window-tl .x-panel-icon {
+    padding-left:20px !important;
+    background-repeat:no-repeat;
+    background-position:0 4px;
+    zoom:1;
+}
+
+.x-panel-inline-icon {
+    width:16px;
+	height:16px;
+    background-repeat:no-repeat;
+    background-position:0 0;
+	vertical-align:middle;
+	margin-right:4px;
+	margin-top:-1px;
+	margin-bottom:-1px;
+}
+
+.x-panel-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+}
+
+/* fix ie7 strict mode bug */
+.ext-strict .ext-ie7 .x-panel-tc {
+    overflow: visible;
+}
+
+.x-panel-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    zoom:1;
+    border-bottom:1px solid;
+}
+
+.x-panel-tr {
+	background: transparent no-repeat right 0;
+	zoom:1;
+    padding-right:6px;
+}
+
+.x-panel-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-panel-bc .x-panel-footer {
+    zoom:1;
+}
+
+.x-panel-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-panel-br {
+	background: transparent no-repeat right bottom;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-panel-mc {
+    border:0 none;
+    padding:0;
+    margin:0;
+    padding-top:6px;
+}
+
+.x-panel-mc .x-panel-body {
+    background-color:transparent;
+    border: 0 none;
+}
+
+.x-panel-ml {
+	background: repeat-y 0 0;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-panel-mr {
+	background: transparent repeat-y right 0;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-panel-bc .x-panel-footer {
+    padding-bottom:6px;
+}
+
+.x-panel-nofooter .x-panel-bc, .x-panel-nofooter .x-window-bc {
+	height:6px;
+    font-size:0;
+    line-height:0;
+}
+
+.x-panel-bwrap {
+    overflow:hidden;
+    zoom:1;
+    left:0;
+    top:0;
+}
+.x-panel-body {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-panel-collapsed .x-resizable-handle{
+    display:none;
+}
+
+.ext-gecko .x-panel-animated div {
+    overflow:hidden !important;
+}
+
+/* Plain */
+.x-plain-body {
+    overflow:hidden;
+}
+
+.x-plain-bbar .x-toolbar {
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-plain-tbar .x-toolbar {
+    overflow:hidden;
+    padding:2px;
+}
+
+.x-plain-bwrap {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-plain {
+    overflow:hidden;
+}
+
+/* Tools */
+.x-tool {
+    overflow:hidden;
+    width:15px;
+    height:15px;
+    float:right;
+    cursor:pointer;
+    background:transparent no-repeat;
+    margin-left:2px;
+}
+
+/* expand / collapse tools */
+.x-tool-toggle {
+    background-position:0 -60px;
+}
+
+.x-tool-toggle-over {
+    background-position:-15px -60px;
+}
+
+.x-panel-collapsed .x-tool-toggle {
+    background-position:0 -75px;
+}
+
+.x-panel-collapsed .x-tool-toggle-over {
+    background-position:-15px -75px;
+}
+
+
+.x-tool-close {
+    background-position:0 -0;
+}
+
+.x-tool-close-over {
+    background-position:-15px 0;
+}
+
+.x-tool-minimize {
+    background-position:0 -15px;
+}
+
+.x-tool-minimize-over {
+    background-position:-15px -15px;
+}
+
+.x-tool-maximize {
+    background-position:0 -30px;
+}
+
+.x-tool-maximize-over {
+    background-position:-15px -30px;
+}
+
+.x-tool-restore {
+    background-position:0 -45px;
+}
+
+.x-tool-restore-over {
+    background-position:-15px -45px;
+}
+
+.x-tool-gear {
+    background-position:0 -90px;
+}
+
+.x-tool-gear-over {
+    background-position:-15px -90px;
+}
+
+.x-tool-prev {
+    background-position:0 -105px;
+}
+
+.x-tool-prev-over {
+    background-position:-15px -105px;
+}
+
+.x-tool-next {
+    background-position:0 -120px;
+}
+
+.x-tool-next-over {
+    background-position:-15px -120px;
+}
+
+.x-tool-pin {
+    background-position:0 -135px;
+}
+
+.x-tool-pin-over {
+    background-position:-15px -135px;
+}
+
+.x-tool-unpin {
+    background-position:0 -150px;
+}
+
+.x-tool-unpin-over {
+    background-position:-15px -150px;
+}
+
+.x-tool-right {
+    background-position:0 -165px;
+}
+
+.x-tool-right-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-left {
+    background-position:0 -180px;
+}
+
+.x-tool-left-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-down {
+    background-position:0 -195px;
+}
+
+.x-tool-down-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-up {
+    background-position:0 -210px;
+}
+
+.x-tool-up-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-refresh {
+    background-position:0 -225px;
+}
+
+.x-tool-refresh-over {
+    background-position:-15px -225px;
+}
+
+.x-tool-plus {
+    background-position:0 -240px;
+}
+
+.x-tool-plus-over {
+    background-position:-15px -240px;
+}
+
+.x-tool-minus {
+    background-position:0 -255px;
+}
+
+.x-tool-minus-over {
+    background-position:-15px -255px;
+}
+
+.x-tool-search {
+    background-position:0 -270px;
+}
+
+.x-tool-search-over {
+    background-position:-15px -270px;
+}
+
+.x-tool-save {
+    background-position:0 -285px;
+}
+
+.x-tool-save-over {
+    background-position:-15px -285px;
+}
+
+.x-tool-help {
+    background-position:0 -300px;
+}
+
+.x-tool-help-over {
+    background-position:-15px -300px;
+}
+
+.x-tool-print {
+    background-position:0 -315px;
+}
+
+.x-tool-print-over {
+    background-position:-15px -315px;
+}
+
+.x-tool-expand {
+    background-position:0 -330px;
+}
+
+.x-tool-expand-over {
+    background-position:-15px -330px;
+}
+
+.x-tool-collapse {
+    background-position:0 -345px;
+}
+
+.x-tool-collapse-over {
+    background-position:-15px -345px;
+}
+
+.x-tool-resize {
+    background-position:0 -360px;
+}
+
+.x-tool-resize-over {
+    background-position:-15px -360px;
+}
+
+.x-tool-move {
+    background-position:0 -375px;
+}
+
+.x-tool-move-over {
+    background-position:-15px -375px;
+}
+
+/* Ghosting */
+.x-panel-ghost {
+    z-index:12000;
+    overflow:hidden;
+    position:absolute;
+    left:0;top:0;
+    opacity:.65;
+    -moz-opacity:.65;
+    filter:alpha(opacity=65);
+}
+
+.x-panel-ghost ul {
+    margin:0;
+    padding:0;
+    overflow:hidden;
+    font-size:0;
+    line-height:0;
+    border:1px solid;
+    border-top:0 none;
+    display:block;
+}
+
+.x-panel-ghost * {
+    cursor:move !important;
+}
+
+.x-panel-dd-spacer {
+    border:2px dashed;
+}
+
+/* Buttons */
+.x-panel-btns {
+    padding:5px;
+    overflow:hidden;
+}
+
+.x-panel-btns td.x-toolbar-cell{
+	padding:3px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-left{
+	background-position:0 -147px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-right{
+	background-position:0 -168px;
+}
+
+.x-panel-btns .x-btn-focus .x-btn-center{
+	background-position:0 -189px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-left{
+	background-position:0 -63px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-right{
+	background-position:0 -84px;
+}
+
+.x-panel-btns .x-btn-over .x-btn-center{
+	background-position:0 -105px;
+}
+
+.x-panel-btns .x-btn-click .x-btn-center{
+	background-position:0 -126px;
+}
+
+.x-panel-btns .x-btn-click  .x-btn-right{
+	background-position:0 -84px;
+}
+
+.x-panel-btns .x-btn-click .x-btn-left{
+	background-position:0 -63px;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+	white-space: nowrap;
+}
+/**
+ * W3C Suggested Default style sheet for HTML 4
+ * http://www.w3.org/TR/CSS21/sample.html
+ *
+ * Resets for Ext.Panel @cfg normal: true
+ */
+.x-panel-reset .x-panel-body html,
+.x-panel-reset .x-panel-body address,
+.x-panel-reset .x-panel-body blockquote,
+.x-panel-reset .x-panel-body body,
+.x-panel-reset .x-panel-body dd,
+.x-panel-reset .x-panel-body div,
+.x-panel-reset .x-panel-body dl,
+.x-panel-reset .x-panel-body dt,
+.x-panel-reset .x-panel-body fieldset,
+.x-panel-reset .x-panel-body form,
+.x-panel-reset .x-panel-body frame, frameset,
+.x-panel-reset .x-panel-body h1,
+.x-panel-reset .x-panel-body h2,
+.x-panel-reset .x-panel-body h3,
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body h5,
+.x-panel-reset .x-panel-body h6,
+.x-panel-reset .x-panel-body noframes,
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body p,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body center,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body hr,
+.x-panel-reset .x-panel-body menu,
+.x-panel-reset .x-panel-body pre 			  { display: block }
+.x-panel-reset .x-panel-body li              { display: list-item }
+.x-panel-reset .x-panel-body head            { display: none }
+.x-panel-reset .x-panel-body table           { display: table }
+.x-panel-reset .x-panel-body tr              { display: table-row }
+.x-panel-reset .x-panel-body thead           { display: table-header-group }
+.x-panel-reset .x-panel-body tbody           { display: table-row-group }
+.x-panel-reset .x-panel-body tfoot           { display: table-footer-group }
+.x-panel-reset .x-panel-body col             { display: table-column }
+.x-panel-reset .x-panel-body colgroup        { display: table-column-group }
+.x-panel-reset .x-panel-body td,
+.x-panel-reset .x-panel-body th 	          { display: table-cell }
+.x-panel-reset .x-panel-body caption         { display: table-caption }
+.x-panel-reset .x-panel-body th              { font-weight: bolder; text-align: center }
+.x-panel-reset .x-panel-body caption         { text-align: center }
+.x-panel-reset .x-panel-body body            { margin: 8px }
+.x-panel-reset .x-panel-body h1              { font-size: 2em; margin: .67em 0 }
+.x-panel-reset .x-panel-body h2              { font-size: 1.5em; margin: .75em 0 }
+.x-panel-reset .x-panel-body h3              { font-size: 1.17em; margin: .83em 0 }
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body p,
+.x-panel-reset .x-panel-body blockquote,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body fieldset,
+.x-panel-reset .x-panel-body form,
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body dl,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body menu            { margin: 1.12em 0 }
+.x-panel-reset .x-panel-body h5              { font-size: .83em; margin: 1.5em 0 }
+.x-panel-reset .x-panel-body h6              { font-size: .75em; margin: 1.67em 0 }
+.x-panel-reset .x-panel-body h1,
+.x-panel-reset .x-panel-body h2,
+.x-panel-reset .x-panel-body h3,
+.x-panel-reset .x-panel-body h4,
+.x-panel-reset .x-panel-body h5,
+.x-panel-reset .x-panel-body h6,
+.x-panel-reset .x-panel-body b,
+.x-panel-reset .x-panel-body strong          { font-weight: bolder }
+.x-panel-reset .x-panel-body blockquote      { margin-left: 40px; margin-right: 40px }
+.x-panel-reset .x-panel-body i,
+.x-panel-reset .x-panel-body cite,
+.x-panel-reset .x-panel-body em,
+.x-panel-reset .x-panel-body var,
+.x-panel-reset .x-panel-body address    	  { font-style: italic }
+.x-panel-reset .x-panel-body pre,
+.x-panel-reset .x-panel-body tt,
+.x-panel-reset .x-panel-body code,
+.x-panel-reset .x-panel-body kbd,
+.x-panel-reset .x-panel-body samp       	  { font-family: monospace }
+.x-panel-reset .x-panel-body pre             { white-space: pre }
+.x-panel-reset .x-panel-body button,
+.x-panel-reset .x-panel-body textarea,
+.x-panel-reset .x-panel-body input,
+.x-panel-reset .x-panel-body select   		  { display: inline-block }
+.x-panel-reset .x-panel-body big             { font-size: 1.17em }
+.x-panel-reset .x-panel-body small,
+.x-panel-reset .x-panel-body sub,
+.x-panel-reset .x-panel-body sup 			  { font-size: .83em }
+.x-panel-reset .x-panel-body sub             { vertical-align: sub }
+.x-panel-reset .x-panel-body sup             { vertical-align: super }
+.x-panel-reset .x-panel-body table           { border-spacing: 2px; }
+.x-panel-reset .x-panel-body thead,
+.x-panel-reset .x-panel-body tbody,
+.x-panel-reset .x-panel-body tfoot           { vertical-align: middle }
+.x-panel-reset .x-panel-body td,
+.x-panel-reset .x-panel-body th          	  { vertical-align: inherit }
+.x-panel-reset .x-panel-body s,
+.x-panel-reset .x-panel-body strike,
+.x-panel-reset .x-panel-body del  			  { text-decoration: line-through }
+.x-panel-reset .x-panel-body hr              { border: 1px inset }
+.x-panel-reset .x-panel-body ol,
+.x-panel-reset .x-panel-body ul,
+.x-panel-reset .x-panel-body dir,
+.x-panel-reset .x-panel-body menu,
+.x-panel-reset .x-panel-body dd        	  { margin-left: 40px }
+.x-panel-reset .x-panel-body ul, .x-panel-reset .x-panel-body menu, .x-panel-reset .x-panel-body dir { list-style-type: disc;}
+.x-panel-reset .x-panel-body ol              { list-style-type: decimal }
+.x-panel-reset .x-panel-body ol ul,
+.x-panel-reset .x-panel-body ul ol,
+.x-panel-reset .x-panel-body ul ul,
+.x-panel-reset .x-panel-body ol ol    		  { margin-top: 0; margin-bottom: 0 }
+.x-panel-reset .x-panel-body u,
+.x-panel-reset .x-panel-body ins          	  { text-decoration: underline }
+.x-panel-reset .x-panel-body br:before       { content: "\A" }
+.x-panel-reset .x-panel-body :before, .x-panel-reset .x-panel-body :after { white-space: pre-line }
+.x-panel-reset .x-panel-body center          { text-align: center }
+.x-panel-reset .x-panel-body :link, .x-panel-reset .x-panel-body :visited { text-decoration: underline }
+.x-panel-reset .x-panel-body :focus          { outline: invert dotted thin }
+
+/* Begin bidirectionality settings (do not change) */
+.x-panel-reset .x-panel-body BDO[DIR="ltr"]  { direction: ltr; unicode-bidi: bidi-override }
+.x-panel-reset .x-panel-body BDO[DIR="rtl"]  { direction: rtl; unicode-bidi: bidi-override }
+.x-window {
+    zoom:1;
+}
+
+.x-window .x-window-handle {
+    opacity:0;
+    -moz-opacity:0;
+    filter:alpha(opacity=0);
+}
+
+.x-window-proxy {
+    border:1px solid;
+    z-index:12000;
+    overflow:hidden;
+    position:absolute;
+    left:0;top:0;
+    display:none;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+}
+
+.x-window-header {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-window-bwrap {
+    z-index:1;
+    position:relative;
+    zoom:1;
+    left:0;top:0;
+}
+
+.x-window-tl .x-window-header {
+    padding:5px 0 4px 0;
+}
+
+.x-window-header-text {
+    cursor:pointer;
+}
+
+.x-window-tc {
+	background: transparent repeat-x 0 0;
+	overflow:hidden;
+    zoom:1;
+}
+
+.x-window-tl {
+	background: transparent no-repeat 0 0;
+	padding-left:6px;
+    zoom:1;
+    z-index:1;
+    position:relative;
+}
+
+.x-window-tr {
+	background: transparent no-repeat right 0;
+	padding-right:6px;
+}
+
+.x-window-bc {
+	background: transparent repeat-x 0 bottom;
+    zoom:1;
+}
+
+.x-window-bc .x-window-footer {
+    padding-bottom:6px;
+    zoom:1;
+    font-size:0;
+    line-height:0;
+}
+
+.x-window-bl {
+	background: transparent no-repeat 0 bottom;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-window-br {
+	background: transparent no-repeat right bottom;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-window-mc {
+    border:1px solid;
+    padding:0;
+    margin:0;
+}
+
+.x-window-ml {
+	background: transparent repeat-y 0 0;
+	padding-left:6px;
+    zoom:1;
+}
+
+.x-window-mr {
+	background: transparent repeat-y right 0;
+	padding-right:6px;
+    zoom:1;
+}
+
+.x-window-body {
+    overflow:hidden;
+}
+
+.x-window-bwrap {
+    overflow:hidden;
+}
+
+.x-window-maximized .x-window-bl, .x-window-maximized .x-window-br,
+    .x-window-maximized .x-window-ml, .x-window-maximized .x-window-mr,
+    .x-window-maximized .x-window-tl, .x-window-maximized .x-window-tr {
+    padding:0;
+}
+
+.x-window-maximized .x-window-footer {
+    padding-bottom:0;
+}
+
+.x-window-maximized .x-window-tc {
+    padding-left:3px;
+    padding-right:3px;
+}
+
+.x-window-maximized .x-window-mc {
+    border-left:0 none;
+    border-right:0 none;
+}
+
+.x-window-tbar .x-toolbar, .x-window-bbar .x-toolbar {
+    border-left:0 none;
+    border-right: 0 none;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top:1px solid;
+    border-bottom:0 none;
+}
+
+.x-window-draggable, .x-window-draggable .x-window-header-text {
+    cursor:move;
+}
+
+.x-window-maximized .x-window-draggable, .x-window-maximized .x-window-draggable .x-window-header-text {
+    cursor:default;
+}
+
+.x-window-body {
+    background-color:transparent;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom:1px solid;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom:1px solid;
+}
+
+.x-window-maximized-ct {
+    overflow:hidden;
+}
+
+.x-window-maximized .x-window-handle {
+    display:none;
+}
+
+.x-window-sizing-ghost ul {
+    border:0 none !important;
+}
+
+.x-dlg-focus{
+	-moz-outline:0 none;
+	outline:0 none;
+	width:0;
+	height:0;
+	overflow:hidden;
+	position:absolute;
+	top:0;
+	left:0;
+}
+
+.ext-webkit .x-dlg-focus{
+    width: 1px;
+    height: 1px;
+}
+
+.x-dlg-mask{
+    z-index:10000;
+    display:none;
+    position:absolute;
+    top:0;
+    left:0;
+    -moz-opacity: 0.5;
+    opacity:.50;
+    filter: alpha(opacity=50);
+}
+
+body.ext-ie6.x-body-masked select {
+	visibility:hidden;
+}
+
+body.ext-ie6.x-body-masked .x-window select {
+	visibility:visible;
+}
+
+.x-window-plain .x-window-mc {
+    border: 1px solid;
+}
+
+.x-window-plain .x-window-body {
+    border: 1px solid;
+    background:transparent !important;
+}.x-html-editor-wrap {
+    border:1px solid;
+}
+
+.x-html-editor-tb .x-btn-text {
+    background:transparent no-repeat;
+}
+
+.x-html-editor-tb .x-edit-bold, .x-menu-item img.x-edit-bold {
+    background-position:0 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);    
+}
+
+.x-html-editor-tb .x-edit-italic, .x-menu-item img.x-edit-italic {
+    background-position:-16px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-underline, .x-menu-item img.x-edit-underline {
+    background-position:-32px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-forecolor, .x-menu-item img.x-edit-forecolor {
+    background-position:-160px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-backcolor, .x-menu-item img.x-edit-backcolor {
+    background-position:-176px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifyleft, .x-menu-item img.x-edit-justifyleft {
+    background-position:-112px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifycenter, .x-menu-item img.x-edit-justifycenter {
+    background-position:-128px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-justifyright, .x-menu-item img.x-edit-justifyright {
+    background-position:-144px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-insertorderedlist, .x-menu-item img.x-edit-insertorderedlist {
+    background-position:-80px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-insertunorderedlist, .x-menu-item img.x-edit-insertunorderedlist {
+    background-position:-96px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-increasefontsize, .x-menu-item img.x-edit-increasefontsize {
+    background-position:-48px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-decreasefontsize, .x-menu-item img.x-edit-decreasefontsize {
+    background-position:-64px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-sourceedit, .x-menu-item img.x-edit-sourceedit {
+    background-position:-192px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tb .x-edit-createlink, .x-menu-item img.x-edit-createlink {
+    background-position:-208px 0;
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}
+
+.x-html-editor-tip .x-tip-bd .x-tip-bd-inner {
+    padding:5px;
+    padding-bottom:1px;
+}
+
+.x-html-editor-tb .x-toolbar {
+    position:static !important;
+}.x-panel-noborder .x-panel-body-noborder {
+    border-width:0;
+}
+
+.x-panel-noborder .x-panel-header-noborder {
+    border-width:0 0 1px;
+    border-style:solid;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-width:0 0 1px;
+    border-style:solid;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-width:1px 0 0 0;
+    border-style:solid;
+}
+
+.x-window-noborder .x-window-mc {
+    border-width:0;
+}
+
+.x-window-plain .x-window-body-noborder {
+    border-width:0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-body-noborder {
+	border-width:0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-header-noborder {
+    border-width: 0 0 1px 0;
+}
+
+.x-tab-panel-noborder .x-tab-panel-footer-noborder {
+    border-width: 1px 0 0 0;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-width: 1px 0 0 0;
+    border-style:solid;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-width:0 0 1px;
+    border-style:solid;
+}.x-border-layout-ct {
+    position: relative;
+}
+
+.x-border-panel {
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.x-tool-collapse-south {
+    background-position:0 -195px;
+}
+
+.x-tool-collapse-south-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-collapse-north {
+    background-position:0 -210px;
+}
+
+.x-tool-collapse-north-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-collapse-west {
+    background-position:0 -180px;
+}
+
+.x-tool-collapse-west-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-collapse-east {
+    background-position:0 -165px;
+}
+
+.x-tool-collapse-east-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-expand-south {
+    background-position:0 -210px;
+}
+
+.x-tool-expand-south-over {
+    background-position:-15px -210px;
+}
+
+.x-tool-expand-north {
+    background-position:0 -195px;
+}
+.x-tool-expand-north-over {
+    background-position:-15px -195px;
+}
+
+.x-tool-expand-west {
+    background-position:0 -165px;
+}
+
+.x-tool-expand-west-over {
+    background-position:-15px -165px;
+}
+
+.x-tool-expand-east {
+    background-position:0 -180px;
+}
+
+.x-tool-expand-east-over {
+    background-position:-15px -180px;
+}
+
+.x-tool-expand-north, .x-tool-expand-south {
+    float:right;
+    margin:3px;
+}
+
+.x-tool-expand-east, .x-tool-expand-west {
+    float:none;
+    margin:3px 2px;
+}
+
+.x-accordion-hd .x-tool-toggle {
+    background-position:0 -255px;
+}
+
+.x-accordion-hd .x-tool-toggle-over {
+    background-position:-15px -255px;
+}
+
+.x-panel-collapsed .x-accordion-hd .x-tool-toggle {
+    background-position:0 -240px;
+}
+
+.x-panel-collapsed .x-accordion-hd .x-tool-toggle-over {
+    background-position:-15px -240px;
+}
+
+.x-accordion-hd {
+	padding-top:4px;
+	padding-bottom:3px;
+	border-top:0 none;
+    background: transparent repeat-x 0 -9px;
+}
+
+.x-layout-collapsed{
+    position:absolute;
+    left:-10000px;
+    top:-10000px;
+    visibility:hidden;
+    width:20px;
+    height:20px;
+    overflow:hidden;
+	border:1px solid;
+	z-index:20;
+}
+
+.ext-border-box .x-layout-collapsed{
+    width:22px;
+    height:22px;
+}
+
+.x-layout-collapsed-over{
+    cursor:pointer;
+}
+
+.x-layout-collapsed-west .x-layout-collapsed-tools, .x-layout-collapsed-east .x-layout-collapsed-tools{
+	position:absolute;
+    top:0;
+    left:0;
+    width:20px;
+    height:20px;
+}
+
+
+.x-layout-split{
+    position:absolute;
+    height:5px;
+    width:5px;
+    line-height:1px;
+    font-size:1px;
+    z-index:3;
+    background-color:transparent;
+}
+
+/* IE6 strict won't drag w/out a color */
+.ext-strict .ext-ie6 .x-layout-split{
+    background-color: #fff !important;
+    filter: alpha(opacity=1);
+}
+
+.x-layout-split-h{
+    background-image:url(../images/default/s.gif);
+    background-position: left;
+}
+
+.x-layout-split-v{
+    background-image:url(../images/default/s.gif);
+    background-position: top;
+}
+
+.x-column-layout-ct {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-column {
+    float:left;
+    padding:0;
+    margin:0;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-column-inner {
+    overflow:hidden;
+    zoom:1;
+}
+
+/* mini mode */
+.x-layout-mini {
+    position:absolute;
+    top:0;
+    left:0;
+    display:block;
+    width:5px;
+    height:35px;
+    cursor:pointer;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+}
+
+.x-layout-mini-over, .x-layout-collapsed-over .x-layout-mini{
+    opacity:1;
+    -moz-opacity:1;
+    filter:none;
+}
+
+.x-layout-split-west .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-split-east .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-split-north .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-split-south .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    top:48%;
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    left:48%;
+    height:5px;
+    width:35px;
+}
+
+.x-layout-cmini-west, .x-layout-cmini-east {
+    border:0 none;
+    width:5px !important;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-layout-cmini-north, .x-layout-cmini-south {
+    border:0 none;
+    height:5px !important;
+    padding:0;
+    background-color:transparent;
+}
+
+.x-viewport, .x-viewport body {
+    margin: 0;
+    padding: 0;
+    border: 0 none;
+    overflow: hidden;
+    height: 100%;
+}
+
+.x-abs-layout-item {
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.ext-ie input.x-abs-layout-item, .ext-ie textarea.x-abs-layout-item {
+    margin:0;
+}
+
+.x-box-layout-ct {
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-box-inner {
+    overflow:hidden;
+    zoom:1;
+    position:relative;
+    left:0;
+    top:0;
+}
+
+.x-box-item {
+    position:absolute;
+    left:0;
+    top:0;
+}.x-progress-wrap {
+    border:1px solid;
+    overflow:hidden;
+}
+
+.x-progress-inner {
+    height:18px;
+    background:repeat-x;
+    position:relative;
+}
+
+.x-progress-bar {
+    height:18px;
+    float:left;
+    width:0;
+    background: repeat-x left center;
+    border-top:1px solid;
+    border-bottom:1px solid;
+    border-right:1px solid;
+}
+
+.x-progress-text {
+    padding:1px 5px;
+    overflow:hidden;
+    position:absolute;
+    left:0;
+    text-align:center;
+}
+
+.x-progress-text-back {
+    line-height:16px;
+}
+
+.ext-ie .x-progress-text-back {
+    line-height:15px;
+}
+
+.ext-strict .ext-ie7 .x-progress-text-back{
+    width: 100%;
+}
+.x-list-header{
+	background: repeat-x 0 bottom;
+	cursor:default;
+    zoom:1;
+    height:22px;
+}
+
+.x-list-header-inner div {
+    display:block;
+    float:left;
+    overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.x-list-header-inner div em {
+    display:block;
+    border-left:1px solid;
+    padding:4px 4px;
+    overflow:hidden;
+    -moz-user-select: none;
+    -khtml-user-select: none;
+    line-height:14px;
+}
+
+.x-list-body {
+    overflow:auto;
+    overflow-x:hidden;
+    overflow-y:auto;
+    zoom:1;
+    float: left;
+    width: 100%;
+}
+
+.x-list-body dl {
+    zoom:1;
+}
+
+.x-list-body dt {
+    display:block;
+    float:left;
+    overflow:hidden;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    white-space: nowrap;
+    cursor:pointer;
+    zoom:1;
+}
+
+.x-list-body dt em {
+    display:block;
+    padding:3px 4px;
+    overflow:hidden;
+    -moz-user-select: none;
+    -khtml-user-select: none;
+}
+
+.x-list-resizer {
+    border-left:1px solid;
+    border-right:1px solid;
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.x-list-header-inner em.sort-asc {
+    background: transparent no-repeat center 0;
+    border-style:solid;
+    border-width: 0 1px 1px;
+    padding-bottom:3px;
+}
+
+.x-list-header-inner em.sort-desc {
+    background: transparent no-repeat center -23px;
+    border-style:solid;
+    border-width: 0 1px 1px;
+    padding-bottom:3px;
+}
+
+/* Shared styles */
+.x-slider {
+    zoom:1;
+}
+
+.x-slider-inner {
+    position:relative;
+    left:0;
+    top:0;
+    overflow:visible;
+    zoom:1;
+}
+
+.x-slider-focus {
+	position:absolute;
+	left:0;
+	top:0;
+	width:1px;
+	height:1px;
+    line-height:1px;
+    font-size:1px;
+    -moz-outline:0 none;
+    outline:0 none;
+    -moz-user-select: none;
+    -khtml-user-select:none;
+    -webkit-user-select:ignore;
+	display:block;
+	overflow:hidden;  
+}
+
+/* Horizontal styles */
+.x-slider-horz {
+    padding-left:7px;
+    background:transparent no-repeat 0 -22px;
+}
+
+.x-slider-horz .x-slider-end {
+    padding-right:7px;
+    zoom:1;
+    background:transparent no-repeat right -44px;
+}
+
+.x-slider-horz .x-slider-inner {
+    background:transparent repeat-x 0 0;
+    height:22px;
+}
+
+.x-slider-horz .x-slider-thumb {
+    width:14px;
+    height:15px;
+    position:absolute;
+    left:0;
+    top:3px;
+    background:transparent no-repeat 0 0;
+}
+
+.x-slider-horz .x-slider-thumb-over {
+    background-position: -14px -15px;
+}
+
+.x-slider-horz .x-slider-thumb-drag {
+    background-position: -28px -30px;
+}
+
+/* Vertical styles */
+.x-slider-vert {
+    padding-top:7px;
+    background:transparent no-repeat -44px 0;
+    width:22px;
+}
+
+.x-slider-vert .x-slider-end {
+    padding-bottom:7px;
+    zoom:1;
+    background:transparent no-repeat -22px bottom;
+}
+
+.x-slider-vert .x-slider-inner {
+    background:transparent repeat-y 0 0;
+}
+
+.x-slider-vert .x-slider-thumb {
+    width:15px;
+    height:14px;
+    position:absolute;
+    left:3px;
+    bottom:0;
+    background:transparent no-repeat 0 0;
+}
+
+.x-slider-vert .x-slider-thumb-over {
+    background-position: -15px -14px;
+}
+
+.x-slider-vert .x-slider-thumb-drag {
+    background-position: -30px -28px;
+}.x-window-dlg .x-window-body {
+    border:0 none !important;
+    padding:5px 10px;
+    overflow:hidden !important;
+}
+
+.x-window-dlg .x-window-mc {
+    border:0 none !important;
+}
+
+.x-window-dlg .ext-mb-input {
+    margin-top:4px;
+    width:95%;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    margin-top:4px;
+}
+
+.x-window-dlg .x-progress-wrap {
+    margin-top:4px;
+}
+
+.ext-ie .x-window-dlg .x-progress-wrap {
+    margin-top:6px;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background:transparent no-repeat left;
+    display:block;
+    width:300px;
+    padding-left:18px;
+    line-height:18px;
+}
+
+.x-window-dlg .ext-mb-icon {
+    float:left;
+    width:47px;
+    height:32px;
+}
+
+.x-window-dlg .x-dlg-icon .ext-mb-content{
+    zoom: 1; 
+    margin-left: 47px;
+}
+
+.x-window-dlg .ext-mb-info, .x-window-dlg .ext-mb-warning, .x-window-dlg .ext-mb-question, .x-window-dlg .ext-mb-error {
+    background:transparent no-repeat top left;
+}
+
+.ext-gecko2 .ext-mb-fix-cursor {
+    overflow:auto;
+}.ext-el-mask {
+    background-color: #ccc;
+}
+
+.ext-el-mask-msg {
+    border-color:#6593cf;
+    background-color:#c3daf9;
+    background-image:url(../images/default/box/tb-blue.gif);
+}
+.ext-el-mask-msg div {
+    background-color: #eee;
+    border-color:#a3bad9;
+    color:#222;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-mask-loading div {
+    background-color:#fbfbfb;
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-item-disabled {
+    color: gray;
+}
+
+.x-item-disabled * {
+    color: gray !important;
+}
+
+.x-splitbar-proxy {
+    background-color: #aaa;
+}
+
+.x-color-palette a {
+    border-color:#fff;
+}
+
+.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {
+    border-color:#8bb8f3;
+    background-color: #deecfd;
+}
+
+/*
+.x-color-palette em:hover, .x-color-palette span:hover{   
+    background-color: #deecfd;
+}
+*/
+
+.x-color-palette em {
+    border-color:#aca899;
+}
+
+.x-ie-shadow {
+    background-color:#777;
+}
+
+.x-shadow .xsmc {
+    background-image: url(../images/default/shadow-c.png);
+}
+
+.x-shadow .xsml, .x-shadow .xsmr {
+    background-image: url(../images/default/shadow-lr.png);
+}
+
+.x-shadow .xstl, .x-shadow .xstc,  .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbc, .x-shadow .xsbr{
+    background-image: url(../images/default/shadow.png);
+}
+
+.loading-indicator {
+    font-size: 11px;
+    background-image: url(../images/default/grid/loading.gif);
+}
+
+.x-spotlight {
+    background-color: #ccc;
+}
+.x-tab-panel-header, .x-tab-panel-footer {
+	background-color: #deecfd;
+	border-color:#8db2e3;
+    overflow:hidden;
+    zoom:1;
+}
+
+.x-tab-panel-header, .x-tab-panel-footer {
+	border-color:#8db2e3;
+}
+
+ul.x-tab-strip-top{
+    background-color:#cedff5;
+	background-image: url(../images/default/tabs/tab-strip-bg.gif);
+	border-bottom-color:#8db2e3;
+}
+
+ul.x-tab-strip-bottom{
+    background-color:#cedff5;
+	background-image: url(../images/default/tabs/tab-strip-btm-bg.gif);
+	border-top-color:#8db2e3;
+}
+
+.x-tab-panel-header-plain .x-tab-strip-spacer,
+.x-tab-panel-footer-plain .x-tab-strip-spacer {
+    border-color:#8db2e3;
+    background-color: #deecfd;
+}
+
+.x-tab-strip span.x-tab-strip-text {
+	font:normal 11px tahoma,arial,helvetica;
+	color:#416aa3;
+}
+
+.x-tab-strip-over span.x-tab-strip-text {
+	color:#15428b;
+}
+
+.x-tab-strip-active span.x-tab-strip-text {
+	color:#15428b;
+    font-weight:bold;
+}
+
+.x-tab-strip-disabled .x-tabs-text {
+	color:#aaaaaa;
+}
+
+.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner{
+	background-image: url(../images/default/tabs/tabs-sprite.gif);
+}
+
+.x-tab-strip-bottom .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-inactive-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-inactive-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-over-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-over .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-over-left-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {
+	background-image: url(../images/default/tabs/tab-btm-right-bg.gif);
+}
+
+.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {
+	background-image: url(../images/default/tabs/tab-btm-left-bg.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {
+	background-image:url(../images/default/tabs/tab-close.gif);
+}
+
+.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{
+	background-image:url(../images/default/tabs/tab-close.gif);
+}
+
+.x-tab-panel-body {
+    border-color:#8db2e3;
+    background-color:#fff;
+}
+
+.x-tab-panel-body-top {
+    border-top: 0 none;
+}
+
+.x-tab-panel-body-bottom {
+    border-bottom: 0 none;
+}
+
+.x-tab-scroller-left {
+    background-image:url(../images/default/tabs/scroll-left.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-scroller-left-over {
+    background-position: 0 0;
+}
+
+.x-tab-scroller-left-disabled {
+    background-position: -18px 0;
+    opacity:.5;
+    -moz-opacity:.5;
+    filter:alpha(opacity=50);
+    cursor:default;
+}
+
+.x-tab-scroller-right {
+    background-image:url(../images/default/tabs/scroll-right.gif);
+    border-bottom-color:#8db2e3;
+}
+
+.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}.x-form-field {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-text, textarea.x-form-field {
+    background-color:#fff;
+    background-image:url(../images/default/form/text-bg.gif);
+    border-color:#b5b8c8;
+}
+
+.x-form-select-one {
+    background-color:#fff;
+    border-color:#b5b8c8;
+}
+
+.x-form-check-group-label {
+    border-bottom: 1px solid #99bbe8;
+    color: #15428b;
+}
+
+.x-editor .x-form-check-wrap {
+    background-color:#fff;
+}
+
+.x-form-field-wrap .x-form-trigger {
+    background-image:url(../images/default/form/trigger.gif);
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-field-wrap .x-form-date-trigger {
+    background-image: url(../images/default/form/date-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-clear-trigger {
+    background-image: url(../images/default/form/clear-trigger.gif);
+}
+
+.x-form-field-wrap .x-form-search-trigger {
+    background-image: url(../images/default/form/search-trigger.gif);
+}
+
+.x-trigger-wrap-focus .x-form-trigger {
+    border-bottom-color:#7eadd9;
+}
+
+.x-item-disabled .x-form-trigger-over {
+    border-bottom-color:#b5b8c8;
+}
+
+.x-item-disabled .x-form-trigger-click {
+    border-bottom-color:#b5b8c8;
+}
+
+.x-form-focus, textarea.x-form-focus {
+	border-color:#7eadd9;
+}
+
+.x-form-invalid, textarea.x-form-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.x-form-invalid.x-form-composite {
+    border: none;
+    background-image: none;
+}
+
+.x-form-invalid.x-form-composite .x-form-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+	border-color:#c30;
+}
+
+.x-form-inner-invalid, textarea.x-form-inner-invalid {
+    background-color:#fff;
+	background-image:url(../images/default/grid/invalid_line.gif);
+}
+
+.x-form-grow-sizer {
+	font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-item {
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-form-invalid-msg {
+    color:#c0272b;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+    background-image:url(../images/default/shared/warning.gif);
+}
+
+.x-form-empty-field {
+    color:gray;
+}
+
+.x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.ext-webkit .x-small-editor .x-form-field {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-form-invalid-icon {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-fieldset {
+    border-color:#b5b8c8;
+}
+
+.x-fieldset legend {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#15428b;
+}
+.x-btn{
+	font:normal 11px tahoma, verdana, helvetica;
+}
+
+.x-btn button{
+    font:normal 11px arial,tahoma,verdana,helvetica;
+    color:#333;
+}
+
+.x-btn em {
+    font-style:normal;
+    font-weight:normal;
+}
+
+.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc{
+	background-image:url(../images/default/button/btn.gif);
+}
+
+.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text{
+    color:#000;
+}
+
+.x-btn-disabled *{
+	color:gray !important;
+}
+
+.x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/button/arrow.gif);
+}
+
+.x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split, .x-btn-click .x-btn-mc em.x-btn-split, .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-btn-pressed .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-o.gif);
+}
+
+.x-btn-mc em.x-btn-arrow-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b.gif);
+}
+
+.x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-btn-click .x-btn-mc em.x-btn-split-bottom, .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-btn-pressed .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-bo.gif);
+}
+
+.x-btn-group-header {
+    color: #3e6aaa;
+}
+
+.x-btn-group-tc {
+	background-image: url(../images/default/button/group-tb.gif);
+}
+
+.x-btn-group-tl {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-tr {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-bc {
+	background-image: url(../images/default/button/group-tb.gif);
+}
+
+.x-btn-group-bl {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-br {
+	background-image: url(../images/default/button/group-cs.gif);
+}
+
+.x-btn-group-ml {
+	background-image: url(../images/default/button/group-lr.gif);
+}
+.x-btn-group-mr {
+	background-image: url(../images/default/button/group-lr.gif);
+}
+
+.x-btn-group-notitle .x-btn-group-tc {
+	background-image: url(../images/default/button/group-tb.gif);
+}.x-toolbar{
+	border-color:#a9bfd3;
+    background-color:#d0def0;
+    background-image:url(../images/default/toolbar/bg.gif);
+}
+
+.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+
+.x-toolbar .x-item-disabled {
+	color:gray;
+}
+
+.x-toolbar .x-item-disabled * {
+	color:gray;
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split {
+    background-image:url(../images/default/button/s-arrow-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split,
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split
+{
+    background-image:url(../images/default/button/s-arrow-o.gif);
+}
+
+.x-toolbar .x-btn-mc em.x-btn-split-bottom {
+    background-image:url(../images/default/button/s-arrow-b-noline.gif);
+}
+
+.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom,
+.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom
+{
+    background-image:url(../images/default/button/s-arrow-bo.gif);
+}
+
+.x-toolbar .xtb-sep {
+	background-image: url(../images/default/grid/grid-blue-split.gif);
+}
+
+.x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first.gif) !important;
+}
+
+.x-tbar-loading{
+	background-image: url(../images/default/grid/refresh.gif) !important;
+}
+
+.x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last.gif) !important;
+}
+
+.x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next.gif) !important;
+}
+
+.x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev.gif) !important;
+}
+
+.x-item-disabled .x-tbar-loading{
+	background-image: url(../images/default/grid/refresh-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-first{
+	background-image: url(../images/default/grid/page-first-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-last{
+	background-image: url(../images/default/grid/page-last-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-next{
+	background-image: url(../images/default/grid/page-next-disabled.gif) !important;
+}
+
+.x-item-disabled .x-tbar-page-prev{
+	background-image: url(../images/default/grid/page-prev-disabled.gif) !important;
+}
+
+.x-paging-info {
+    color:#444;
+}
+
+.x-toolbar-more-icon {
+    background-image: url(../images/default/toolbar/more.gif) !important;
+}.x-resizable-handle {
+	background-color:#fff;
+}
+
+.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west
+{
+    background-image:url(../images/default/sizer/e-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north
+{
+    background-image:url(../images/default/sizer/s-handle.gif);
+}
+
+.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north{
+    background-image:url(../images/default/sizer/s-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{
+    background-image:url(../images/default/sizer/se-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{
+    background-image:url(../images/default/sizer/nw-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{
+    background-image:url(../images/default/sizer/ne-handle.gif);
+}
+.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{
+    background-image:url(../images/default/sizer/sw-handle.gif);
+}
+.x-resizable-proxy{
+    border-color:#3b5a82;
+}
+.x-resizable-overlay{
+    background-color:#fff;
+}
+.x-grid3 {
+    background-color:#fff;
+}
+
+.x-grid-panel .x-panel-mc .x-panel-body {
+    border-color:#99bbe8;
+}
+
+.x-grid3-row td, .x-grid3-summary-row td{
+	font:normal 11px/13px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-hd-row td {
+	font:normal 11px/15px arial, tahoma, helvetica, sans-serif;
+}
+
+
+.x-grid3-hd-row td {
+    border-left-color:#eee;
+    border-right-color:#d0d0d0;
+}
+
+.x-grid-row-loading {
+    background-color: #fff;
+    background-image:url(../images/default/shared/loading-balls.gif);
+}
+
+.x-grid3-row {
+    border-color:#ededed;
+    border-top-color:#fff;
+}
+
+.x-grid3-row-alt{
+	background-color:#fafafa;
+}
+
+.x-grid3-row-over {
+	border-color:#ddd;
+    background-color:#efefef;
+    background-image:url(../images/default/grid/row-over.gif);
+}
+
+.x-grid3-resize-proxy {
+    background-color:#777;
+}
+
+.x-grid3-resize-marker {
+    background-color:#777;
+}
+
+.x-grid3-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/default/grid/grid3-hrow.gif);
+}
+
+.x-grid3-header-pop {
+    border-left-color:#d0d0d0;
+}
+
+.x-grid3-header-pop-inner {
+    border-left-color:#eee;
+    background-image:url(../images/default/grid/hd-pop.gif);
+}
+
+td.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {
+    border-left-color:#aaccf6;
+    border-right-color:#aaccf6;
+}
+
+td.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {
+    background-color:#ebf3fd;
+    background-image:url(../images/default/grid/grid3-hrow-over.gif);
+
+}
+
+.sort-asc .x-grid3-sort-icon {
+	background-image: url(../images/default/grid/sort_asc.gif);
+}
+
+.sort-desc .x-grid3-sort-icon {
+	background-image: url(../images/default/grid/sort_desc.gif);
+}
+
+.x-grid3-cell-text, .x-grid3-hd-text {
+	color:#000;
+}
+
+.x-grid3-split {
+	background-image: url(../images/default/grid/grid-split.gif);
+}
+
+.x-grid3-hd-text {
+	color:#15428b;
+}
+
+.x-dd-drag-proxy .x-grid3-hd-inner{
+    background-color:#ebf3fd;
+	background-image:url(../images/default/grid/grid3-hrow-over.gif);
+	border-color:#aaccf6;
+}
+
+.col-move-top{
+	background-image:url(../images/default/grid/col-move-top.gif);
+}
+
+.col-move-bottom{
+	background-image:url(../images/default/grid/col-move-bottom.gif);
+}
+
+td.grid-hd-group-cell {
+    background: url(../images/default/grid/grid3-hrow.gif) repeat-x bottom;
+}
+
+.x-grid3-row-selected {
+	background-color: #dfe8f6 !important;
+	background-image: none;
+	border-color:#a3bae9;
+}
+
+.x-grid3-cell-selected{
+	background-color: #b8cfee !important;
+	color:#000;
+}
+
+.x-grid3-cell-selected span{
+	color:#000 !important;
+}
+
+.x-grid3-cell-selected .x-grid3-cell-text{
+	color:#000;
+}
+
+.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{
+    background-color:#ebeadb !important;
+    background-image:url(../images/default/grid/grid-hrow.gif) !important;
+    color:#000;
+    border-top-color:#fff;
+    border-right-color:#6fa0df !important;
+}
+
+.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{
+    color:#15428b !important;
+}
+
+.x-grid3-dirty-cell {
+    background-image:url(../images/default/grid/dirty.gif);
+}
+
+.x-grid3-topbar, .x-grid3-bottombar{
+	font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-grid3-bottombar .x-toolbar{
+	border-top-color:#a9bfd3;
+}
+
+.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{
+	background-image:url(../images/default/grid/grid3-special-col-bg.gif) !important;
+    color:#000 !important;
+}
+
+.x-props-grid .x-grid3-body .x-grid3-td-name{
+    background-color:#fff !important;
+    border-right-color:#eee;
+}
+
+.xg-hmenu-sort-asc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-asc.gif);
+}
+
+.xg-hmenu-sort-desc .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-desc.gif);
+}
+
+.xg-hmenu-lock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-lock.gif);
+}
+
+.xg-hmenu-unlock .x-menu-item-icon{
+	background-image: url(../images/default/grid/hmenu-unlock.gif);
+}
+
+.x-grid3-hd-btn {
+    background-color:#c3daf9;
+    background-image:url(../images/default/grid/grid3-hd-btn.gif);
+}
+
+.x-grid3-body .x-grid3-td-expander {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-expander {
+    background-image:url(../images/default/grid/row-expand-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-checker {
+    background-image: url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-row-checker, .x-grid3-hd-checker {
+    background-image:url(../images/default/grid/row-check-sprite.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {
+	color:#444;
+}
+
+.x-grid3-body .x-grid3-td-row-icon {
+    background-image:url(../images/default/grid/grid3-special-col-bg.gif);
+}
+
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,
+.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {
+	background-image:url(../images/default/grid/grid3-special-col-sel-bg.gif);
+}
+
+.x-grid3-check-col {
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-grid3-check-col-on {
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-grid-group, .x-grid-group-body, .x-grid-group-hd {
+    zoom:1;
+}
+
+.x-grid-group-hd {
+    border-bottom-color:#99bbe8;
+}
+
+.x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/default/grid/group-collapse.gif);
+    color:#3764a0;
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title {
+    background-image:url(../images/default/grid/group-expand.gif);
+}
+
+.x-group-by-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-cols-icon {
+    background-image:url(../images/default/grid/columns.gif);
+}
+
+.x-show-groups-icon {
+    background-image:url(../images/default/grid/group-by.gif);
+}
+
+.x-grid-empty {
+    color:gray;
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {
+    border-right-color:#ededed;
+}
+
+.x-grid-with-col-lines .x-grid3-row-selected {
+	border-top-color:#a3bae9;
+}.x-pivotgrid .x-grid3-header-offset table td {
+    background: url(../images/default/grid/grid3-hrow.gif) repeat-x 50% 100%;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #EEE;
+    border-right-color: #D0D0D0;
+}
+
+.x-pivotgrid .x-grid3-row-headers {
+    background-color: #f9f9f9;
+}
+
+.x-pivotgrid .x-grid3-row-headers table td {
+    background: #EEE url(../images/default/grid/grid3-rowheader.gif) repeat-x left top;
+    border-left: 1px solid;
+    border-right: 1px solid;
+    border-left-color: #EEE;
+    border-right-color: #D0D0D0;
+    border-bottom: 1px solid;
+    border-bottom-color: #D0D0D0;
+    height: 18px;
+}
+.x-dd-drag-ghost{
+	color:#000;
+	font: normal 11px arial, helvetica, sans-serif;
+    border-color: #ddd #bbb #bbb #ddd;
+	background-color:#fff;
+}
+
+.x-dd-drop-nodrop .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-no.gif);
+}
+
+.x-dd-drop-ok .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-yes.gif);
+}
+
+.x-dd-drop-ok-add .x-dd-drop-icon{
+  background-image: url(../images/default/dd/drop-add.gif);
+}
+
+.x-view-selector {
+    background-color:#c3daf9;
+    border-color:#3399bb;
+}.x-tree-node-expanded .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder-open.gif);
+}
+
+.x-tree-node-leaf .x-tree-node-icon{
+	background-image:url(../images/default/tree/leaf.gif);
+}
+
+.x-tree-node-collapsed .x-tree-node-icon{
+	background-image:url(../images/default/tree/folder.gif);
+}
+
+.x-tree-node-loading .x-tree-node-icon{
+	background-image:url(../images/default/tree/loading.gif) !important;
+}
+
+.x-tree-node .x-tree-node-inline-icon {
+    background-image: none;
+}
+
+.x-tree-node-loading a span{
+	 font-style: italic;
+	 color:#444444;
+}
+
+.x-tree-lines .x-tree-elbow{
+	background-image:url(../images/default/tree/elbow.gif);
+}
+
+.x-tree-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end{
+	background-image:url(../images/default/tree/elbow-end.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/default/tree/elbow-end-plus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/default/tree/elbow-end-minus.gif);
+}
+
+.x-tree-lines .x-tree-elbow-line{
+	background-image:url(../images/default/tree/elbow-line.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-plus{
+	background-image:url(../images/default/tree/elbow-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-minus{
+	background-image:url(../images/default/tree/elbow-minus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-plus{
+	background-image:url(../images/default/tree/elbow-end-plus-nl.gif);
+}
+
+.x-tree-no-lines .x-tree-elbow-end-minus{
+	background-image:url(../images/default/tree/elbow-end-minus-nl.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-plus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-minus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-plus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-arrows .x-tree-elbow-end-minus{
+    background-image:url(../images/default/tree/arrows.gif);
+}
+
+.x-tree-node{
+	color:#000;
+	font: normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-tree-node a, .x-dd-drag-ghost a{
+	color:#000;
+}
+
+.x-tree-node a span, .x-dd-drag-ghost a span{
+	color:#000;
+}
+
+.x-tree-node .x-tree-node-disabled a span{
+	color:gray !important;
+}
+
+.x-tree-node div.x-tree-drag-insert-below{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-node div.x-tree-drag-insert-above{
+	 border-top-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
+ 	 border-bottom-color:#36c;
+}
+
+.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
+	 border-top-color:#36c;
+}
+
+.x-tree-node .x-tree-drag-append a span{
+	 background-color:#ddd;
+	 border-color:gray;
+}
+
+.x-tree-node .x-tree-node-over {
+	background-color: #eee;
+}
+
+.x-tree-node .x-tree-selected {
+	background-color: #d9e8fb;
+}
+
+.x-tree-drop-ok-append .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-add.gif);
+}
+
+.x-tree-drop-ok-above .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-over.gif);
+}
+
+.x-tree-drop-ok-below .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-under.gif);
+}
+
+.x-tree-drop-ok-between .x-dd-drop-icon{
+  background-image: url(../images/default/tree/drop-between.gif);
+}.x-date-picker {
+    border-color: #1b376c;
+    background-color:#fff;
+}
+
+.x-date-middle,.x-date-left,.x-date-right {
+	background-image: url(../images/default/shared/hd-sprite.gif);
+	color:#fff;
+	font:bold 11px "sans serif", tahoma, verdana, helvetica;
+}
+
+.x-date-middle .x-btn .x-btn-text {
+    color:#fff;
+}
+
+.x-date-middle .x-btn-mc em.x-btn-arrow {
+    background-image:url(../images/default/toolbar/btn-arrow-light.gif);
+}
+
+.x-date-right a {
+    background-image: url(../images/default/shared/right-btn.gif);
+}
+
+.x-date-left a{
+	background-image: url(../images/default/shared/left-btn.gif);
+}
+
+.x-date-inner th {
+    background-color:#dfecfb;
+    background-image:url(../images/default/shared/glass-bg.gif);
+	border-bottom-color:#a3bad9;
+    font:normal 10px arial, helvetica,tahoma,sans-serif;
+	color:#233d6d;
+}
+
+.x-date-inner td {
+    border-color:#fff;
+}
+
+.x-date-inner a {
+    font:normal 11px arial, helvetica,tahoma,sans-serif;
+    color:#000;
+}
+
+.x-date-inner .x-date-active{
+	color:#000;
+}
+
+.x-date-inner .x-date-selected a{
+    background-color:#dfecfb;
+	background-image:url(../images/default/shared/glass-bg.gif);
+	border-color:#8db2e3;
+}
+
+.x-date-inner .x-date-today a{
+	border-color:darkred;
+}
+
+.x-date-inner .x-date-selected span{
+    font-weight:bold;
+}
+
+.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {
+	color:#aaa;
+}
+
+.x-date-bottom {
+    border-top-color:#a3bad9;
+    background-color:#dfecfb;
+    background-image:url(../images/default/shared/glass-bg.gif);
+}
+
+.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{
+    color:#000;
+    background-color:#ddecfe;
+}
+
+.x-date-inner .x-date-disabled a {
+	background-color:#eee;
+	color:#bbb;
+}
+
+.x-date-mmenu{
+    background-color:#eee !important;
+}
+
+.x-date-mmenu .x-menu-item {
+	font-size:10px;
+	color:#000;
+}
+
+.x-date-mp {
+	background-color:#fff;
+}
+
+.x-date-mp td {
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns button {
+	background-color:#083772;
+	color:#fff;
+	border-color: #3366cc #000055 #000055 #3366cc;
+	font:normal 11px arial, helvetica,tahoma,sans-serif;
+}
+
+.x-date-mp-btns {
+    background-color: #dfecfb;
+	background-image: url(../images/default/shared/glass-bg.gif);
+}
+
+.x-date-mp-btns td {
+	border-top-color: #c5d2df;
+}
+
+td.x-date-mp-month a,td.x-date-mp-year a {
+	color:#15428b;
+}
+
+td.x-date-mp-month a:hover,td.x-date-mp-year a:hover {
+	color:#15428b;
+	background-color: #ddecfe;
+}
+
+td.x-date-mp-sel a {
+    background-color: #dfecfb;
+	background-image: url(../images/default/shared/glass-bg.gif);
+	border-color:#8db2e3;
+}
+
+.x-date-mp-ybtn a {
+    background-image:url(../images/default/panel/tool-sprites.gif);
+}
+
+td.x-date-mp-sep {
+   border-right-color:#c5d2df;
+}.x-tip .x-tip-close{
+	background-image: url(../images/default/qtip/close.gif);
+}
+
+.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr {
+	background-image: url(../images/default/qtip/tip-sprite.gif);
+}
+
+.x-tip .x-tip-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+}
+.x-tip .x-tip-ml {
+	background-color: #fff;
+}
+
+.x-tip .x-tip-header-text {
+    font: bold 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-tip .x-tip-body {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    color:#444;
+}
+
+.x-form-invalid-tip .x-tip-tc, .x-form-invalid-tip .x-tip-tl, .x-form-invalid-tip .x-tip-tr, .x-form-invalid-tip .x-tip-bc,
+.x-form-invalid-tip .x-tip-bl, .x-form-invalid-tip .x-tip-br, .x-form-invalid-tip .x-tip-ml, .x-form-invalid-tip .x-tip-mr
+{
+	background-image: url(../images/default/form/error-tip-corners.gif);
+}
+
+.x-form-invalid-tip .x-tip-body {
+    background-image:url(../images/default/form/exclamation.gif);
+}
+
+.x-tip-anchor {
+    background-image:url(../images/default/qtip/tip-anchor-sprite.gif);
+}.x-menu {
+    background-color:#f0f0f0;
+	background-image:url(../images/default/menu/menu.gif);
+}
+
+.x-menu-floating{
+    border-color:#718bb7;
+}
+
+.x-menu-nosep {
+	background-image:none;
+}
+
+.x-menu-list-item{
+	font:normal 11px arial,tahoma,sans-serif;
+}
+
+.x-menu-item-arrow{
+	background-image:url(../images/default/menu/menu-parent.gif);
+}
+
+.x-menu-sep {
+    background-color:#e0e0e0;
+	border-bottom-color:#fff;
+}
+
+a.x-menu-item {
+	color:#222;
+}
+
+.x-menu-item-active {
+    background-image: url(../images/default/menu/item-over.gif);
+	background-color: #dbecf4;
+    border-color:#aaccf6;
+}
+
+.x-menu-item-active a.x-menu-item {
+	border-color:#aaccf6;
+}
+
+.x-menu-check-item .x-menu-item-icon{
+	background-image:url(../images/default/menu/unchecked.gif);
+}
+
+.x-menu-item-checked .x-menu-item-icon{
+	background-image:url(../images/default/menu/checked.gif);
+}
+
+.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
+    background-image:url(../images/default/menu/group-checked.gif);
+}
+
+.x-menu-group-item .x-menu-item-icon{
+    background-image:none;
+}
+
+.x-menu-plain {
+	background-color:#f0f0f0 !important;
+    background-image: none;
+}
+
+.x-date-menu, .x-color-menu{
+    background-color: #fff !important;
+}
+
+.x-menu .x-date-picker{
+    border-color:#a3bad9;
+}
+
+.x-cycle-menu .x-menu-item-checked {
+    border-color:#a3bae9 !important;
+    background-color:#def8f6;
+}
+
+.x-menu-scroller-top {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+
+.x-menu-scroller-bottom {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+.x-box-tl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-tc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-tr {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-ml {
+	background-image: url(../images/default/box/l.gif);
+}
+
+.x-box-mc {
+	background-color: #eee;
+    background-image: url(../images/default/box/tb.gif);
+	font-family: "Myriad Pro","Myriad Web","Tahoma","Helvetica","Arial",sans-serif;
+	color: #393939;
+	font-size: 12px;
+}
+
+.x-box-mc h3 {
+	font-size: 14px;
+	font-weight: bold;
+}
+
+.x-box-mr {
+	background-image: url(../images/default/box/r.gif);
+}
+
+.x-box-bl {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-bc {
+	background-image: url(../images/default/box/tb.gif);
+}
+
+.x-box-br {
+	background-image: url(../images/default/box/corners.gif);
+}
+
+.x-box-blue .x-box-bl, .x-box-blue .x-box-br, .x-box-blue .x-box-tl, .x-box-blue .x-box-tr {
+	background-image: url(../images/default/box/corners-blue.gif);
+}
+
+.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc {
+	background-image: url(../images/default/box/tb-blue.gif);
+}
+
+.x-box-blue .x-box-mc {
+	background-color: #c3daf9;
+}
+
+.x-box-blue .x-box-mc h3 {
+	color: #17385b;
+}
+
+.x-box-blue .x-box-ml {
+	background-image: url(../images/default/box/l-blue.gif);
+}
+
+.x-box-blue .x-box-mr {
+	background-image: url(../images/default/box/r-blue.gif);
+}.x-combo-list {
+    border-color:#98c0f4;
+    background-color:#ddecfe;
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+}
+
+.x-combo-list-inner {
+    background-color:#fff;
+}
+
+.x-combo-list-hd {
+    font:bold 11px tahoma, arial, helvetica, sans-serif;
+    color:#15428b;
+    background-image: url(../images/default/layout/panel-title-light-bg.gif);
+    border-bottom-color:#98c0f4;
+}
+
+.x-resizable-pinned .x-combo-list-inner {
+    border-bottom-color:#98c0f4;
+}
+
+.x-combo-list-item {
+    border-color:#fff;
+}
+
+.x-combo-list .x-combo-selected{
+	border-color:#a3bae9 !important;
+    background-color:#dfe8f6;
+}
+
+.x-combo-list .x-toolbar {
+    border-top-color:#98c0f4;
+}
+
+.x-combo-list-small {
+    font:normal 11px tahoma, arial, helvetica, sans-serif;
+}.x-panel {
+    border-color: #99bbe8;
+}
+
+.x-panel-header {
+    color:#15428b;
+	font-weight:bold; 
+    font-size: 11px;
+    font-family: tahoma,arial,verdana,sans-serif;
+    border-color:#99bbe8;
+    background-image: url(../images/default/panel/white-top-bottom.gif);
+}
+
+.x-panel-body {
+    border-color:#99bbe8;
+    background-color:#fff;
+}
+
+.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {
+    border-color:#99bbe8;
+}
+
+.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-body-noheader, .x-panel-mc .x-panel-body {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-tl .x-panel-header {
+    color:#15428b;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-panel-tc {
+	background-image: url(../images/default/panel/top-bottom.gif);
+}
+
+.x-panel-tl, .x-panel-tr, .x-panel-bl,  .x-panel-br{
+	background-image: url(../images/default/panel/corners-sprite.gif);
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-bc {
+	background-image: url(../images/default/panel/top-bottom.gif);
+}
+
+.x-panel-mc {
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#dfe8f6;
+}
+
+.x-panel-ml {
+	background-color: #fff;
+    background-image:url(../images/default/panel/left-right.gif);
+}
+
+.x-panel-mr {
+	background-image: url(../images/default/panel/left-right.gif);
+}
+
+.x-tool {
+    background-image:url(../images/default/panel/tool-sprites.gif);
+}
+
+.x-panel-ghost {
+    background-color:#cbddf3;
+}
+
+.x-panel-ghost ul {
+    border-color:#99bbe8;
+}
+
+.x-panel-dd-spacer {
+    border-color:#99bbe8;
+}
+
+.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{
+    font:normal 11px arial,tahoma, helvetica, sans-serif;
+}
+.x-window-proxy {
+    background-color:#c7dffc;
+    border-color:#99bbe8;
+}
+
+.x-window-tl .x-window-header {
+    color:#15428b;
+	font:bold 11px tahoma,arial,verdana,sans-serif;
+}
+
+.x-window-tc {
+	background-image: url(../images/default/window/top-bottom.png);
+}
+
+.x-window-tl {
+	background-image: url(../images/default/window/left-corners.png);
+}
+
+.x-window-tr {
+	background-image: url(../images/default/window/right-corners.png);
+}
+
+.x-window-bc {
+	background-image: url(../images/default/window/top-bottom.png);
+}
+
+.x-window-bl {
+	background-image: url(../images/default/window/left-corners.png);
+}
+
+.x-window-br {
+	background-image: url(../images/default/window/right-corners.png);
+}
+
+.x-window-mc {
+    border-color:#99bbe8;
+    font: normal 11px tahoma,arial,helvetica,sans-serif;
+    background-color:#dfe8f6;
+}
+
+.x-window-ml {
+	background-image: url(../images/default/window/left-right.png);
+}
+
+.x-window-mr {
+	background-image: url(../images/default/window/left-right.png);
+}
+
+.x-window-maximized .x-window-tc {
+    background-color:#fff;
+}
+
+.x-window-bbar .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-panel-ghost .x-window-tl {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-collapsed .x-window-tl {
+    border-bottom-color:#84a0c4;
+}
+
+.x-dlg-mask{
+   background-color:#ccc;
+}
+
+.x-window-plain .x-window-mc {
+    background-color: #ccd9e8;
+    border-color: #a3bae9 #dfe8f6 #dfe8f6 #a3bae9;
+}
+
+.x-window-plain .x-window-body {
+    border-color: #dfe8f6 #a3bae9 #a3bae9 #dfe8f6;
+}
+
+body.x-body-masked .x-window-plain .x-window-mc {
+    background-color: #ccd9e8;
+}.x-html-editor-wrap {
+    border-color:#a9bfd3;
+    background-color:#fff;
+}
+.x-html-editor-tb .x-btn-text {
+    background-image:url(../images/default/editor/tb-sprite.gif);
+}.x-panel-noborder .x-panel-header-noborder {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#99bbe8;
+}
+
+.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-tab-panel-bbar-noborder .x-toolbar {
+    border-top-color:#99bbe8;
+}
+
+.x-tab-panel-tbar-noborder .x-toolbar {
+    border-bottom-color:#99bbe8;
+}.x-border-layout-ct {
+    background-color:#dfe8f6;
+}
+
+.x-accordion-hd {
+	color:#222;
+    font-weight:normal;
+    background-image: url(../images/default/panel/light-hd.gif);
+}
+
+.x-layout-collapsed{
+    background-color:#d2e0f2;
+	border-color:#98c0f4;
+}
+
+.x-layout-collapsed-over{
+    background-color:#d9e8fb;
+}
+
+.x-layout-split-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+.x-layout-split-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+.x-layout-split-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}
+.x-layout-split-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-west .x-layout-mini {
+    background-image:url(../images/default/layout/mini-right.gif);
+}
+
+.x-layout-cmini-east .x-layout-mini {
+    background-image:url(../images/default/layout/mini-left.gif);
+}
+
+.x-layout-cmini-north .x-layout-mini {
+    background-image:url(../images/default/layout/mini-bottom.gif);
+}
+
+.x-layout-cmini-south .x-layout-mini {
+    background-image:url(../images/default/layout/mini-top.gif);
+}.x-progress-wrap {
+    border-color:#6593cf;
+}
+
+.x-progress-inner {
+    background-color:#e0e8f3;
+    background-image:url(../images/default/qtip/bg.gif);
+}
+
+.x-progress-bar {
+    background-color:#9cbfee;
+    background-image:url(../images/default/progress/progress-bg.gif);
+    border-top-color:#d1e4fd;
+    border-bottom-color:#7fa9e4;
+    border-right-color:#7fa9e4;
+}
+
+.x-progress-text {
+    font-size:11px;
+    font-weight:bold;
+    color:#fff;
+}
+
+.x-progress-text-back {
+    color:#396095;
+}.x-list-header{
+    background-color:#f9f9f9;
+	background-image:url(../images/default/grid/grid3-hrow.gif);
+}
+
+.x-list-header-inner div em {
+    border-left-color:#ddd;
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-body dt em {
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-list-over {
+    background-color:#eee;
+}
+
+.x-list-selected {
+    background-color:#dfe8f6;
+}
+
+.x-list-resizer {
+    border-left-color:#555;
+    border-right-color:#555;
+}
+
+.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc {
+    background-image:url(../images/default/grid/sort-hd.gif);
+    border-color: #99bbe8;
+}.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner {
+    background-image:url(../images/default/slider/slider-bg.png);
+}
+
+.x-slider-horz .x-slider-thumb {
+    background-image:url(../images/default/slider/slider-thumb.png);
+}
+
+.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner {
+    background-image:url(../images/default/slider/slider-v-bg.png);
+}
+
+.x-slider-vert .x-slider-thumb {
+    background-image:url(../images/default/slider/slider-v-thumb.png);
+}.x-window-dlg .ext-mb-text,
+.x-window-dlg .x-window-header-text {
+    font-size:12px;
+}
+
+.x-window-dlg .ext-mb-textarea {
+    font:normal 12px tahoma,arial,helvetica,sans-serif;
+}
+
+.x-window-dlg .x-msg-box-wait {
+    background-image:url(../images/default/grid/loading.gif);
+}
+
+.x-window-dlg .ext-mb-info {
+    background-image:url(../images/default/window/icon-info.gif);
+}
+
+.x-window-dlg .ext-mb-warning {
+    background-image:url(../images/default/window/icon-warning.gif);
+}
+
+.x-window-dlg .ext-mb-question {
+    background-image:url(../images/default/window/icon-question.gif);
+}
+
+.x-window-dlg .ext-mb-error {
+    background-image:url(../images/default/window/icon-error.gif);
+}
\ No newline at end of file
diff --git a/modules/organize/vendor/ext/css/ux-all.css b/modules/organize/vendor/ext/css/ux-all.css
new file mode 100644
index 0000000..42943be
--- /dev/null
+++ b/modules/organize/vendor/ext/css/ux-all.css
@@ -0,0 +1,772 @@
+/*!
+ * Ext JS Library 3.3.1
+ * Copyright(c) 2006-2010 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+.ux-layout-center-item {
+    margin:0 auto;
+    text-align:left;
+}
+.ux-layout-center .x-panel-body,   
+body.ux-layout-center {            
+    text-align:center;
+}
+td.ux-grid-hd-group-cell {
+    background: url(../../../resources/images/default/grid/grid3-hrow.gif) repeat-x bottom;
+}.x-column-tree .x-panel-header {
+	padding: 3px 0px 0px 0px;
+	border-bottom-width: 0px;
+}
+
+.x-column-tree .x-panel-header .x-panel-header-text {
+	margin-left: 3px
+}
+
+.x-column-tree .x-tree-node {
+    zoom:1;
+}
+.x-column-tree .x-tree-node-el {
+    /*border-bottom:1px solid #eee; borders? */
+    zoom:1;
+}
+.x-column-tree .x-tree-selected {
+    background: #d9e8fb;
+}
+.x-column-tree  .x-tree-node a {
+    line-height:18px;
+    vertical-align:middle;
+}
+.x-column-tree  .x-tree-node a span{
+	
+}
+.x-column-tree  .x-tree-node .x-tree-selected a span{
+	background:transparent;
+	color:#000;
+}
+.x-tree-col {
+    float:left;
+    overflow:hidden;
+    padding:0 1px;
+    zoom:1;
+}
+
+.x-tree-col-text, .x-tree-hd-text {
+    color:#000;
+    overflow:hidden;
+    -o-text-overflow: ellipsis;
+    text-overflow: ellipsis;
+    padding:3px 3px 3px 5px;
+    white-space: nowrap;
+    font:normal 11px arial, tahoma, helvetica, sans-serif;
+}
+
+.x-tree-headers {
+	margin-top: 3px;
+	background: #f9f9f9 url(../../../resources/images/default/grid/grid3-hrow.gif) repeat-x 0 bottom;
+	cursor:default;
+    zoom:1;
+}
+
+.x-tree-hd {
+    float:left;
+    overflow:hidden;
+    border-left:1px solid #eee;
+    border-right:1px solid #d0d0d0;
+}
+/*
+ * FileUploadField component styles
+ */
+.x-form-file-wrap {
+    position: relative;
+    height: 22px;
+}
+.x-form-file-wrap .x-form-file {
+	position: absolute;
+	right: 0;
+	-moz-opacity: 0;
+	filter:alpha(opacity: 0);
+	opacity: 0;
+	z-index: 2;
+    height: 22px;
+}
+.x-form-file-wrap .x-form-file-btn {
+	position: absolute;
+	right: 0;
+	z-index: 1;
+}
+.x-form-file-wrap .x-form-file-text {
+    position: absolute;
+    left: 0;
+    z-index: 3;
+    color: #777;
+}/**
+ * GridFilters Styles
+ **/
+/*
+.x-grid3-hd-row .ux-filtered-column {
+	border-left:  1px solid #C7E3B4;
+	border-right: 1px solid #C7E3B4;
+}
+
+.x-grid3-hd-row .ux-filtered-column .x-grid3-hd-inner {
+	background-image: url(../images/header_bg.gif);
+}
+
+.ux-filtered-column .x-grid3-hd-btn {
+	background-image: url(../images/hd-btn.gif);
+}
+*/
+.x-grid3-hd-row td.ux-filtered-column {   
+    font-style: italic;  
+    font-weight: bold;
+}		
+
+.ux-filtered-column.sort-asc .x-grid3-sort-icon {
+	background-image: url(../images/sort_filtered_asc.gif) !important;
+}
+
+.ux-filtered-column.sort-desc .x-grid3-sort-icon {
+	background-image: url(../images/sort_filtered_desc.gif) !important;
+}
+
+.ux-gridfilter-text-icon {
+	background-image: url(../images/find.png) !important;
+}
+
+/* Temporary Patch for Bug ??? */
+.x-menu-list-item-indent .x-menu-item-icon {
+	position: relative;
+    top: 3px;
+    left: 3px;
+	margin-right: 10px;
+}
+li.x-menu-list-item-indent {
+	padding-left:0px;
+}
+li.x-menu-list-item div {
+	display: block;
+}
+
+/**
+ * RangeMenu Styles
+ **/
+.ux-rangemenu-gt {
+	background-image: url(../images/greater_than.png) !important;
+}
+
+.ux-rangemenu-lt {
+	background-image: url(../images/less_than.png) !important;
+}
+
+.ux-rangemenu-eq {
+	background-image: url(../images/equals.png) !important;
+}
+.x-grid3-summary-row {
+    border-left:1px solid #fff;
+    border-right:1px solid #fff;
+    color:#333;
+    background: #f1f2f4;
+}
+.x-grid3-summary-row .x-grid3-cell-inner {
+    font-weight:bold;
+    padding-bottom:4px;
+}
+.x-grid3-cell-first .x-grid3-cell-inner {
+    padding-left:16px;
+}
+.x-grid-hide-summary .x-grid3-summary-row {
+    display:none;
+}
+.x-grid3-summary-msg {
+    padding:4px 16px;
+    font-weight:bold;
+}.x-grouptabs-panel {
+    background-color: #4E78B1;
+    border: solid 15px #4E78B1;
+}
+.x-tab-panel-left .x-grouptabs-panel-header,
+.x-tab-panel-right .x-grouptabs-panel-header {
+    float: left;
+    border: 0;
+    background: transparent;
+}
+.x-tab-panel-right .x-grouptabs-panel-header {
+    float:right;
+}
+.x-tab-panel-left .x-grouptabs-bwrap {
+    float: right;
+    position: relative;
+}
+.x-tab-panel-right .x-grouptabs-bwrap {
+    float: left;
+    position: relative;
+}
+.x-tab-panel-left ul.x-grouptabs-strip,
+.x-tab-panel-right ul.x-grouptabs-strip {
+    width: auto;
+	display: block;
+}
+.x-tab-panel-left ul.x-grouptabs-strip li,
+.x-tab-panel-right ul.x-grouptabs-strip li {
+    padding: 6px 0 2px 6px;
+    float: none;
+    margin: 0;
+    position: relative;
+    clear: both;
+}
+.x-tab-panel-left .x-tab-panel-header ul.x-grouptabs-strip a.x-grouptabs-text,
+.x-tab-panel-right .x-tab-panel-header ul.x-grouptabs-strip a.x-grouptabs-text{
+	font-size: 13px;
+	line-height: 18px;
+	cursor: pointer;
+}
+
+.x-tab-panel-left .x-tab-panel-header ul.x-grouptabs-strip a.x-grouptabs-text{
+    padding-left: 18px;
+}
+.x-tab-panel-right .x-tab-panel-header ul.x-grouptabs-strip a.x-grouptabs-text{
+    padding-right: 18px;
+}
+
+.x-tab-panel-left .x-tab-panel-header ul.x-grouptabs-sub a.x-grouptabs-text,
+.x-tab-panel-right .x-tab-panel-header ul.x-grouptabs-sub a.x-grouptabs-text{
+	font-size: 12px;
+    padding: 0;  
+}
+
+.x-tab-panel-left .x-tab-panel-header ul.x-grouptabs-sub a.x-grouptabs-text{
+	margin-left: 4px;
+}
+.x-tab-panel-right .x-tab-panel-header ul.x-grouptabs-sub a.x-grouptabs-text{
+	margin-right: 4px;
+}
+
+.x-grouptabs-panel .x-grouptabs-strip a.x-grouptabs-text{
+    overflow: hidden;
+    white-space: nowrap;
+	display: block;
+    color: #DFE8F6;
+    font-family: tahoma, arial, sans-serif;
+    font-weight: bold;
+    text-decoration: none;
+}
+.x-tab-panel-right .x-grouptabs-strip a.x-grouptabs-text {
+    text-align: right;
+}
+
+.x-grouptabs-panel .x-grouptabs-strip-active a.x-grouptabs-text {
+    color: #395B8E;
+}
+
+.x-grouptabs-panel ul.x-grouptabs-sub a.x-grouptabs-text {
+	font-weight: normal;
+}
+.x-tab-joint {
+    position: absolute;
+    width: 3px;
+    top: 1px;
+    background: #fff;
+    z-index: 8999;
+}
+
+.x-grouptabs-panel .x-grouptabs-panel-body {
+    border: 1px solid #999;
+}
+
+.x-grouptabs-panel ul.x-grouptabs-strip li {
+    border-top: 1px solid transparent;
+    border-bottom: 1px solid transparent;
+	border-left: 1px solid transparent;
+}
+
+.x-grouptabs-panel ul.x-grouptabs-strip li.x-grouptabs-strip-active {
+    border: 0;
+    background: #fff;
+    border-top: 1px solid #999;
+    border-bottom: 1px solid #999;
+}
+
+.x-tab-panel-left ul.x-grouptabs-strip li.x-grouptabs-strip-active {
+    border-left: 1px solid #999;
+}
+.x-tab-panel-right ul.x-grouptabs-strip li.x-grouptabs-strip-active {
+    border-right: 1px solid #999;
+}
+
+.x-grouptabs-panel li.x-grouptabs-strip-active ul.x-grouptabs-sub li.x-grouptabs-strip-active{
+    background-color: #EDEEF0;
+}
+
+.x-grouptabs-panel li.x-grouptabs-strip-active ul.x-grouptabs-sub {
+    background-color: transparent;
+}
+
+.x-grouptabs-panel li.x-grouptabs-strip-active ul.x-grouptabs-sub li {
+    border-color: transparent;
+}
+
+/* Tab corners */
+.x-grouptabs-panel .x-grouptabs-corner {
+    background-image: url('../images/x-grouptabs-corners.gif');
+    display: none;
+    width: 11px;
+    height: 11px;
+    position: absolute;
+    font-size: 1px;
+    line-height: 6px;
+    overflow: hidden;
+    zoom:1;
+}
+.x-grouptabs-panel .x-grouptabs-strip-active .x-grouptabs-corner {
+    display: block;
+}
+.x-grouptabs-panel .x-grouptabs-main.x-grouptabs-strip-active ul.x-grouptabs-sub .x-grouptabs-corner {
+	display: none;
+}
+
+.x-grouptabs-panel .x-grouptabs-corner-top-left {
+    background-position: top left;
+    left: 0; top: 0;
+}
+.x-grouptabs-panel .x-grouptabs-corner-bottom-left {
+    background-position: bottom left;
+    left: 0; bottom: 0;
+}
+.x-grouptabs-panel .x-grouptabs-corner-top-right {
+    background-position: top right;
+    right: 0; top: 0;
+}
+.x-grouptabs-panel .x-grouptabs-corner-bottom-right {
+    background-position: bottom right;
+    right: 0; bottom: 0;
+}
+.x-grouptabs-panel li.x-grouptabs-strip-active .x-grouptabs-corner-bottom-left{
+    bottom: -4px; left: -4px;
+}
+.x-grouptabs-panel li.x-grouptabs-strip-active .x-grouptabs-corner-bottom-right{
+    bottom: -4px; right: -4px;
+}
+.x-grouptabs-panel li.x-grouptabs-strip-active .x-grouptabs-corner-top-left{
+    top: -4px; left: -4px;
+}
+.x-grouptabs-panel li.x-grouptabs-strip-active .x-grouptabs-corner-top-right{
+    top: -4px; right: -4px;
+}
+
+.x-grouptabs-panel ul.x-grouptabs-sub li.x-tab-with-icon a.x-grouptabs-text {
+    background-repeat: no-repeat;
+    padding-left: 20px;
+}
+
+/* General tab styling */
+.x-grouptabs-panel .x-grouptabs-expand {
+	background: transparent url('../images/elbow-plus-nl.gif') no-repeat;
+	width: 16px;
+	height: 16px;
+	position: absolute;
+	left: 7px;
+	top: 6px;
+}
+
+.ext-ie6 .x-grouptabs-panel .x-grouptabs-expand,
+.ext-border-box .x-grouptabs-panel .x-grouptabs-expand {
+	left: 0;
+}
+
+.x-grouptabs-expanded .x-grouptabs-expand {
+	background-image: url('../images/elbow-minus-nl.gif');
+}
+
+/* GroupTabs sub group styling */
+.x-grouptabs-sub {
+	display: none;
+	margin-top: 4px;
+}
+
+.x-grouptabs-expanded .x-grouptabs-sub {
+	display: block;
+}
+
+.x-grouptabs-panel ul.x-grouptabs-sub li {
+	height: 18px;
+	margin: 0 0 2px;
+    padding: 0;
+}
+
+.x-grouptabs-panel ul.x-grouptabs-sub .x-grouptabs-main-item {
+	display: none;
+}
+
+.x-tab-with-icon{
+   border-style:none !important;
+}
+.x-grid3-locked, .x-grid3-unlocked {
+	overflow: hidden;
+	position: absolute;
+}
+
+.x-grid3-locked {
+	border-right: 1px solid #99BBE8;
+}
+
+.x-grid3-locked .x-grid3-scroller {
+	overflow: hidden;
+}
+
+.x-grid3-locked .x-grid3-row {
+	border-right: 0;
+}
+
+.x-grid3-scroll-spacer {
+	height: 19px;
+}
+
+.x-grid3-unlocked .x-grid3-header-offset {
+	padding-left: 0;
+}
+
+.x-grid3-unlocked .x-grid3-row {
+	border-left: 0;
+}
+.ux-mselect{
+    overflow:auto;
+    background:white;
+    position:relative; /* for calculating scroll offsets */
+    zoom:1;
+    overflow:auto;	
+}
+.ux-mselect-item{
+    font:normal 12px tahoma, arial, helvetica, sans-serif;
+    padding:2px;
+    border:1px solid #fff;
+    white-space: nowrap;
+    cursor:pointer;
+}
+.ux-mselect-selected{
+	border:1px dotted #a3bae9 !important;
+    background:#DFE8F6;
+    cursor:pointer;
+}
+
+.x-view-drag-insert-above { 
+    border-top:1px dotted #3366cc; 
+} 
+.x-view-drag-insert-below { 
+    border-bottom:1px dotted #3366cc; 
+} 
+.x-panel-resize {
+        height:5px;
+        background:transparent url(../images/panel-handle.gif) no-repeat center bottom;
+        position:relative;
+        left:0;
+        top:2px;
+        cursor:n-resize;
+        cursor:row-resize;
+        /* for IE */
+        font-size:1px;
+        line-height:1px;
+        overflow:hidden;
+}.x-portal .x-panel-dd-spacer {
+    margin-bottom:10px;
+}
+
+.x-portlet {
+    margin-bottom:10px;
+}
+
+/* Clean up the look of the portlets */
+.x-portlet .x-panel-ml {
+    padding-left:2px;
+}
+.x-portlet .x-panel-mr {
+    padding-right:2px;
+}
+.x-portlet .x-panel-bl {
+    padding-left:2px;
+}
+
+.x-portlet .x-panel-br {
+    padding-right:2px;
+}
+.x-portlet .x-panel-body {
+    background:white;
+}
+.x-portlet .x-panel-mc {
+    padding-top:2px;
+}
+.x-portlet .x-panel-bc .x-panel-footer {
+    padding-bottom:2px;
+}
+.x-portlet .x-panel-nofooter .x-panel-bc {
+    height:2px;
+}.ext-ie .x-row-editor .x-form-text {
+    margin:0 !important; 
+}
+.x-row-editor-header {
+    height:2px;
+    overflow:hidden;
+    background: transparent url(../images/row-editor-bg.gif) repeat-x 0 0;
+}
+.x-row-editor-footer {
+    height:2px;
+    overflow:hidden;
+    background: transparent url(../images/row-editor-bg.gif) repeat-x 0 -2px;
+}
+.ext-ie .x-row-editor-footer {
+    margin-top:-1px;
+}
+
+.x-row-editor-body {
+    overflow:hidden;
+    zoom:1;
+    background: #ebf2fb;
+    padding-top:2px;
+}
+.x-row-editor .x-btns {
+    position:absolute;
+    top:28px;
+    left:20px;
+    padding-left:5px;
+    background: transparent url(../images/row-editor-btns.gif) no-repeat 0 0;
+}
+.x-row-editor .x-btns .x-plain-bwrap {
+    padding-right:5px;
+    background: transparent url(../images/row-editor-btns.gif) no-repeat right -31px;
+}
+.x-row-editor .x-btns .x-plain-body {
+    background: transparent url(../images/row-editor-btns.gif) repeat-x 0 -62px;
+    height:31px;
+}
+.x-row-editor .x-btns .x-table-layout-cell {
+    padding:3px;
+}
+
+/* Fixes for IE6/7 trigger fields */
+.ext-ie6 .x-row-editor .x-form-field-wrap .x-form-trigger, .ext-ie7 .x-row-editor .x-form-field-wrap .x-form-trigger {
+  top: 1px;
+}
+
+.ext-ie6 .x-row-editor .x-form-field-trigger-wrap, .ext-ie7 .x-row-editor .x-form-field-trigger-wrap {
+  margin-top: -1px;
+}
+
+.errorTip .x-tip-body ul{
+    list-style-type:disc;
+    margin-left:15px;
+}
+.x-form-spinner-proxy{
+	/*background-color:#ff00cc;*/
+}
+.x-form-field-wrap .x-form-spinner-trigger {
+    background:transparent url('../images/spinner.gif') no-repeat 0 0;
+}
+
+.x-form-field-wrap .x-form-spinner-overup{
+    background-position:-17px 0;
+}
+.x-form-field-wrap .x-form-spinner-clickup{
+    background-position:-34px 0;
+}
+.x-form-field-wrap .x-form-spinner-overdown{
+    background-position:-51px 0;
+}
+.x-form-field-wrap .x-form-spinner-clickdown{
+    background-position:-68px 0;
+}
+
+
+.x-trigger-wrap-focus .x-form-spinner-trigger{
+    background-position:-85px 0;
+}
+.x-trigger-wrap-focus .x-form-spinner-overup{
+    background-position:-102px 0;
+}
+.x-trigger-wrap-focus .x-form-spinner-clickup{
+    background-position:-119px 0;
+}
+.x-trigger-wrap-focus .x-form-spinner-overdown{
+    background-position:-136px 0;
+}
+.x-trigger-wrap-focus .x-form-spinner-clickdown{
+    background-position:-153px 0;
+}
+.x-trigger-wrap-focus .x-form-trigger{
+    border-bottom: 1px solid #7eadd9;
+}
+
+.x-form-field-wrap .x-form-spinner-splitter {
+	line-height:1px;
+	font-size:1px;
+    background:transparent url('../images/spinner-split.gif') no-repeat 0 0;
+	position:absolute;
+	cursor: n-resize;
+}
+.x-trigger-wrap-focus .x-form-spinner-splitter{
+    background-position:-14px 0;
+}
+/* StatusBar - structure */
+.x-statusbar .x-status-text {
+    cursor: default;
+/*
+    height: 21px;
+    line-height: 21px;
+    padding: 0 4px;
+*/
+}
+.x-statusbar .x-status-busy {
+    padding-left: 25px !important;
+    background: transparent no-repeat 3px 2px;
+}
+
+.x-toolbar div.xtb-text
+
+.x-statusbar .x-status-text-panel {
+    border-top: 1px solid;
+    border-right: 1px solid;
+    border-bottom: 1px solid;
+    border-left: 1px solid;
+    padding: 2px 8px 2px 5px;
+}
+
+/* StatusBar word processor example styles */
+
+#word-status .x-status-text-panel .spacer {
+    width: 60px;
+    font-size:0;
+    line-height:0;
+}
+#word-status .x-status-busy {
+    padding-left: 25px !important;
+    background: transparent no-repeat 3px 2px;
+}
+#word-status .x-status-saved {
+    padding-left: 25px !important;
+    background: transparent no-repeat 3px 2px;
+}
+
+/* StatusBar form validation example styles */
+
+.x-statusbar .x-status-error {
+    cursor: pointer;
+    padding-left: 25px !important;
+    background: transparent no-repeat 3px 2px;
+}
+.x-statusbar .x-status-valid {
+    padding-left: 25px !important;
+    background: transparent no-repeat 3px 2px;
+}
+.x-status-error-list {
+    font: 11px tahoma,arial,verdana,sans-serif;
+    position: absolute;
+    z-index: 9999;
+    border-top: 1px solid;
+    border-right: 1px solid;
+    border-bottom: 1px solid;
+    border-left: 1px solid;
+    padding: 5px 10px;
+}
+.x-status-error-list li {
+    cursor: pointer;
+    list-style: disc;
+    margin-left: 10px;
+}
+.x-status-error-list li a {
+    text-decoration: none;
+}
+.x-status-error-list li a:hover {
+    text-decoration: underline;
+}
+
+
+/* *********************************************************** */
+/* *********************************************************** */
+/* *********************************************************** */
+
+
+/* StatusBar - visual */
+
+.x-statusbar .x-status-busy {
+    background-image: url(../images/loading.gif);
+}
+.x-statusbar .x-status-text-panel {
+    border-color: #99bbe8 #fff #fff #99bbe8;
+}
+
+/* StatusBar word processor example styles */
+
+#word-status .x-status-text {
+    color: #777;
+}
+#word-status .x-status-busy {
+    background-image: url(../images/saving.gif);
+}
+#word-status .x-status-saved {
+    background-image: url(../images/saved.png);
+}
+
+/* StatusBar form validation example styles */
+
+.x-statusbar .x-status-error {
+    color: #C33;
+    background-image: url(../images/exclamation.gif);
+}
+.x-statusbar .x-status-valid {
+    background-image: url(../images/accept.png);
+}
+.x-status-error-list {
+    border-color: #C33;
+}
+.x-status-error-list li a {
+    color: #15428B;
+}.x-treegrid-root-table {
+    border-right: 1px solid;
+}
+
+.x-treegrid-root-node {
+    overflow: auto;
+}
+
+.x-treegrid-hd-hidden {
+    visibility: hidden;
+    border: 0;
+    width: 0;
+}
+
+.x-treegrid-col {
+    border-bottom: 1px solid;
+    height: 20px;
+    overflow: hidden;
+    vertical-align: top;
+	-o-text-overflow: ellipsis;
+	text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.x-treegrid-text {
+    padding-left: 4px;
+    -moz-user-select: none;
+    -khtml-user-select: none;
+}
+
+.x-treegrid-resizer {
+    border-left:1px solid;
+    border-right:1px solid;
+    position:absolute;
+    left:0;
+    top:0;
+}
+
+.x-treegrid-header-inner {
+    overflow: hidden;
+}
+
+.x-treegrid-root-table,
+.x-treegrid-col {
+    border-color: #ededed;
+}
+
+.x-treegrid-resizer {
+    border-left-color:#555;
+    border-right-color:#555;
+}
\ No newline at end of file
diff --git a/modules/organize/vendor/ext/images/default/box/tb-blue.gif b/modules/organize/vendor/ext/images/default/box/tb-blue.gif
new file mode 100644
index 0000000..562fecc
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/box/tb-blue.gif differ
diff --git a/modules/organize/vendor/ext/images/default/button/btn.gif b/modules/organize/vendor/ext/images/default/button/btn.gif
new file mode 100644
index 0000000..06b404d
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/button/btn.gif differ
diff --git a/modules/organize/vendor/ext/images/default/dd/drop-no.gif b/modules/organize/vendor/ext/images/default/dd/drop-no.gif
new file mode 100644
index 0000000..08d0833
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/dd/drop-no.gif differ
diff --git a/modules/organize/vendor/ext/images/default/dd/drop-yes.gif b/modules/organize/vendor/ext/images/default/dd/drop-yes.gif
new file mode 100644
index 0000000..8aacb30
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/dd/drop-yes.gif differ
diff --git a/modules/organize/vendor/ext/images/default/form/text-bg.gif b/modules/organize/vendor/ext/images/default/form/text-bg.gif
new file mode 100644
index 0000000..4179607
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/form/text-bg.gif differ
diff --git a/modules/organize/vendor/ext/images/default/form/trigger.gif b/modules/organize/vendor/ext/images/default/form/trigger.gif
new file mode 100644
index 0000000..f6cba37
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/form/trigger.gif differ
diff --git a/modules/organize/vendor/ext/images/default/grid/invalid_line.gif b/modules/organize/vendor/ext/images/default/grid/invalid_line.gif
new file mode 100644
index 0000000..fb7e0f3
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/grid/invalid_line.gif differ
diff --git a/modules/organize/vendor/ext/images/default/grid/loading.gif b/modules/organize/vendor/ext/images/default/grid/loading.gif
new file mode 100644
index 0000000..e846e1d
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/grid/loading.gif differ
diff --git a/modules/organize/vendor/ext/images/default/panel/tool-sprites.gif b/modules/organize/vendor/ext/images/default/panel/tool-sprites.gif
new file mode 100644
index 0000000..9a3c5b9
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/panel/tool-sprites.gif differ
diff --git a/modules/organize/vendor/ext/images/default/panel/white-top-bottom.gif b/modules/organize/vendor/ext/images/default/panel/white-top-bottom.gif
new file mode 100644
index 0000000..fe7dd1c
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/panel/white-top-bottom.gif differ
diff --git a/modules/organize/vendor/ext/images/default/progress/progress-bg.gif b/modules/organize/vendor/ext/images/default/progress/progress-bg.gif
new file mode 100644
index 0000000..1c1abeb
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/progress/progress-bg.gif differ
diff --git a/modules/organize/vendor/ext/images/default/qtip/bg.gif b/modules/organize/vendor/ext/images/default/qtip/bg.gif
new file mode 100644
index 0000000..43488af
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/qtip/bg.gif differ
diff --git a/modules/organize/vendor/ext/images/default/s.gif b/modules/organize/vendor/ext/images/default/s.gif
new file mode 100644
index 0000000..1d11fa9
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/s.gif differ
diff --git a/modules/organize/vendor/ext/images/default/shadow-c.png b/modules/organize/vendor/ext/images/default/shadow-c.png
new file mode 100644
index 0000000..d435f80
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/shadow-c.png differ
diff --git a/modules/organize/vendor/ext/images/default/shadow-lr.png b/modules/organize/vendor/ext/images/default/shadow-lr.png
new file mode 100644
index 0000000..bb88b6f
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/shadow-lr.png differ
diff --git a/modules/organize/vendor/ext/images/default/shadow.png b/modules/organize/vendor/ext/images/default/shadow.png
new file mode 100644
index 0000000..75c0eba
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/shadow.png differ
diff --git a/modules/organize/vendor/ext/images/default/toolbar/bg.gif b/modules/organize/vendor/ext/images/default/toolbar/bg.gif
new file mode 100644
index 0000000..0b085bf
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/toolbar/bg.gif differ
diff --git a/modules/organize/vendor/ext/images/default/tree/arrows.gif b/modules/organize/vendor/ext/images/default/tree/arrows.gif
new file mode 100644
index 0000000..2683463
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/tree/arrows.gif differ
diff --git a/modules/organize/vendor/ext/images/default/tree/drop-add.gif b/modules/organize/vendor/ext/images/default/tree/drop-add.gif
new file mode 100644
index 0000000..b22cd14
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/tree/drop-add.gif differ
diff --git a/modules/organize/vendor/ext/images/default/tree/drop-between.gif b/modules/organize/vendor/ext/images/default/tree/drop-between.gif
new file mode 100644
index 0000000..5c6c09d
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/tree/drop-between.gif differ
diff --git a/modules/organize/vendor/ext/images/default/tree/drop-over.gif b/modules/organize/vendor/ext/images/default/tree/drop-over.gif
new file mode 100644
index 0000000..30d1ca7
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/tree/drop-over.gif differ
diff --git a/modules/organize/vendor/ext/images/default/tree/folder-open.gif b/modules/organize/vendor/ext/images/default/tree/folder-open.gif
new file mode 100644
index 0000000..56ba737
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/tree/folder-open.gif differ
diff --git a/modules/organize/vendor/ext/images/default/tree/folder.gif b/modules/organize/vendor/ext/images/default/tree/folder.gif
new file mode 100644
index 0000000..20412f7
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/tree/folder.gif differ
diff --git a/modules/organize/vendor/ext/images/default/tree/loading.gif b/modules/organize/vendor/ext/images/default/tree/loading.gif
new file mode 100644
index 0000000..e846e1d
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/tree/loading.gif differ
diff --git a/modules/organize/vendor/ext/images/default/window/left-corners.png b/modules/organize/vendor/ext/images/default/window/left-corners.png
new file mode 100644
index 0000000..1a51833
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/window/left-corners.png differ
diff --git a/modules/organize/vendor/ext/images/default/window/left-right.png b/modules/organize/vendor/ext/images/default/window/left-right.png
new file mode 100644
index 0000000..7586ff3
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/window/left-right.png differ
diff --git a/modules/organize/vendor/ext/images/default/window/right-corners.png b/modules/organize/vendor/ext/images/default/window/right-corners.png
new file mode 100644
index 0000000..e69a3ff
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/window/right-corners.png differ
diff --git a/modules/organize/vendor/ext/images/default/window/top-bottom.png b/modules/organize/vendor/ext/images/default/window/top-bottom.png
new file mode 100644
index 0000000..33779e7
Binary files /dev/null and b/modules/organize/vendor/ext/images/default/window/top-bottom.png differ
diff --git a/modules/organize/vendor/ext/images/fam/delete.gif b/modules/organize/vendor/ext/images/fam/delete.gif
new file mode 100644
index 0000000..5e2a3b1
Binary files /dev/null and b/modules/organize/vendor/ext/images/fam/delete.gif differ
diff --git a/modules/organize/vendor/ext/js/ext-organize-bundle.js b/modules/organize/vendor/ext/js/ext-organize-bundle.js
new file mode 100644
index 0000000..bf483bd
--- /dev/null
+++ b/modules/organize/vendor/ext/js/ext-organize-bundle.js
@@ -0,0 +1,2202 @@
+
+window.undefined=window.undefined;Ext={version:'3.3.1',versionDetail:{major:3,minor:3,patch:1}};Ext.apply=function(o,c,defaults){if(defaults){Ext.apply(o,defaults);}
+if(o&&c&&typeof c=='object'){for(var p in c){o[p]=c[p];}}
+return o;};(function(){var idSeed=0,toString=Object.prototype.toString,ua=navigator.userAgent.toLowerCase(),check=function(r){return r.test(ua);},DOC=document,docMode=DOC.documentMode,isStrict=DOC.compatMode=="CSS1Compat",isOpera=check(/opera/),isChrome=check(/\bchrome\b/),isWebKit=check(/webkit/),isSafari=!isChrome&&check(/safari/),isSafari2=isSafari&&check(/applewebkit\/4/),isSafari3=isSafari&&check(/version\/3/),isSafari4=isSafari&&check(/version\/4/),isIE=!isOpera&&check(/msie/),isIE7=isIE&&(check(/msie 7/)||docMode==7),isIE8=isIE&&(check(/msie 8/)&&docMode!=7),isIE6=isIE&&!isIE7&&!isIE8,isGecko=!isWebKit&&check(/gecko/),isGecko2=isGecko&&check(/rv:1\.8/),isGecko3=isGecko&&check(/rv:1\.9/),isBorderBox=isIE&&!isStrict,isWindows=check(/windows|win32/),isMac=check(/macintosh|mac os x/),isAir=check(/adobeair/),isLinux=check(/linux/),isSecure=/^https/i.test(window.location.protocol);if(isIE6){try{DOC.execCommand("BackgroundImageCache",false,true);}catch(e){}}
+Ext.apply(Ext,{SSL_SECURE_URL:isSecure&&isIE?'javascript:""':'about:blank',isStrict:isStrict,isSecure:isSecure,isReady:false,enableForcedBoxModel:false,enableGarbageCollector:true,enableListenerCollection:false,enableNestedListenerRemoval:false,USE_NATIVE_JSON:false,applyIf:function(o,c){if(o){for(var p in c){if(!Ext.isDefined(o[p])){o[p]=c[p];}}}
+return o;},id:function(el,prefix){el=Ext.getDom(el,true)||{};if(!el.id){el.id=(prefix||"ext-gen")+(++idSeed);}
+return el.id;},extend:function(){var io=function(o){for(var m in o){this[m]=o[m];}};var oc=Object.prototype.constructor;return function(sb,sp,overrides){if(typeof sp=='object'){overrides=sp;sp=sb;sb=overrides.constructor!=oc?overrides.constructor:function(){sp.apply(this,arguments);};}
+var F=function(){},sbp,spp=sp.prototype;F.prototype=spp;sbp=sb.prototype=new F();sbp.constructor=sb;sb.superclass=spp;if(spp.constructor==oc){spp.constructor=sp;}
+sb.override=function(o){Ext.override(sb,o);};sbp.superclass=sbp.supr=(function(){return spp;});sbp.override=io;Ext.override(sb,overrides);sb.extend=function(o){return Ext.extend(sb,o);};return sb;};}(),override:function(origclass,overrides){if(overrides){var p=origclass.prototype;Ext.apply(p,overrides);if(Ext.isIE&&overrides.hasOwnProperty('toString')){p.toString=overrides.toString;}}},namespace:function(){var o,d;Ext.each(arguments,function(v){d=v.split(".");o=window[d[0]]=window[d[0]]||{};Ext.each(d.slice(1),function(v2){o=o[v2]=o[v2]||{};});});return o;},urlEncode:function(o,pre){var empty,buf=[],e=encodeURIComponent;Ext.iterate(o,function(key,item){empty=Ext.isEmpty(item);Ext.each(empty?key:item,function(val){buf.push('&',e(key),'=',(!Ext.isEmpty(val)&&(val!=key||!empty))?(Ext.isDate(val)?Ext.encode(val).replace(/"/g,''):e(val)):'');});});if(!pre){buf.shift();pre='';}
+return pre+buf.join('');},urlDecode:function(string,overwrite){if(Ext.isEmpty(string)){return{};}
+var obj={},pairs=string.split('&'),d=decodeURIComponent,name,value;Ext.each(pairs,function(pair){pair=pair.split('=');name=d(pair[0]);value=d(pair[1]);obj[name]=overwrite||!obj[name]?value:[].concat(obj[name]).concat(value);});return obj;},urlAppend:function(url,s){if(!Ext.isEmpty(s)){return url+(url.indexOf('?')===-1?'?':'&')+s;}
+return url;},toArray:function(){return isIE?function(a,i,j,res){res=[];for(var x=0,len=a.length;x<len;x++){res.push(a[x]);}
+return res.slice(i||0,j||res.length);}:function(a,i,j){return Array.prototype.slice.call(a,i||0,j||a.length);};}(),isIterable:function(v){if(Ext.isArray(v)||v.callee){return true;}
+if(/NodeList|HTMLCollection/.test(toString.call(v))){return true;}
+return((typeof v.nextNode!='undefined'||v.item)&&Ext.isNumber(v.length));},each:function(array,fn,scope){if(Ext.isEmpty(array,true)){return;}
+if(!Ext.isIterable(array)||Ext.isPrimitive(array)){array=[array];}
+for(var i=0,len=array.length;i<len;i++){if(fn.call(scope||array[i],array[i],i,array)===false){return i;};}},iterate:function(obj,fn,scope){if(Ext.isEmpty(obj)){return;}
+if(Ext.isIterable(obj)){Ext.each(obj,fn,scope);return;}else if(typeof obj=='object'){for(var prop in obj){if(obj.hasOwnProperty(prop)){if(fn.call(scope||obj,prop,obj[prop],obj)===false){return;};}}}},getDom:function(el,strict){if(!el||!DOC){return null;}
+if(el.dom){return el.dom;}else{if(typeof el=='string'){var e=DOC.getElementById(el);if(e&&isIE&&strict){if(el==e.getAttribute('id')){return e;}else{return null;}}
+return e;}else{return el;}}},getBody:function(){return Ext.get(DOC.body||DOC.documentElement);},getHead:function(){var head;return function(){if(head==undefined){head=Ext.get(DOC.getElementsByTagName("head")[0]);}
+return head;};}(),removeNode:isIE&&!isIE8?function(){var d;return function(n){if(n&&n.tagName!='BODY'){(Ext.enableNestedListenerRemoval)?Ext.EventManager.purgeElement(n,true):Ext.EventManager.removeAll(n);d=d||DOC.createElement('div');d.appendChild(n);d.innerHTML='';delete Ext.elCache[n.id];}};}():function(n){if(n&&n.parentNode&&n.tagName!='BODY'){(Ext.enableNestedListenerRemoval)?Ext.EventManager.purgeElement(n,true):Ext.EventManager.removeAll(n);n.parentNode.removeChild(n);delete Ext.elCache[n.id];}},isEmpty:function(v,allowBlank){return v===null||v===undefined||((Ext.isArray(v)&&!v.length))||(!allowBlank?v==='':false);},isArray:function(v){return toString.apply(v)==='[object Array]';},isDate:function(v){return toString.apply(v)==='[object Date]';},isObject:function(v){return!!v&&Object.prototype.toString.call(v)==='[object Object]';},isPrimitive:function(v){return Ext.isString(v)||Ext.isNumber(v)||Ext.isBoolean(v);},isFunction:function(v){return toString.apply(v)==='[object Function]';},isNumber:function(v){return typeof v==='number'&&isFinite(v);},isString:function(v){return typeof v==='string';},isBoolean:function(v){return typeof v==='boolean';},isElement:function(v){return v?!!v.tagName:false;},isDefined:function(v){return typeof v!=='undefined';},isOpera:isOpera,isWebKit:isWebKit,isChrome:isChrome,isSafari:isSafari,isSafari3:isSafari3,isSafari4:isSafari4,isSafari2:isSafari2,isIE:isIE,isIE6:isIE6,isIE7:isIE7,isIE8:isIE8,isGecko:isGecko,isGecko2:isGecko2,isGecko3:isGecko3,isBorderBox:isBorderBox,isLinux:isLinux,isWindows:isWindows,isMac:isMac,isAir:isAir});Ext.ns=Ext.namespace;})();Ext.ns('Ext.util','Ext.lib','Ext.data','Ext.supports');Ext.elCache={};Ext.apply(Function.prototype,{createInterceptor:function(fcn,scope){var method=this;return!Ext.isFunction(fcn)?this:function(){var me=this,args=arguments;fcn.target=me;fcn.method=method;return(fcn.apply(scope||me||window,args)!==false)?method.apply(me||window,args):null;};},createCallback:function(){var args=arguments,method=this;return function(){return method.apply(window,args);};},createDelegate:function(obj,args,appendArgs){var method=this;return function(){var callArgs=args||arguments;if(appendArgs===true){callArgs=Array.prototype.slice.call(arguments,0);callArgs=callArgs.concat(args);}else if(Ext.isNumber(appendArgs)){callArgs=Array.prototype.slice.call(arguments,0);var applyArgs=[appendArgs,0].concat(args);Array.prototype.splice.apply(callArgs,applyArgs);}
+return method.apply(obj||window,callArgs);};},defer:function(millis,obj,args,appendArgs){var fn=this.createDelegate(obj,args,appendArgs);if(millis>0){return setTimeout(fn,millis);}
+fn();return 0;}});Ext.applyIf(String,{format:function(format){var args=Ext.toArray(arguments,1);return format.replace(/\{(\d+)\}/g,function(m,i){return args[i];});}});Ext.applyIf(Array.prototype,{indexOf:function(o,from){var len=this.length;from=from||0;from+=(from<0)?len:0;for(;from<len;++from){if(this[from]===o){return from;}}
+return-1;},remove:function(o){var index=this.indexOf(o);if(index!=-1){this.splice(index,1);}
+return this;}});Ext.util.TaskRunner=function(interval){interval=interval||10;var tasks=[],removeQueue=[],id=0,running=false,stopThread=function(){running=false;clearInterval(id);id=0;},startThread=function(){if(!running){running=true;id=setInterval(runTasks,interval);}},removeTask=function(t){removeQueue.push(t);if(t.onStop){t.onStop.apply(t.scope||t);}},runTasks=function(){var rqLen=removeQueue.length,now=new Date().getTime();if(rqLen>0){for(var i=0;i<rqLen;i++){tasks.remove(removeQueue[i]);}
+removeQueue=[];if(tasks.length<1){stopThread();return;}}
+for(var i=0,t,itime,rt,len=tasks.length;i<len;++i){t=tasks[i];itime=now-t.taskRunTime;if(t.interval<=itime){rt=t.run.apply(t.scope||t,t.args||[++t.taskRunCount]);t.taskRunTime=now;if(rt===false||t.taskRunCount===t.repeat){removeTask(t);return;}}
+if(t.duration&&t.duration<=(now-t.taskStartTime)){removeTask(t);}}};this.start=function(task){tasks.push(task);task.taskStartTime=new Date().getTime();task.taskRunTime=0;task.taskRunCount=0;startThread();return task;};this.stop=function(task){removeTask(task);return task;};this.stopAll=function(){stopThread();for(var i=0,len=tasks.length;i<len;i++){if(tasks[i].onStop){tasks[i].onStop();}}
+tasks=[];removeQueue=[];};};Ext.TaskMgr=new Ext.util.TaskRunner();(function(){var libFlyweight;function fly(el){if(!libFlyweight){libFlyweight=new Ext.Element.Flyweight();}
+libFlyweight.dom=el;return libFlyweight;}
+(function(){var doc=document,isCSS1=doc.compatMode=="CSS1Compat",MAX=Math.max,ROUND=Math.round,PARSEINT=parseInt;Ext.lib.Dom={isAncestor:function(p,c){var ret=false;p=Ext.getDom(p);c=Ext.getDom(c);if(p&&c){if(p.contains){return p.contains(c);}else if(p.compareDocumentPosition){return!!(p.compareDocumentPosition(c)&16);}else{while(c=c.parentNode){ret=c==p||ret;}}}
+return ret;},getViewWidth:function(full){return full?this.getDocumentWidth():this.getViewportWidth();},getViewHeight:function(full){return full?this.getDocumentHeight():this.getViewportHeight();},getDocumentHeight:function(){return MAX(!isCSS1?doc.body.scrollHeight:doc.documentElement.scrollHeight,this.getViewportHeight());},getDocumentWidth:function(){return MAX(!isCSS1?doc.body.scrollWidth:doc.documentElement.scrollWidth,this.getViewportWidth());},getViewportHeight:function(){return Ext.isIE?(Ext.isStrict?doc.documentElement.clientHeight:doc.body.clientHeight):self.innerHeight;},getViewportWidth:function(){return!Ext.isStrict&&!Ext.isOpera?doc.body.clientWidth:Ext.isIE?doc.documentElement.clientWidth:self.innerWidth;},getY:function(el){return this.getXY(el)[1];},getX:function(el){return this.getXY(el)[0];},getXY:function(el){var p,pe,b,bt,bl,dbd,x=0,y=0,scroll,hasAbsolute,bd=(doc.body||doc.documentElement),ret=[0,0];el=Ext.getDom(el);if(el!=bd){if(el.getBoundingClientRect){b=el.getBoundingClientRect();scroll=fly(document).getScroll();ret=[ROUND(b.left+scroll.left),ROUND(b.top+scroll.top)];}else{p=el;hasAbsolute=fly(el).isStyle("position","absolute");while(p){pe=fly(p);x+=p.offsetLeft;y+=p.offsetTop;hasAbsolute=hasAbsolute||pe.isStyle("position","absolute");if(Ext.isGecko){y+=bt=PARSEINT(pe.getStyle("borderTopWidth"),10)||0;x+=bl=PARSEINT(pe.getStyle("borderLeftWidth"),10)||0;if(p!=el&&!pe.isStyle('overflow','visible')){x+=bl;y+=bt;}}
+p=p.offsetParent;}
+if(Ext.isSafari&&hasAbsolute){x-=bd.offsetLeft;y-=bd.offsetTop;}
+if(Ext.isGecko&&!hasAbsolute){dbd=fly(bd);x+=PARSEINT(dbd.getStyle("borderLeftWidth"),10)||0;y+=PARSEINT(dbd.getStyle("borderTopWidth"),10)||0;}
+p=el.parentNode;while(p&&p!=bd){if(!Ext.isOpera||(p.tagName!='TR'&&!fly(p).isStyle("display","inline"))){x-=p.scrollLeft;y-=p.scrollTop;}
+p=p.parentNode;}
+ret=[x,y];}}
+return ret;},setXY:function(el,xy){(el=Ext.fly(el,'_setXY')).position();var pts=el.translatePoints(xy),style=el.dom.style,pos;for(pos in pts){if(!isNaN(pts[pos])){style[pos]=pts[pos]+"px";}}},setX:function(el,x){this.setXY(el,[x,false]);},setY:function(el,y){this.setXY(el,[false,y]);}};})();Ext.lib.Event=function(){var loadComplete=false,unloadListeners={},retryCount=0,onAvailStack=[],_interval,locked=false,win=window,doc=document,POLL_RETRYS=200,POLL_INTERVAL=20,TYPE=0,FN=1,OBJ=2,ADJ_SCOPE=3,SCROLLLEFT='scrollLeft',SCROLLTOP='scrollTop',UNLOAD='unload',MOUSEOVER='mouseover',MOUSEOUT='mouseout',doAdd=function(){var ret;if(win.addEventListener){ret=function(el,eventName,fn,capture){if(eventName=='mouseenter'){fn=fn.createInterceptor(checkRelatedTarget);el.addEventListener(MOUSEOVER,fn,(capture));}else if(eventName=='mouseleave'){fn=fn.createInterceptor(checkRelatedTarget);el.addEventListener(MOUSEOUT,fn,(capture));}else{el.addEventListener(eventName,fn,(capture));}
+return fn;};}else if(win.attachEvent){ret=function(el,eventName,fn,capture){el.attachEvent("on"+eventName,fn);return fn;};}else{ret=function(){};}
+return ret;}(),doRemove=function(){var ret;if(win.removeEventListener){ret=function(el,eventName,fn,capture){if(eventName=='mouseenter'){eventName=MOUSEOVER;}else if(eventName=='mouseleave'){eventName=MOUSEOUT;}
+el.removeEventListener(eventName,fn,(capture));};}else if(win.detachEvent){ret=function(el,eventName,fn){el.detachEvent("on"+eventName,fn);};}else{ret=function(){};}
+return ret;}();function checkRelatedTarget(e){return!elContains(e.currentTarget,pub.getRelatedTarget(e));}
+function elContains(parent,child){if(parent&&parent.firstChild){while(child){if(child===parent){return true;}
+child=child.parentNode;if(child&&(child.nodeType!=1)){child=null;}}}
+return false;}
+function _tryPreloadAttach(){var ret=false,notAvail=[],element,i,v,override,tryAgain=!loadComplete||(retryCount>0);if(!locked){locked=true;for(i=0;i<onAvailStack.length;++i){v=onAvailStack[i];if(v&&(element=doc.getElementById(v.id))){if(!v.checkReady||loadComplete||element.nextSibling||(doc&&doc.body)){override=v.override;element=override?(override===true?v.obj:override):element;v.fn.call(element,v.obj);onAvailStack.remove(v);--i;}else{notAvail.push(v);}}}
+retryCount=(notAvail.length===0)?0:retryCount-1;if(tryAgain){startInterval();}else{clearInterval(_interval);_interval=null;}
+ret=!(locked=false);}
+return ret;}
+function startInterval(){if(!_interval){var callback=function(){_tryPreloadAttach();};_interval=setInterval(callback,POLL_INTERVAL);}}
+function getScroll(){var dd=doc.documentElement,db=doc.body;if(dd&&(dd[SCROLLTOP]||dd[SCROLLLEFT])){return[dd[SCROLLLEFT],dd[SCROLLTOP]];}else if(db){return[db[SCROLLLEFT],db[SCROLLTOP]];}else{return[0,0];}}
+function getPageCoord(ev,xy){ev=ev.browserEvent||ev;var coord=ev['page'+xy];if(!coord&&coord!==0){coord=ev['client'+xy]||0;if(Ext.isIE){coord+=getScroll()[xy=="X"?0:1];}}
+return coord;}
+var pub={extAdapter:true,onAvailable:function(p_id,p_fn,p_obj,p_override){onAvailStack.push({id:p_id,fn:p_fn,obj:p_obj,override:p_override,checkReady:false});retryCount=POLL_RETRYS;startInterval();},addListener:function(el,eventName,fn){el=Ext.getDom(el);if(el&&fn){if(eventName==UNLOAD){if(unloadListeners[el.id]===undefined){unloadListeners[el.id]=[];}
+unloadListeners[el.id].push([eventName,fn]);return fn;}
+return doAdd(el,eventName,fn,false);}
+return false;},removeListener:function(el,eventName,fn){el=Ext.getDom(el);var i,len,li,lis;if(el&&fn){if(eventName==UNLOAD){if((lis=unloadListeners[el.id])!==undefined){for(i=0,len=lis.length;i<len;i++){if((li=lis[i])&&li[TYPE]==eventName&&li[FN]==fn){unloadListeners[el.id].splice(i,1);}}}
+return;}
+doRemove(el,eventName,fn,false);}},getTarget:function(ev){ev=ev.browserEvent||ev;return this.resolveTextNode(ev.target||ev.srcElement);},resolveTextNode:Ext.isGecko?function(node){if(!node){return;}
+var s=HTMLElement.prototype.toString.call(node);if(s=='[xpconnect wrapped native prototype]'||s=='[object XULElement]'){return;}
+return node.nodeType==3?node.parentNode:node;}:function(node){return node&&node.nodeType==3?node.parentNode:node;},getRelatedTarget:function(ev){ev=ev.browserEvent||ev;return this.resolveTextNode(ev.relatedTarget||(/(mouseout|mouseleave)/.test(ev.type)?ev.toElement:/(mouseover|mouseenter)/.test(ev.type)?ev.fromElement:null));},getPageX:function(ev){return getPageCoord(ev,"X");},getPageY:function(ev){return getPageCoord(ev,"Y");},getXY:function(ev){return[this.getPageX(ev),this.getPageY(ev)];},stopEvent:function(ev){this.stopPropagation(ev);this.preventDefault(ev);},stopPropagation:function(ev){ev=ev.browserEvent||ev;if(ev.stopPropagation){ev.stopPropagation();}else{ev.cancelBubble=true;}},preventDefault:function(ev){ev=ev.browserEvent||ev;if(ev.preventDefault){ev.preventDefault();}else{ev.returnValue=false;}},getEvent:function(e){e=e||win.event;if(!e){var c=this.getEvent.caller;while(c){e=c.arguments[0];if(e&&Event==e.constructor){break;}
+c=c.caller;}}
+return e;},getCharCode:function(ev){ev=ev.browserEvent||ev;return ev.charCode||ev.keyCode||0;},getListeners:function(el,eventName){Ext.EventManager.getListeners(el,eventName);},purgeElement:function(el,recurse,eventName){Ext.EventManager.purgeElement(el,recurse,eventName);},_load:function(e){loadComplete=true;if(Ext.isIE&&e!==true){doRemove(win,"load",arguments.callee);}},_unload:function(e){var EU=Ext.lib.Event,i,v,ul,id,len,scope;for(id in unloadListeners){ul=unloadListeners[id];for(i=0,len=ul.length;i<len;i++){v=ul[i];if(v){try{scope=v[ADJ_SCOPE]?(v[ADJ_SCOPE]===true?v[OBJ]:v[ADJ_SCOPE]):win;v[FN].call(scope,EU.getEvent(e),v[OBJ]);}catch(ex){}}}};Ext.EventManager._unload();doRemove(win,UNLOAD,EU._unload);}};pub.on=pub.addListener;pub.un=pub.removeListener;if(doc&&doc.body){pub._load(true);}else{doAdd(win,"load",pub._load);}
+doAdd(win,UNLOAD,pub._unload);_tryPreloadAttach();return pub;}();Ext.lib.Ajax=function(){var activeX=['Msxml2.XMLHTTP.6.0','Msxml2.XMLHTTP.3.0','Msxml2.XMLHTTP'],CONTENTTYPE='Content-Type';function setHeader(o){var conn=o.conn,prop,headers={};function setTheHeaders(conn,headers){for(prop in headers){if(headers.hasOwnProperty(prop)){conn.setRequestHeader(prop,headers[prop]);}}}
+Ext.apply(headers,pub.headers,pub.defaultHeaders);setTheHeaders(conn,headers);delete pub.headers;}
+function createExceptionObject(tId,callbackArg,isAbort,isTimeout){return{tId:tId,status:isAbort?-1:0,statusText:isAbort?'transaction aborted':'communication failure',isAbort:isAbort,isTimeout:isTimeout,argument:callbackArg};}
+function initHeader(label,value){(pub.headers=pub.headers||{})[label]=value;}
+function createResponseObject(o,callbackArg){var headerObj={},headerStr,conn=o.conn,t,s,isBrokenStatus=conn.status==1223;try{headerStr=o.conn.getAllResponseHeaders();Ext.each(headerStr.replace(/\r\n/g,'\n').split('\n'),function(v){t=v.indexOf(':');if(t>=0){s=v.substr(0,t).toLowerCase();if(v.charAt(t+1)==' '){++t;}
+headerObj[s]=v.substr(t+1);}});}catch(e){}
+return{tId:o.tId,status:isBrokenStatus?204:conn.status,statusText:isBrokenStatus?'No Content':conn.statusText,getResponseHeader:function(header){return headerObj[header.toLowerCase()];},getAllResponseHeaders:function(){return headerStr;},responseText:conn.responseText,responseXML:conn.responseXML,argument:callbackArg};}
+function releaseObject(o){if(o.tId){pub.conn[o.tId]=null;}
+o.conn=null;o=null;}
+function handleTransactionResponse(o,callback,isAbort,isTimeout){if(!callback){releaseObject(o);return;}
+var httpStatus,responseObject;try{if(o.conn.status!==undefined&&o.conn.status!=0){httpStatus=o.conn.status;}
+else{httpStatus=13030;}}
+catch(e){httpStatus=13030;}
+if((httpStatus>=200&&httpStatus<300)||(Ext.isIE&&httpStatus==1223)){responseObject=createResponseObject(o,callback.argument);if(callback.success){if(!callback.scope){callback.success(responseObject);}
+else{callback.success.apply(callback.scope,[responseObject]);}}}
+else{switch(httpStatus){case 12002:case 12029:case 12030:case 12031:case 12152:case 13030:responseObject=createExceptionObject(o.tId,callback.argument,(isAbort?isAbort:false),isTimeout);if(callback.failure){if(!callback.scope){callback.failure(responseObject);}
+else{callback.failure.apply(callback.scope,[responseObject]);}}
+break;default:responseObject=createResponseObject(o,callback.argument);if(callback.failure){if(!callback.scope){callback.failure(responseObject);}
+else{callback.failure.apply(callback.scope,[responseObject]);}}}}
+releaseObject(o);responseObject=null;}
+function checkResponse(o,callback,conn,tId,poll,cbTimeout){if(conn&&conn.readyState==4){clearInterval(poll[tId]);poll[tId]=null;if(cbTimeout){clearTimeout(pub.timeout[tId]);pub.timeout[tId]=null;}
+handleTransactionResponse(o,callback);}}
+function checkTimeout(o,callback){pub.abort(o,callback,true);}
+function handleReadyState(o,callback){callback=callback||{};var conn=o.conn,tId=o.tId,poll=pub.poll,cbTimeout=callback.timeout||null;if(cbTimeout){pub.conn[tId]=conn;pub.timeout[tId]=setTimeout(checkTimeout.createCallback(o,callback),cbTimeout);}
+poll[tId]=setInterval(checkResponse.createCallback(o,callback,conn,tId,poll,cbTimeout),pub.pollInterval);}
+function asyncRequest(method,uri,callback,postData){var o=getConnectionObject()||null;if(o){o.conn.open(method,uri,true);if(pub.useDefaultXhrHeader){initHeader('X-Requested-With',pub.defaultXhrHeader);}
+if(postData&&pub.useDefaultHeader&&(!pub.headers||!pub.headers[CONTENTTYPE])){initHeader(CONTENTTYPE,pub.defaultPostHeader);}
+if(pub.defaultHeaders||pub.headers){setHeader(o);}
+handleReadyState(o,callback);o.conn.send(postData||null);}
+return o;}
+function getConnectionObject(){var o;try{if(o=createXhrObject(pub.transactionId)){pub.transactionId++;}}catch(e){}finally{return o;}}
+function createXhrObject(transactionId){var http;try{http=new XMLHttpRequest();}catch(e){for(var i=0;i<activeX.length;++i){try{http=new ActiveXObject(activeX[i]);break;}catch(e){}}}finally{return{conn:http,tId:transactionId};}}
+var pub={request:function(method,uri,cb,data,options){if(options){var me=this,xmlData=options.xmlData,jsonData=options.jsonData,hs;Ext.applyIf(me,options);if(xmlData||jsonData){hs=me.headers;if(!hs||!hs[CONTENTTYPE]){initHeader(CONTENTTYPE,xmlData?'text/xml':'application/json');}
+data=xmlData||(!Ext.isPrimitive(jsonData)?Ext.encode(jsonData):jsonData);}}
+return asyncRequest(method||options.method||"POST",uri,cb,data);},serializeForm:function(form){var fElements=form.elements||(document.forms[form]||Ext.getDom(form)).elements,hasSubmit=false,encoder=encodeURIComponent,name,data='',type,hasValue;Ext.each(fElements,function(element){name=element.name;type=element.type;if(!element.disabled&&name){if(/select-(one|multiple)/i.test(type)){Ext.each(element.options,function(opt){if(opt.selected){hasValue=opt.hasAttribute?opt.hasAttribute('value'):opt.getAttributeNode('value').specified;data+=String.format("{0}={1}&",encoder(name),encoder(hasValue?opt.value:opt.text));}});}else if(!(/file|undefined|reset|button/i.test(type))){if(!(/radio|checkbox/i.test(type)&&!element.checked)&&!(type=='submit'&&hasSubmit)){data+=encoder(name)+'='+encoder(element.value)+'&';hasSubmit=/submit/i.test(type);}}}});return data.substr(0,data.length-1);},useDefaultHeader:true,defaultPostHeader:'application/x-www-form-urlencoded; charset=UTF-8',useDefaultXhrHeader:true,defaultXhrHeader:'XMLHttpRequest',poll:{},timeout:{},conn:{},pollInterval:50,transactionId:0,abort:function(o,callback,isTimeout){var me=this,tId=o.tId,isAbort=false;if(me.isCallInProgress(o)){o.conn.abort();clearInterval(me.poll[tId]);me.poll[tId]=null;clearTimeout(pub.timeout[tId]);me.timeout[tId]=null;handleTransactionResponse(o,callback,(isAbort=true),isTimeout);}
+return isAbort;},isCallInProgress:function(o){return o.conn&&!{0:true,4:true}[o.conn.readyState];}};return pub;}();(function(){var EXTLIB=Ext.lib,noNegatives=/width|height|opacity|padding/i,offsetAttribute=/^((width|height)|(top|left))$/,defaultUnit=/width|height|top$|bottom$|left$|right$/i,offsetUnit=/\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i,isset=function(v){return typeof v!=='undefined';},now=function(){return new Date();};EXTLIB.Anim={motion:function(el,args,duration,easing,cb,scope){return this.run(el,args,duration,easing,cb,scope,Ext.lib.Motion);},run:function(el,args,duration,easing,cb,scope,type){type=type||Ext.lib.AnimBase;if(typeof easing=="string"){easing=Ext.lib.Easing[easing];}
+var anim=new type(el,args,duration,easing);anim.animateX(function(){if(Ext.isFunction(cb)){cb.call(scope);}});return anim;}};EXTLIB.AnimBase=function(el,attributes,duration,method){if(el){this.init(el,attributes,duration,method);}};EXTLIB.AnimBase.prototype={doMethod:function(attr,start,end){var me=this;return me.method(me.curFrame,start,end-start,me.totalFrames);},setAttr:function(attr,val,unit){if(noNegatives.test(attr)&&val<0){val=0;}
+Ext.fly(this.el,'_anim').setStyle(attr,val+unit);},getAttr:function(attr){var el=Ext.fly(this.el),val=el.getStyle(attr),a=offsetAttribute.exec(attr)||[];if(val!=='auto'&&!offsetUnit.test(val)){return parseFloat(val);}
+return(!!(a[2])||(el.getStyle('position')=='absolute'&&!!(a[3])))?el.dom['offset'+a[0].charAt(0).toUpperCase()+a[0].substr(1)]:0;},getDefaultUnit:function(attr){return defaultUnit.test(attr)?'px':'';},animateX:function(callback,scope){var me=this,f=function(){me.onComplete.removeListener(f);if(Ext.isFunction(callback)){callback.call(scope||me,me);}};me.onComplete.addListener(f,me);me.animate();},setRunAttr:function(attr){var me=this,a=this.attributes[attr],to=a.to,by=a.by,from=a.from,unit=a.unit,ra=(this.runAttrs[attr]={}),end;if(!isset(to)&&!isset(by)){return false;}
+var start=isset(from)?from:me.getAttr(attr);if(isset(to)){end=to;}else if(isset(by)){if(Ext.isArray(start)){end=[];for(var i=0,len=start.length;i<len;i++){end[i]=start[i]+by[i];}}else{end=start+by;}}
+Ext.apply(ra,{start:start,end:end,unit:isset(unit)?unit:me.getDefaultUnit(attr)});},init:function(el,attributes,duration,method){var me=this,actualFrames=0,mgr=EXTLIB.AnimMgr;Ext.apply(me,{isAnimated:false,startTime:null,el:Ext.getDom(el),attributes:attributes||{},duration:duration||1,method:method||EXTLIB.Easing.easeNone,useSec:true,curFrame:0,totalFrames:mgr.fps,runAttrs:{},animate:function(){var me=this,d=me.duration;if(me.isAnimated){return false;}
+me.curFrame=0;me.totalFrames=me.useSec?Math.ceil(mgr.fps*d):d;mgr.registerElement(me);},stop:function(finish){var me=this;if(finish){me.curFrame=me.totalFrames;me._onTween.fire();}
+mgr.stop(me);}});var onStart=function(){var me=this,attr;me.onStart.fire();me.runAttrs={};for(attr in this.attributes){this.setRunAttr(attr);}
+me.isAnimated=true;me.startTime=now();actualFrames=0;};var onTween=function(){var me=this;me.onTween.fire({duration:now()-me.startTime,curFrame:me.curFrame});var ra=me.runAttrs;for(var attr in ra){this.setAttr(attr,me.doMethod(attr,ra[attr].start,ra[attr].end),ra[attr].unit);}
+++actualFrames;};var onComplete=function(){var me=this,actual=(now()-me.startTime)/1000,data={duration:actual,frames:actualFrames,fps:actualFrames/actual};me.isAnimated=false;actualFrames=0;me.onComplete.fire(data);};me.onStart=new Ext.util.Event(me);me.onTween=new Ext.util.Event(me);me.onComplete=new Ext.util.Event(me);(me._onStart=new Ext.util.Event(me)).addListener(onStart);(me._onTween=new Ext.util.Event(me)).addListener(onTween);(me._onComplete=new Ext.util.Event(me)).addListener(onComplete);}};Ext.lib.AnimMgr=new function(){var me=this,thread=null,queue=[],tweenCount=0;Ext.apply(me,{fps:1000,delay:1,registerElement:function(tween){queue.push(tween);++tweenCount;tween._onStart.fire();me.start();},unRegister:function(tween,index){tween._onComplete.fire();index=index||getIndex(tween);if(index!=-1){queue.splice(index,1);}
+if(--tweenCount<=0){me.stop();}},start:function(){if(thread===null){thread=setInterval(me.run,me.delay);}},stop:function(tween){if(!tween){clearInterval(thread);for(var i=0,len=queue.length;i<len;++i){if(queue[0].isAnimated){me.unRegister(queue[0],0);}}
+queue=[];thread=null;tweenCount=0;}else{me.unRegister(tween);}},run:function(){var tf,i,len,tween;for(i=0,len=queue.length;i<len;i++){tween=queue[i];if(tween&&tween.isAnimated){tf=tween.totalFrames;if(tween.curFrame<tf||tf===null){++tween.curFrame;if(tween.useSec){correctFrame(tween);}
+tween._onTween.fire();}else{me.stop(tween);}}}}});var getIndex=function(anim){var i,len;for(i=0,len=queue.length;i<len;i++){if(queue[i]===anim){return i;}}
+return-1;};var correctFrame=function(tween){var frames=tween.totalFrames,frame=tween.curFrame,duration=tween.duration,expected=(frame*duration*1000/frames),elapsed=(now()-tween.startTime),tweak=0;if(elapsed<duration*1000){tweak=Math.round((elapsed/expected-1)*frame);}else{tweak=frames-(frame+1);}
+if(tweak>0&&isFinite(tweak)){if(tween.curFrame+tweak>=frames){tweak=frames-(frame+1);}
+tween.curFrame+=tweak;}};};EXTLIB.Bezier=new function(){this.getPosition=function(points,t){var n=points.length,tmp=[],c=1-t,i,j;for(i=0;i<n;++i){tmp[i]=[points[i][0],points[i][1]];}
+for(j=1;j<n;++j){for(i=0;i<n-j;++i){tmp[i][0]=c*tmp[i][0]+t*tmp[parseInt(i+1,10)][0];tmp[i][1]=c*tmp[i][1]+t*tmp[parseInt(i+1,10)][1];}}
+return[tmp[0][0],tmp[0][1]];};};EXTLIB.Easing={easeNone:function(t,b,c,d){return c*t/d+b;},easeIn:function(t,b,c,d){return c*(t/=d)*t+b;},easeOut:function(t,b,c,d){return-c*(t/=d)*(t-2)+b;}};(function(){EXTLIB.Motion=function(el,attributes,duration,method){if(el){EXTLIB.Motion.superclass.constructor.call(this,el,attributes,duration,method);}};Ext.extend(EXTLIB.Motion,Ext.lib.AnimBase);var superclass=EXTLIB.Motion.superclass,pointsRe=/^points$/i;Ext.apply(EXTLIB.Motion.prototype,{setAttr:function(attr,val,unit){var me=this,setAttr=superclass.setAttr;if(pointsRe.test(attr)){unit=unit||'px';setAttr.call(me,'left',val[0],unit);setAttr.call(me,'top',val[1],unit);}else{setAttr.call(me,attr,val,unit);}},getAttr:function(attr){var me=this,getAttr=superclass.getAttr;return pointsRe.test(attr)?[getAttr.call(me,'left'),getAttr.call(me,'top')]:getAttr.call(me,attr);},doMethod:function(attr,start,end){var me=this;return pointsRe.test(attr)?EXTLIB.Bezier.getPosition(me.runAttrs[attr],me.method(me.curFrame,0,100,me.totalFrames)/100):superclass.doMethod.call(me,attr,start,end);},setRunAttr:function(attr){if(pointsRe.test(attr)){var me=this,el=this.el,points=this.attributes.points,control=points.control||[],from=points.from,to=points.to,by=points.by,DOM=EXTLIB.Dom,start,i,end,len,ra;if(control.length>0&&!Ext.isArray(control[0])){control=[control];}else{}
+Ext.fly(el,'_anim').position();DOM.setXY(el,isset(from)?from:DOM.getXY(el));start=me.getAttr('points');if(isset(to)){end=translateValues.call(me,to,start);for(i=0,len=control.length;i<len;++i){control[i]=translateValues.call(me,control[i],start);}}else if(isset(by)){end=[start[0]+by[0],start[1]+by[1]];for(i=0,len=control.length;i<len;++i){control[i]=[start[0]+control[i][0],start[1]+control[i][1]];}}
+ra=this.runAttrs[attr]=[start];if(control.length>0){ra=ra.concat(control);}
+ra[ra.length]=end;}else{superclass.setRunAttr.call(this,attr);}}});var translateValues=function(val,start){var pageXY=EXTLIB.Dom.getXY(this.el);return[val[0]-pageXY[0]+start[0],val[1]-pageXY[1]+start[1]];};})();})();(function(){var abs=Math.abs,pi=Math.PI,asin=Math.asin,pow=Math.pow,sin=Math.sin,EXTLIB=Ext.lib;Ext.apply(EXTLIB.Easing,{easeBoth:function(t,b,c,d){return((t/=d/2)<1)?c/2*t*t+b:-c/2*((--t)*(t-2)-1)+b;},easeInStrong:function(t,b,c,d){return c*(t/=d)*t*t*t+b;},easeOutStrong:function(t,b,c,d){return-c*((t=t/d-1)*t*t*t-1)+b;},easeBothStrong:function(t,b,c,d){return((t/=d/2)<1)?c/2*t*t*t*t+b:-c/2*((t-=2)*t*t*t-2)+b;},elasticIn:function(t,b,c,d,a,p){if(t==0||(t/=d)==1){return t==0?b:b+c;}
+p=p||(d*.3);var s;if(a>=abs(c)){s=p/(2*pi)*asin(c/a);}else{a=c;s=p/4;}
+return-(a*pow(2,10*(t-=1))*sin((t*d-s)*(2*pi)/p))+b;},elasticOut:function(t,b,c,d,a,p){if(t==0||(t/=d)==1){return t==0?b:b+c;}
+p=p||(d*.3);var s;if(a>=abs(c)){s=p/(2*pi)*asin(c/a);}else{a=c;s=p/4;}
+return a*pow(2,-10*t)*sin((t*d-s)*(2*pi)/p)+c+b;},elasticBoth:function(t,b,c,d,a,p){if(t==0||(t/=d/2)==2){return t==0?b:b+c;}
+p=p||(d*(.3*1.5));var s;if(a>=abs(c)){s=p/(2*pi)*asin(c/a);}else{a=c;s=p/4;}
+return t<1?-.5*(a*pow(2,10*(t-=1))*sin((t*d-s)*(2*pi)/p))+b:a*pow(2,-10*(t-=1))*sin((t*d-s)*(2*pi)/p)*.5+c+b;},backIn:function(t,b,c,d,s){s=s||1.70158;return c*(t/=d)*t*((s+1)*t-s)+b;},backOut:function(t,b,c,d,s){if(!s){s=1.70158;}
+return c*((t=t/d-1)*t*((s+1)*t+s)+1)+b;},backBoth:function(t,b,c,d,s){s=s||1.70158;return((t/=d/2)<1)?c/2*(t*t*(((s*=(1.525))+1)*t-s))+b:c/2*((t-=2)*t*(((s*=(1.525))+1)*t+s)+2)+b;},bounceIn:function(t,b,c,d){return c-EXTLIB.Easing.bounceOut(d-t,0,c,d)+b;},bounceOut:function(t,b,c,d){if((t/=d)<(1/2.75)){return c*(7.5625*t*t)+b;}else if(t<(2/2.75)){return c*(7.5625*(t-=(1.5/2.75))*t+.75)+b;}else if(t<(2.5/2.75)){return c*(7.5625*(t-=(2.25/2.75))*t+.9375)+b;}
+return c*(7.5625*(t-=(2.625/2.75))*t+.984375)+b;},bounceBoth:function(t,b,c,d){return(t<d/2)?EXTLIB.Easing.bounceIn(t*2,0,c,d)*.5+b:EXTLIB.Easing.bounceOut(t*2-d,0,c,d)*.5+c*.5+b;}});})();(function(){var EXTLIB=Ext.lib;EXTLIB.Anim.color=function(el,args,duration,easing,cb,scope){return EXTLIB.Anim.run(el,args,duration,easing,cb,scope,EXTLIB.ColorAnim);};EXTLIB.ColorAnim=function(el,attributes,duration,method){EXTLIB.ColorAnim.superclass.constructor.call(this,el,attributes,duration,method);};Ext.extend(EXTLIB.ColorAnim,EXTLIB.AnimBase);var superclass=EXTLIB.ColorAnim.superclass,colorRE=/color$/i,transparentRE=/^transparent|rgba\(0, 0, 0, 0\)$/,rgbRE=/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,hexRE=/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,hex3RE=/^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i,isset=function(v){return typeof v!=='undefined';};function parseColor(s){var pi=parseInt,base,out=null,c;if(s.length==3){return s;}
+Ext.each([hexRE,rgbRE,hex3RE],function(re,idx){base=(idx%2==0)?16:10;c=re.exec(s);if(c&&c.length==4){out=[pi(c[1],base),pi(c[2],base),pi(c[3],base)];return false;}});return out;}
+Ext.apply(EXTLIB.ColorAnim.prototype,{getAttr:function(attr){var me=this,el=me.el,val;if(colorRE.test(attr)){while(el&&transparentRE.test(val=Ext.fly(el).getStyle(attr))){el=el.parentNode;val="fff";}}else{val=superclass.getAttr.call(me,attr);}
+return val;},doMethod:function(attr,start,end){var me=this,val,floor=Math.floor,i,len,v;if(colorRE.test(attr)){val=[];end=end||[];for(i=0,len=start.length;i<len;i++){v=start[i];val[i]=superclass.doMethod.call(me,attr,v,end[i]);}
+val='rgb('+floor(val[0])+','+floor(val[1])+','+floor(val[2])+')';}else{val=superclass.doMethod.call(me,attr,start,end);}
+return val;},setRunAttr:function(attr){var me=this,a=me.attributes[attr],to=a.to,by=a.by,ra;superclass.setRunAttr.call(me,attr);ra=me.runAttrs[attr];if(colorRE.test(attr)){var start=parseColor(ra.start),end=parseColor(ra.end);if(!isset(to)&&isset(by)){end=parseColor(by);for(var i=0,len=start.length;i<len;i++){end[i]=start[i]+end[i];}}
+ra.start=start;ra.end=end;}}});})();(function(){var EXTLIB=Ext.lib;EXTLIB.Anim.scroll=function(el,args,duration,easing,cb,scope){return EXTLIB.Anim.run(el,args,duration,easing,cb,scope,EXTLIB.Scroll);};EXTLIB.Scroll=function(el,attributes,duration,method){if(el){EXTLIB.Scroll.superclass.constructor.call(this,el,attributes,duration,method);}};Ext.extend(EXTLIB.Scroll,EXTLIB.ColorAnim);var superclass=EXTLIB.Scroll.superclass,SCROLL='scroll';Ext.apply(EXTLIB.Scroll.prototype,{doMethod:function(attr,start,end){var val,me=this,curFrame=me.curFrame,totalFrames=me.totalFrames;if(attr==SCROLL){val=[me.method(curFrame,start[0],end[0]-start[0],totalFrames),me.method(curFrame,start[1],end[1]-start[1],totalFrames)];}else{val=superclass.doMethod.call(me,attr,start,end);}
+return val;},getAttr:function(attr){var me=this;if(attr==SCROLL){return[me.el.scrollLeft,me.el.scrollTop];}else{return superclass.getAttr.call(me,attr);}},setAttr:function(attr,val,unit){var me=this;if(attr==SCROLL){me.el.scrollLeft=val[0];me.el.scrollTop=val[1];}else{superclass.setAttr.call(me,attr,val,unit);}}});})();if(Ext.isIE){function fnCleanUp(){var p=Function.prototype;delete p.createSequence;delete p.defer;delete p.createDelegate;delete p.createCallback;delete p.createInterceptor;window.detachEvent("onunload",fnCleanUp);}
+window.attachEvent("onunload",fnCleanUp);}})();(function(){var EXTUTIL=Ext.util,EACH=Ext.each,TRUE=true,FALSE=false;EXTUTIL.Observable=function(){var me=this,e=me.events;if(me.listeners){me.on(me.listeners);delete me.listeners;}
+me.events=e||{};};EXTUTIL.Observable.prototype={filterOptRe:/^(?:scope|delay|buffer|single)$/,fireEvent:function(){var a=Array.prototype.slice.call(arguments,0),ename=a[0].toLowerCase(),me=this,ret=TRUE,ce=me.events[ename],cc,q,c;if(me.eventsSuspended===TRUE){if(q=me.eventQueue){q.push(a);}}
+else if(typeof ce=='object'){if(ce.bubble){if(ce.fire.apply(ce,a.slice(1))===FALSE){return FALSE;}
+c=me.getBubbleTarget&&me.getBubbleTarget();if(c&&c.enableBubble){cc=c.events[ename];if(!cc||typeof cc!='object'||!cc.bubble){c.enableBubble(ename);}
+return c.fireEvent.apply(c,a);}}
+else{a.shift();ret=ce.fire.apply(ce,a);}}
+return ret;},addListener:function(eventName,fn,scope,o){var me=this,e,oe,ce;if(typeof eventName=='object'){o=eventName;for(e in o){oe=o[e];if(!me.filterOptRe.test(e)){me.addListener(e,oe.fn||oe,oe.scope||o.scope,oe.fn?oe:o);}}}else{eventName=eventName.toLowerCase();ce=me.events[eventName]||TRUE;if(typeof ce=='boolean'){me.events[eventName]=ce=new EXTUTIL.Event(me,eventName);}
+ce.addListener(fn,scope,typeof o=='object'?o:{});}},removeListener:function(eventName,fn,scope){var ce=this.events[eventName.toLowerCase()];if(typeof ce=='object'){ce.removeListener(fn,scope);}},purgeListeners:function(){var events=this.events,evt,key;for(key in events){evt=events[key];if(typeof evt=='object'){evt.clearListeners();}}},addEvents:function(o){var me=this;me.events=me.events||{};if(typeof o=='string'){var a=arguments,i=a.length;while(i--){me.events[a[i]]=me.events[a[i]]||TRUE;}}else{Ext.applyIf(me.events,o);}},hasListener:function(eventName){var e=this.events[eventName.toLowerCase()];return typeof e=='object'&&e.listeners.length>0;},suspendEvents:function(queueSuspended){this.eventsSuspended=TRUE;if(queueSuspended&&!this.eventQueue){this.eventQueue=[];}},resumeEvents:function(){var me=this,queued=me.eventQueue||[];me.eventsSuspended=FALSE;delete me.eventQueue;EACH(queued,function(e){me.fireEvent.apply(me,e);});}};var OBSERVABLE=EXTUTIL.Observable.prototype;OBSERVABLE.on=OBSERVABLE.addListener;OBSERVABLE.un=OBSERVABLE.removeListener;EXTUTIL.Observable.releaseCapture=function(o){o.fireEvent=OBSERVABLE.fireEvent;};function createTargeted(h,o,scope){return function(){if(o.target==arguments[0]){h.apply(scope,Array.prototype.slice.call(arguments,0));}};};function createBuffered(h,o,l,scope){l.task=new EXTUTIL.DelayedTask();return function(){l.task.delay(o.buffer,h,scope,Array.prototype.slice.call(arguments,0));};};function createSingle(h,e,fn,scope){return function(){e.removeListener(fn,scope);return h.apply(scope,arguments);};};function createDelayed(h,o,l,scope){return function(){var task=new EXTUTIL.DelayedTask(),args=Array.prototype.slice.call(arguments,0);if(!l.tasks){l.tasks=[];}
+l.tasks.push(task);task.delay(o.delay||10,function(){l.tasks.remove(task);h.apply(scope,args);},scope);};};EXTUTIL.Event=function(obj,name){this.name=name;this.obj=obj;this.listeners=[];};EXTUTIL.Event.prototype={addListener:function(fn,scope,options){var me=this,l;scope=scope||me.obj;if(!me.isListening(fn,scope)){l=me.createListener(fn,scope,options);if(me.firing){me.listeners=me.listeners.slice(0);}
+me.listeners.push(l);}},createListener:function(fn,scope,o){o=o||{};scope=scope||this.obj;var l={fn:fn,scope:scope,options:o},h=fn;if(o.target){h=createTargeted(h,o,scope);}
+if(o.delay){h=createDelayed(h,o,l,scope);}
+if(o.single){h=createSingle(h,this,fn,scope);}
+if(o.buffer){h=createBuffered(h,o,l,scope);}
+l.fireFn=h;return l;},findListener:function(fn,scope){var list=this.listeners,i=list.length,l;scope=scope||this.obj;while(i--){l=list[i];if(l){if(l.fn==fn&&l.scope==scope){return i;}}}
+return-1;},isListening:function(fn,scope){return this.findListener(fn,scope)!=-1;},removeListener:function(fn,scope){var index,l,k,me=this,ret=FALSE;if((index=me.findListener(fn,scope))!=-1){if(me.firing){me.listeners=me.listeners.slice(0);}
+l=me.listeners[index];if(l.task){l.task.cancel();delete l.task;}
+k=l.tasks&&l.tasks.length;if(k){while(k--){l.tasks[k].cancel();}
+delete l.tasks;}
+me.listeners.splice(index,1);ret=TRUE;}
+return ret;},clearListeners:function(){var me=this,l=me.listeners,i=l.length;while(i--){me.removeListener(l[i].fn,l[i].scope);}},fire:function(){var me=this,listeners=me.listeners,len=listeners.length,i=0,l;if(len>0){me.firing=TRUE;var args=Array.prototype.slice.call(arguments,0);for(;i<len;i++){l=listeners[i];if(l&&l.fireFn.apply(l.scope||me.obj||window,args)===FALSE){return(me.firing=FALSE);}}}
+me.firing=FALSE;return TRUE;}};})();Ext.DomHelper=function(){var tempTableEl=null,emptyTags=/^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,tableRe=/^table|tbody|tr|td$/i,confRe=/tag|children|cn|html$/i,tableElRe=/td|tr|tbody/i,cssRe=/([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,endRe=/end/i,pub,afterbegin='afterbegin',afterend='afterend',beforebegin='beforebegin',beforeend='beforeend',ts='<table>',te='</table>',tbs=ts+'<tbody>',tbe='</tbody>'+te,trs=tbs+'<tr>',tre='</tr>'+tbe;function doInsert(el,o,returnElement,pos,sibling,append){var newNode=pub.insertHtml(pos,Ext.getDom(el),createHtml(o));return returnElement?Ext.get(newNode,true):newNode;}
+function createHtml(o){var b='',attr,val,key,cn;if(typeof o=="string"){b=o;}else if(Ext.isArray(o)){for(var i=0;i<o.length;i++){if(o[i]){b+=createHtml(o[i]);}};}else{b+='<'+(o.tag=o.tag||'div');for(attr in o){val=o[attr];if(!confRe.test(attr)){if(typeof val=="object"){b+=' '+attr+'="';for(key in val){b+=key+':'+val[key]+';';};b+='"';}else{b+=' '+({cls:'class',htmlFor:'for'}[attr]||attr)+'="'+val+'"';}}};if(emptyTags.test(o.tag)){b+='/>';}else{b+='>';if((cn=o.children||o.cn)){b+=createHtml(cn);}else if(o.html){b+=o.html;}
+b+='</'+o.tag+'>';}}
+return b;}
+function ieTable(depth,s,h,e){tempTableEl.innerHTML=[s,h,e].join('');var i=-1,el=tempTableEl,ns;while(++i<depth){el=el.firstChild;}
+if(ns=el.nextSibling){var df=document.createDocumentFragment();while(el){ns=el.nextSibling;df.appendChild(el);el=ns;}
+el=df;}
+return el;}
+function insertIntoTable(tag,where,el,html){var node,before;tempTableEl=tempTableEl||document.createElement('div');if(tag=='td'&&(where==afterbegin||where==beforeend)||!tableElRe.test(tag)&&(where==beforebegin||where==afterend)){return;}
+before=where==beforebegin?el:where==afterend?el.nextSibling:where==afterbegin?el.firstChild:null;if(where==beforebegin||where==afterend){el=el.parentNode;}
+if(tag=='td'||(tag=='tr'&&(where==beforeend||where==afterbegin))){node=ieTable(4,trs,html,tre);}else if((tag=='tbody'&&(where==beforeend||where==afterbegin))||(tag=='tr'&&(where==beforebegin||where==afterend))){node=ieTable(3,tbs,html,tbe);}else{node=ieTable(2,ts,html,te);}
+el.insertBefore(node,before);return node;}
+pub={markup:function(o){return createHtml(o);},applyStyles:function(el,styles){if(styles){var matches;el=Ext.fly(el);if(typeof styles=="function"){styles=styles.call();}
+if(typeof styles=="string"){cssRe.lastIndex=0;while((matches=cssRe.exec(styles))){el.setStyle(matches[1],matches[2]);}}else if(typeof styles=="object"){el.setStyle(styles);}}},insertHtml:function(where,el,html){var hash={},hashVal,setStart,range,frag,rangeEl,rs;where=where.toLowerCase();hash[beforebegin]=['BeforeBegin','previousSibling'];hash[afterend]=['AfterEnd','nextSibling'];if(el.insertAdjacentHTML){if(tableRe.test(el.tagName)&&(rs=insertIntoTable(el.tagName.toLowerCase(),where,el,html))){return rs;}
+hash[afterbegin]=['AfterBegin','firstChild'];hash[beforeend]=['BeforeEnd','lastChild'];if((hashVal=hash[where])){el.insertAdjacentHTML(hashVal[0],html);return el[hashVal[1]];}}else{range=el.ownerDocument.createRange();setStart='setStart'+(endRe.test(where)?'After':'Before');if(hash[where]){range[setStart](el);frag=range.createContextualFragment(html);el.parentNode.insertBefore(frag,where==beforebegin?el:el.nextSibling);return el[(where==beforebegin?'previous':'next')+'Sibling'];}else{rangeEl=(where==afterbegin?'first':'last')+'Child';if(el.firstChild){range[setStart](el[rangeEl]);frag=range.createContextualFragment(html);if(where==afterbegin){el.insertBefore(frag,el.firstChild);}else{el.appendChild(frag);}}else{el.innerHTML=html;}
+return el[rangeEl];}}
+throw'Illegal insertion point -> "'+where+'"';},insertBefore:function(el,o,returnElement){return doInsert(el,o,returnElement,beforebegin);},insertAfter:function(el,o,returnElement){return doInsert(el,o,returnElement,afterend,'nextSibling');},insertFirst:function(el,o,returnElement){return doInsert(el,o,returnElement,afterbegin,'firstChild');},append:function(el,o,returnElement){return doInsert(el,o,returnElement,beforeend,'',true);},overwrite:function(el,o,returnElement){el=Ext.getDom(el);el.innerHTML=createHtml(o);return returnElement?Ext.get(el.firstChild):el.firstChild;},createHtml:createHtml};return pub;}();Ext.Template=function(html){var me=this,a=arguments,buf=[],v;if(Ext.isArray(html)){html=html.join("");}else if(a.length>1){for(var i=0,len=a.length;i<len;i++){v=a[i];if(typeof v=='object'){Ext.apply(me,v);}else{buf.push(v);}};html=buf.join('');}
+me.html=html;if(me.compiled){me.compile();}};Ext.Template.prototype={re:/\{([\w-]+)\}/g,applyTemplate:function(values){var me=this;return me.compiled?me.compiled(values):me.html.replace(me.re,function(m,name){return values[name]!==undefined?values[name]:"";});},set:function(html,compile){var me=this;me.html=html;me.compiled=null;return compile?me.compile():me;},compile:function(){var me=this,sep=Ext.isGecko?"+":",";function fn(m,name){name="values['"+name+"']";return"'"+sep+'('+name+" == undefined ? '' : "+name+')'+sep+"'";}
+eval("this.compiled = function(values){ return "+(Ext.isGecko?"'":"['")+
+me.html.replace(/\\/g,'\\\\').replace(/(\r\n|\n)/g,'\\n').replace(/'/g,"\\'").replace(this.re,fn)+
+(Ext.isGecko?"';};":"'].join('');};"));return me;},insertFirst:function(el,values,returnElement){return this.doInsert('afterBegin',el,values,returnElement);},insertBefore:function(el,values,returnElement){return this.doInsert('beforeBegin',el,values,returnElement);},insertAfter:function(el,values,returnElement){return this.doInsert('afterEnd',el,values,returnElement);},append:function(el,values,returnElement){return this.doInsert('beforeEnd',el,values,returnElement);},doInsert:function(where,el,values,returnEl){el=Ext.getDom(el);var newNode=Ext.DomHelper.insertHtml(where,el,this.applyTemplate(values));return returnEl?Ext.get(newNode,true):newNode;},overwrite:function(el,values,returnElement){el=Ext.getDom(el);el.innerHTML=this.applyTemplate(values);return returnElement?Ext.get(el.firstChild,true):el.firstChild;}};Ext.Template.prototype.apply=Ext.Template.prototype.applyTemplate;Ext.Template.from=function(el,config){el=Ext.getDom(el);return new Ext.Template(el.value||el.innerHTML,config||'');};Ext.DomQuery=function(){var cache={},simpleCache={},valueCache={},nonSpace=/\S/,trimRe=/^\s+|\s+$/g,tplRe=/\{(\d+)\}/g,modeRe=/^(\s?[\/>+~]\s?|\s|$)/,tagTokenRe=/^(#)?([\w-\*]+)/,nthRe=/(\d*)n\+?(\d*)/,nthRe2=/\D/,isIE=window.ActiveXObject?true:false,key=30803;eval("var batch = 30803;");function child(parent,index){var i=0,n=parent.firstChild;while(n){if(n.nodeType==1){if(++i==index){return n;}}
+n=n.nextSibling;}
+return null;}
+function next(n){while((n=n.nextSibling)&&n.nodeType!=1);return n;}
+function prev(n){while((n=n.previousSibling)&&n.nodeType!=1);return n;}
+function children(parent){var n=parent.firstChild,nodeIndex=-1,nextNode;while(n){nextNode=n.nextSibling;if(n.nodeType==3&&!nonSpace.test(n.nodeValue)){parent.removeChild(n);}else{n.nodeIndex=++nodeIndex;}
+n=nextNode;}
+return this;}
+function byClassName(nodeSet,cls){if(!cls){return nodeSet;}
+var result=[],ri=-1;for(var i=0,ci;ci=nodeSet[i];i++){if((' '+ci.className+' ').indexOf(cls)!=-1){result[++ri]=ci;}}
+return result;};function attrValue(n,attr){if(!n.tagName&&typeof n.length!="undefined"){n=n[0];}
+if(!n){return null;}
+if(attr=="for"){return n.htmlFor;}
+if(attr=="class"||attr=="className"){return n.className;}
+return n.getAttribute(attr)||n[attr];};function getNodes(ns,mode,tagName){var result=[],ri=-1,cs;if(!ns){return result;}
+tagName=tagName||"*";if(typeof ns.getElementsByTagName!="undefined"){ns=[ns];}
+if(!mode){for(var i=0,ni;ni=ns[i];i++){cs=ni.getElementsByTagName(tagName);for(var j=0,ci;ci=cs[j];j++){result[++ri]=ci;}}}else if(mode=="/"||mode==">"){var utag=tagName.toUpperCase();for(var i=0,ni,cn;ni=ns[i];i++){cn=ni.childNodes;for(var j=0,cj;cj=cn[j];j++){if(cj.nodeName==utag||cj.nodeName==tagName||tagName=='*'){result[++ri]=cj;}}}}else if(mode=="+"){var utag=tagName.toUpperCase();for(var i=0,n;n=ns[i];i++){while((n=n.nextSibling)&&n.nodeType!=1);if(n&&(n.nodeName==utag||n.nodeName==tagName||tagName=='*')){result[++ri]=n;}}}else if(mode=="~"){var utag=tagName.toUpperCase();for(var i=0,n;n=ns[i];i++){while((n=n.nextSibling)){if(n.nodeName==utag||n.nodeName==tagName||tagName=='*'){result[++ri]=n;}}}}
+return result;}
+function concat(a,b){if(b.slice){return a.concat(b);}
+for(var i=0,l=b.length;i<l;i++){a[a.length]=b[i];}
+return a;}
+function byTag(cs,tagName){if(cs.tagName||cs==document){cs=[cs];}
+if(!tagName){return cs;}
+var result=[],ri=-1;tagName=tagName.toLowerCase();for(var i=0,ci;ci=cs[i];i++){if(ci.nodeType==1&&ci.tagName.toLowerCase()==tagName){result[++ri]=ci;}}
+return result;}
+function byId(cs,id){if(cs.tagName||cs==document){cs=[cs];}
+if(!id){return cs;}
+var result=[],ri=-1;for(var i=0,ci;ci=cs[i];i++){if(ci&&ci.id==id){result[++ri]=ci;return result;}}
+return result;}
+function byAttribute(cs,attr,value,op,custom){var result=[],ri=-1,useGetStyle=custom=="{",fn=Ext.DomQuery.operators[op],a,xml,hasXml;for(var i=0,ci;ci=cs[i];i++){if(ci.nodeType!=1){continue;}
+if(!hasXml){xml=Ext.DomQuery.isXml(ci);hasXml=true;}
+if(!xml){if(useGetStyle){a=Ext.DomQuery.getStyle(ci,attr);}else if(attr=="class"||attr=="className"){a=ci.className;}else if(attr=="for"){a=ci.htmlFor;}else if(attr=="href"){a=ci.getAttribute("href",2);}else{a=ci.getAttribute(attr);}}else{a=ci.getAttribute(attr);}
+if((fn&&fn(a,value))||(!fn&&a)){result[++ri]=ci;}}
+return result;}
+function byPseudo(cs,name,value){return Ext.DomQuery.pseudos[name](cs,value);}
+function nodupIEXml(cs){var d=++key,r;cs[0].setAttribute("_nodup",d);r=[cs[0]];for(var i=1,len=cs.length;i<len;i++){var c=cs[i];if(!c.getAttribute("_nodup")!=d){c.setAttribute("_nodup",d);r[r.length]=c;}}
+for(var i=0,len=cs.length;i<len;i++){cs[i].removeAttribute("_nodup");}
+return r;}
+function nodup(cs){if(!cs){return[];}
+var len=cs.length,c,i,r=cs,cj,ri=-1;if(!len||typeof cs.nodeType!="undefined"||len==1){return cs;}
+if(isIE&&typeof cs[0].selectSingleNode!="undefined"){return nodupIEXml(cs);}
+var d=++key;cs[0]._nodup=d;for(i=1;c=cs[i];i++){if(c._nodup!=d){c._nodup=d;}else{r=[];for(var j=0;j<i;j++){r[++ri]=cs[j];}
+for(j=i+1;cj=cs[j];j++){if(cj._nodup!=d){cj._nodup=d;r[++ri]=cj;}}
+return r;}}
+return r;}
+function quickDiffIEXml(c1,c2){var d=++key,r=[];for(var i=0,len=c1.length;i<len;i++){c1[i].setAttribute("_qdiff",d);}
+for(var i=0,len=c2.length;i<len;i++){if(c2[i].getAttribute("_qdiff")!=d){r[r.length]=c2[i];}}
+for(var i=0,len=c1.length;i<len;i++){c1[i].removeAttribute("_qdiff");}
+return r;}
+function quickDiff(c1,c2){var len1=c1.length,d=++key,r=[];if(!len1){return c2;}
+if(isIE&&typeof c1[0].selectSingleNode!="undefined"){return quickDiffIEXml(c1,c2);}
+for(var i=0;i<len1;i++){c1[i]._qdiff=d;}
+for(var i=0,len=c2.length;i<len;i++){if(c2[i]._qdiff!=d){r[r.length]=c2[i];}}
+return r;}
+function quickId(ns,mode,root,id){if(ns==root){var d=root.ownerDocument||root;return d.getElementById(id);}
+ns=getNodes(ns,mode,"*");return byId(ns,id);}
+return{getStyle:function(el,name){return Ext.fly(el).getStyle(name);},compile:function(path,type){type=type||"select";var fn=["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],mode,lastPath,matchers=Ext.DomQuery.matchers,matchersLn=matchers.length,modeMatch,lmode=path.match(modeRe);if(lmode&&lmode[1]){fn[fn.length]='mode="'+lmode[1].replace(trimRe,"")+'";';path=path.replace(lmode[1],"");}
+while(path.substr(0,1)=="/"){path=path.substr(1);}
+while(path&&lastPath!=path){lastPath=path;var tokenMatch=path.match(tagTokenRe);if(type=="select"){if(tokenMatch){if(tokenMatch[1]=="#"){fn[fn.length]='n = quickId(n, mode, root, "'+tokenMatch[2]+'");';}else{fn[fn.length]='n = getNodes(n, mode, "'+tokenMatch[2]+'");';}
+path=path.replace(tokenMatch[0],"");}else if(path.substr(0,1)!='@'){fn[fn.length]='n = getNodes(n, mode, "*");';}}else{if(tokenMatch){if(tokenMatch[1]=="#"){fn[fn.length]='n = byId(n, "'+tokenMatch[2]+'");';}else{fn[fn.length]='n = byTag(n, "'+tokenMatch[2]+'");';}
+path=path.replace(tokenMatch[0],"");}}
+while(!(modeMatch=path.match(modeRe))){var matched=false;for(var j=0;j<matchersLn;j++){var t=matchers[j];var m=path.match(t.re);if(m){fn[fn.length]=t.select.replace(tplRe,function(x,i){return m[i];});path=path.replace(m[0],"");matched=true;break;}}
+if(!matched){throw'Error parsing selector, parsing failed at "'+path+'"';}}
+if(modeMatch[1]){fn[fn.length]='mode="'+modeMatch[1].replace(trimRe,"")+'";';path=path.replace(modeMatch[1],"");}}
+fn[fn.length]="return nodup(n);\n}";eval(fn.join(""));return f;},jsSelect:function(path,root,type){root=root||document;if(typeof root=="string"){root=document.getElementById(root);}
+var paths=path.split(","),results=[];for(var i=0,len=paths.length;i<len;i++){var subPath=paths[i].replace(trimRe,"");if(!cache[subPath]){cache[subPath]=Ext.DomQuery.compile(subPath);if(!cache[subPath]){throw subPath+" is not a valid selector";}}
+var result=cache[subPath](root);if(result&&result!=document){results=results.concat(result);}}
+if(paths.length>1){return nodup(results);}
+return results;},isXml:function(el){var docEl=(el?el.ownerDocument||el:0).documentElement;return docEl?docEl.nodeName!=="HTML":false;},select:document.querySelectorAll?function(path,root,type){root=root||document;if(!Ext.DomQuery.isXml(root)){try{var cs=root.querySelectorAll(path);return Ext.toArray(cs);}
+catch(ex){}}
+return Ext.DomQuery.jsSelect.call(this,path,root,type);}:function(path,root,type){return Ext.DomQuery.jsSelect.call(this,path,root,type);},selectNode:function(path,root){return Ext.DomQuery.select(path,root)[0];},selectValue:function(path,root,defaultValue){path=path.replace(trimRe,"");if(!valueCache[path]){valueCache[path]=Ext.DomQuery.compile(path,"select");}
+var n=valueCache[path](root),v;n=n[0]?n[0]:n;if(typeof n.normalize=='function')n.normalize();v=(n&&n.firstChild?n.firstChild.nodeValue:null);return((v===null||v===undefined||v==='')?defaultValue:v);},selectNumber:function(path,root,defaultValue){var v=Ext.DomQuery.selectValue(path,root,defaultValue||0);return parseFloat(v);},is:function(el,ss){if(typeof el=="string"){el=document.getElementById(el);}
+var isArray=Ext.isArray(el),result=Ext.DomQuery.filter(isArray?el:[el],ss);return isArray?(result.length==el.length):(result.length>0);},filter:function(els,ss,nonMatches){ss=ss.replace(trimRe,"");if(!simpleCache[ss]){simpleCache[ss]=Ext.DomQuery.compile(ss,"simple");}
+var result=simpleCache[ss](els);return nonMatches?quickDiff(result,els):result;},matchers:[{re:/^\.([\w-]+)/,select:'n = byClassName(n, " {1} ");'},{re:/^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,select:'n = byPseudo(n, "{1}", "{2}");'},{re:/^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,select:'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'},{re:/^#([\w-]+)/,select:'n = byId(n, "{1}");'},{re:/^@([\w-]+)/,select:'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'}],operators:{"=":function(a,v){return a==v;},"!=":function(a,v){return a!=v;},"^=":function(a,v){return a&&a.substr(0,v.length)==v;},"$=":function(a,v){return a&&a.substr(a.length-v.length)==v;},"*=":function(a,v){return a&&a.indexOf(v)!==-1;},"%=":function(a,v){return(a%v)==0;},"|=":function(a,v){return a&&(a==v||a.substr(0,v.length+1)==v+'-');},"~=":function(a,v){return a&&(' '+a+' ').indexOf(' '+v+' ')!=-1;}},pseudos:{"first-child":function(c){var r=[],ri=-1,n;for(var i=0,ci;ci=n=c[i];i++){while((n=n.previousSibling)&&n.nodeType!=1);if(!n){r[++ri]=ci;}}
+return r;},"last-child":function(c){var r=[],ri=-1,n;for(var i=0,ci;ci=n=c[i];i++){while((n=n.nextSibling)&&n.nodeType!=1);if(!n){r[++ri]=ci;}}
+return r;},"nth-child":function(c,a){var r=[],ri=-1,m=nthRe.exec(a=="even"&&"2n"||a=="odd"&&"2n+1"||!nthRe2.test(a)&&"n+"+a||a),f=(m[1]||1)-0,l=m[2]-0;for(var i=0,n;n=c[i];i++){var pn=n.parentNode;if(batch!=pn._batch){var j=0;for(var cn=pn.firstChild;cn;cn=cn.nextSibling){if(cn.nodeType==1){cn.nodeIndex=++j;}}
+pn._batch=batch;}
+if(f==1){if(l==0||n.nodeIndex==l){r[++ri]=n;}}else if((n.nodeIndex+l)%f==0){r[++ri]=n;}}
+return r;},"only-child":function(c){var r=[],ri=-1;;for(var i=0,ci;ci=c[i];i++){if(!prev(ci)&&!next(ci)){r[++ri]=ci;}}
+return r;},"empty":function(c){var r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){var cns=ci.childNodes,j=0,cn,empty=true;while(cn=cns[j]){++j;if(cn.nodeType==1||cn.nodeType==3){empty=false;break;}}
+if(empty){r[++ri]=ci;}}
+return r;},"contains":function(c,v){var r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){if((ci.textContent||ci.innerText||'').indexOf(v)!=-1){r[++ri]=ci;}}
+return r;},"nodeValue":function(c,v){var r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){if(ci.firstChild&&ci.firstChild.nodeValue==v){r[++ri]=ci;}}
+return r;},"checked":function(c){var r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){if(ci.checked==true){r[++ri]=ci;}}
+return r;},"not":function(c,ss){return Ext.DomQuery.filter(c,ss,true);},"any":function(c,selectors){var ss=selectors.split('|'),r=[],ri=-1,s;for(var i=0,ci;ci=c[i];i++){for(var j=0;s=ss[j];j++){if(Ext.DomQuery.is(ci,s)){r[++ri]=ci;break;}}}
+return r;},"odd":function(c){return this["nth-child"](c,"odd");},"even":function(c){return this["nth-child"](c,"even");},"nth":function(c,a){return c[a-1]||[];},"first":function(c){return c[0]||[];},"last":function(c){return c[c.length-1]||[];},"has":function(c,ss){var s=Ext.DomQuery.select,r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){if(s(ss,ci).length>0){r[++ri]=ci;}}
+return r;},"next":function(c,ss){var is=Ext.DomQuery.is,r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){var n=next(ci);if(n&&is(n,ss)){r[++ri]=ci;}}
+return r;},"prev":function(c,ss){var is=Ext.DomQuery.is,r=[],ri=-1;for(var i=0,ci;ci=c[i];i++){var n=prev(ci);if(n&&is(n,ss)){r[++ri]=ci;}}
+return r;}}};}();Ext.query=Ext.DomQuery.select;Ext.util.DelayedTask=function(fn,scope,args){var me=this,id,call=function(){clearInterval(id);id=null;fn.apply(scope,args||[]);};me.delay=function(delay,newFn,newScope,newArgs){me.cancel();fn=newFn||fn;scope=newScope||scope;args=newArgs||args;id=setInterval(call,delay);};me.cancel=function(){if(id){clearInterval(id);id=null;}};};(function(){var DOC=document;Ext.Element=function(element,forceNew){var dom=typeof element=="string"?DOC.getElementById(element):element,id;if(!dom)return null;id=dom.id;if(!forceNew&&id&&Ext.elCache[id]){return Ext.elCache[id].el;}
+this.dom=dom;this.id=id||Ext.id(dom);};var DH=Ext.DomHelper,El=Ext.Element,EC=Ext.elCache;El.prototype={set:function(o,useSet){var el=this.dom,attr,val,useSet=(useSet!==false)&&!!el.setAttribute;for(attr in o){if(o.hasOwnProperty(attr)){val=o[attr];if(attr=='style'){DH.applyStyles(el,val);}else if(attr=='cls'){el.className=val;}else if(useSet){el.setAttribute(attr,val);}else{el[attr]=val;}}}
+return this;},defaultUnit:"px",is:function(simpleSelector){return Ext.DomQuery.is(this.dom,simpleSelector);},focus:function(defer,dom){var me=this,dom=dom||me.dom;try{if(Number(defer)){me.focus.defer(defer,null,[null,dom]);}else{dom.focus();}}catch(e){}
+return me;},blur:function(){try{this.dom.blur();}catch(e){}
+return this;},getValue:function(asNumber){var val=this.dom.value;return asNumber?parseInt(val,10):val;},addListener:function(eventName,fn,scope,options){Ext.EventManager.on(this.dom,eventName,fn,scope||this,options);return this;},removeListener:function(eventName,fn,scope){Ext.EventManager.removeListener(this.dom,eventName,fn,scope||this);return this;},removeAllListeners:function(){Ext.EventManager.removeAll(this.dom);return this;},purgeAllListeners:function(){Ext.EventManager.purgeElement(this,true);return this;},addUnits:function(size){if(size===""||size=="auto"||size===undefined){size=size||'';}else if(!isNaN(size)||!unitPattern.test(size)){size=size+(this.defaultUnit||'px');}
+return size;},load:function(url,params,cb){Ext.Ajax.request(Ext.apply({params:params,url:url.url||url,callback:cb,el:this.dom,indicatorText:url.indicatorText||''},Ext.isObject(url)?url:{}));return this;},isBorderBox:function(){return Ext.isBorderBox||Ext.isForcedBorderBox||noBoxAdjust[(this.dom.tagName||"").toLowerCase()];},remove:function(){var me=this,dom=me.dom;if(dom){delete me.dom;Ext.removeNode(dom);}},hover:function(overFn,outFn,scope,options){var me=this;me.on('mouseenter',overFn,scope||me.dom,options);me.on('mouseleave',outFn,scope||me.dom,options);return me;},contains:function(el){return!el?false:Ext.lib.Dom.isAncestor(this.dom,el.dom?el.dom:el);},getAttributeNS:function(ns,name){return this.getAttribute(name,ns);},getAttribute:Ext.isIE?function(name,ns){var d=this.dom,type=typeof d[ns+":"+name];if(['undefined','unknown'].indexOf(type)==-1){return d[ns+":"+name];}
+return d[name];}:function(name,ns){var d=this.dom;return d.getAttributeNS(ns,name)||d.getAttribute(ns+":"+name)||d.getAttribute(name)||d[name];},update:function(html){if(this.dom){this.dom.innerHTML=html;}
+return this;}};var ep=El.prototype;El.addMethods=function(o){Ext.apply(ep,o);};ep.on=ep.addListener;ep.un=ep.removeListener;ep.autoBoxAdjust=true;var unitPattern=/\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,docEl;El.get=function(el){var ex,elm,id;if(!el){return null;}
+if(typeof el=="string"){if(!(elm=DOC.getElementById(el))){return null;}
+if(EC[el]&&EC[el].el){ex=EC[el].el;ex.dom=elm;}else{ex=El.addToCache(new El(elm));}
+return ex;}else if(el.tagName){if(!(id=el.id)){id=Ext.id(el);}
+if(EC[id]&&EC[id].el){ex=EC[id].el;ex.dom=el;}else{ex=El.addToCache(new El(el));}
+return ex;}else if(el instanceof El){if(el!=docEl){if(Ext.isIE&&(el.id==undefined||el.id=='')){el.dom=el.dom;}else{el.dom=DOC.getElementById(el.id)||el.dom;}}
+return el;}else if(el.isComposite){return el;}else if(Ext.isArray(el)){return El.select(el);}else if(el==DOC){if(!docEl){var f=function(){};f.prototype=El.prototype;docEl=new f();docEl.dom=DOC;}
+return docEl;}
+return null;};El.addToCache=function(el,id){id=id||el.id;EC[id]={el:el,data:{},events:{}};return el;};El.data=function(el,key,value){el=El.get(el);if(!el){return null;}
+var c=EC[el.id].data;if(arguments.length==2){return c[key];}else{return(c[key]=value);}};function garbageCollect(){if(!Ext.enableGarbageCollector){clearInterval(El.collectorThreadId);}else{var eid,el,d,o;for(eid in EC){o=EC[eid];if(o.skipGC){continue;}
+el=o.el;d=el.dom;if(!d||!d.parentNode||(!d.offsetParent&&!DOC.getElementById(eid))){if(Ext.enableListenerCollection){Ext.EventManager.removeAll(d);}
+delete EC[eid];}}
+if(Ext.isIE){var t={};for(eid in EC){t[eid]=EC[eid];}
+EC=Ext.elCache=t;}}}
+El.collectorThreadId=setInterval(garbageCollect,30000);var flyFn=function(){};flyFn.prototype=El.prototype;El.Flyweight=function(dom){this.dom=dom;};El.Flyweight.prototype=new flyFn();El.Flyweight.prototype.isFlyweight=true;El._flyweights={};El.fly=function(el,named){var ret=null;named=named||'_global';if(el=Ext.getDom(el)){(El._flyweights[named]=El._flyweights[named]||new El.Flyweight()).dom=el;ret=El._flyweights[named];}
+return ret;};Ext.get=El.get;Ext.fly=El.fly;var noBoxAdjust=Ext.isStrict?{select:1}:{input:1,select:1,textarea:1};if(Ext.isIE||Ext.isGecko){noBoxAdjust['button']=1;}})();Ext.Element.addMethods(function(){var PARENTNODE='parentNode',NEXTSIBLING='nextSibling',PREVIOUSSIBLING='previousSibling',DQ=Ext.DomQuery,GET=Ext.get;return{findParent:function(simpleSelector,maxDepth,returnEl){var p=this.dom,b=document.body,depth=0,stopEl;if(Ext.isGecko&&Object.prototype.toString.call(p)=='[object XULElement]'){return null;}
+maxDepth=maxDepth||50;if(isNaN(maxDepth)){stopEl=Ext.getDom(maxDepth);maxDepth=Number.MAX_VALUE;}
+while(p&&p.nodeType==1&&depth<maxDepth&&p!=b&&p!=stopEl){if(DQ.is(p,simpleSelector)){return returnEl?GET(p):p;}
+depth++;p=p.parentNode;}
+return null;},findParentNode:function(simpleSelector,maxDepth,returnEl){var p=Ext.fly(this.dom.parentNode,'_internal');return p?p.findParent(simpleSelector,maxDepth,returnEl):null;},up:function(simpleSelector,maxDepth){return this.findParentNode(simpleSelector,maxDepth,true);},select:function(selector){return Ext.Element.select(selector,this.dom);},query:function(selector){return DQ.select(selector,this.dom);},child:function(selector,returnDom){var n=DQ.selectNode(selector,this.dom);return returnDom?n:GET(n);},down:function(selector,returnDom){var n=DQ.selectNode(" > "+selector,this.dom);return returnDom?n:GET(n);},parent:function(selector,returnDom){return this.matchNode(PARENTNODE,PARENTNODE,selector,returnDom);},next:function(selector,returnDom){return this.matchNode(NEXTSIBLING,NEXTSIBLING,selector,returnDom);},prev:function(selector,returnDom){return this.matchNode(PREVIOUSSIBLING,PREVIOUSSIBLING,selector,returnDom);},first:function(selector,returnDom){return this.matchNode(NEXTSIBLING,'firstChild',selector,returnDom);},last:function(selector,returnDom){return this.matchNode(PREVIOUSSIBLING,'lastChild',selector,returnDom);},matchNode:function(dir,start,selector,returnDom){var n=this.dom[start];while(n){if(n.nodeType==1&&(!selector||DQ.is(n,selector))){return!returnDom?GET(n):n;}
+n=n[dir];}
+return null;}};}());Ext.Element.addMethods(function(){var GETDOM=Ext.getDom,GET=Ext.get,DH=Ext.DomHelper;return{appendChild:function(el){return GET(el).appendTo(this);},appendTo:function(el){GETDOM(el).appendChild(this.dom);return this;},insertBefore:function(el){(el=GETDOM(el)).parentNode.insertBefore(this.dom,el);return this;},insertAfter:function(el){(el=GETDOM(el)).parentNode.insertBefore(this.dom,el.nextSibling);return this;},insertFirst:function(el,returnDom){el=el||{};if(el.nodeType||el.dom||typeof el=='string'){el=GETDOM(el);this.dom.insertBefore(el,this.dom.firstChild);return!returnDom?GET(el):el;}else{return this.createChild(el,this.dom.firstChild,returnDom);}},replace:function(el){el=GET(el);this.insertBefore(el);el.remove();return this;},replaceWith:function(el){var me=this;if(el.nodeType||el.dom||typeof el=='string'){el=GETDOM(el);me.dom.parentNode.insertBefore(el,me.dom);}else{el=DH.insertBefore(me.dom,el);}
+delete Ext.elCache[me.id];Ext.removeNode(me.dom);me.id=Ext.id(me.dom=el);Ext.Element.addToCache(me.isFlyweight?new Ext.Element(me.dom):me);return me;},createChild:function(config,insertBefore,returnDom){config=config||{tag:'div'};return insertBefore?DH.insertBefore(insertBefore,config,returnDom!==true):DH[!this.dom.firstChild?'overwrite':'append'](this.dom,config,returnDom!==true);},wrap:function(config,returnDom){var newEl=DH.insertBefore(this.dom,config||{tag:"div"},!returnDom);newEl.dom?newEl.dom.appendChild(this.dom):newEl.appendChild(this.dom);return newEl;},insertHtml:function(where,html,returnEl){var el=DH.insertHtml(where,this.dom,html);return returnEl?Ext.get(el):el;}};}());Ext.Element.addMethods(function(){var supports=Ext.supports,propCache={},camelRe=/(-[a-z])/gi,view=document.defaultView,opacityRe=/alpha\(opacity=(.*)\)/i,trimRe=/^\s+|\s+$/g,EL=Ext.Element,spacesRe=/\s+/,wordsRe=/\w/g,PADDING="padding",MARGIN="margin",BORDER="border",LEFT="-left",RIGHT="-right",TOP="-top",BOTTOM="-bottom",WIDTH="-width",MATH=Math,HIDDEN='hidden',ISCLIPPED='isClipped',OVERFLOW='overflow',OVERFLOWX='overflow-x',OVERFLOWY='overflow-y',ORIGINALCLIP='originalClip',borders={l:BORDER+LEFT+WIDTH,r:BORDER+RIGHT+WIDTH,t:BORDER+TOP+WIDTH,b:BORDER+BOTTOM+WIDTH},paddings={l:PADDING+LEFT,r:PADDING+RIGHT,t:PADDING+TOP,b:PADDING+BOTTOM},margins={l:MARGIN+LEFT,r:MARGIN+RIGHT,t:MARGIN+TOP,b:MARGIN+BOTTOM},data=Ext.Element.data;function camelFn(m,a){return a.charAt(1).toUpperCase();}
+function chkCache(prop){return propCache[prop]||(propCache[prop]=prop=='float'?(supports.cssFloat?'cssFloat':'styleFloat'):prop.replace(camelRe,camelFn));}
+return{adjustWidth:function(width){var me=this;var isNum=(typeof width=="number");if(isNum&&me.autoBoxAdjust&&!me.isBorderBox()){width-=(me.getBorderWidth("lr")+me.getPadding("lr"));}
+return(isNum&&width<0)?0:width;},adjustHeight:function(height){var me=this;var isNum=(typeof height=="number");if(isNum&&me.autoBoxAdjust&&!me.isBorderBox()){height-=(me.getBorderWidth("tb")+me.getPadding("tb"));}
+return(isNum&&height<0)?0:height;},addClass:function(className){var me=this,i,len,v,cls=[];if(!Ext.isArray(className)){if(typeof className=='string'&&!this.hasClass(className)){me.dom.className+=" "+className;}}
+else{for(i=0,len=className.length;i<len;i++){v=className[i];if(typeof v=='string'&&(' '+me.dom.className+' ').indexOf(' '+v+' ')==-1){cls.push(v);}}
+if(cls.length){me.dom.className+=" "+cls.join(" ");}}
+return me;},removeClass:function(className){var me=this,i,idx,len,cls,elClasses;if(!Ext.isArray(className)){className=[className];}
+if(me.dom&&me.dom.className){elClasses=me.dom.className.replace(trimRe,'').split(spacesRe);for(i=0,len=className.length;i<len;i++){cls=className[i];if(typeof cls=='string'){cls=cls.replace(trimRe,'');idx=elClasses.indexOf(cls);if(idx!=-1){elClasses.splice(idx,1);}}}
+me.dom.className=elClasses.join(" ");}
+return me;},radioClass:function(className){var cn=this.dom.parentNode.childNodes,v,i,len;className=Ext.isArray(className)?className:[className];for(i=0,len=cn.length;i<len;i++){v=cn[i];if(v&&v.nodeType==1){Ext.fly(v,'_internal').removeClass(className);}};return this.addClass(className);},toggleClass:function(className){return this.hasClass(className)?this.removeClass(className):this.addClass(className);},hasClass:function(className){return className&&(' '+this.dom.className+' ').indexOf(' '+className+' ')!=-1;},replaceClass:function(oldClassName,newClassName){return this.removeClass(oldClassName).addClass(newClassName);},isStyle:function(style,val){return this.getStyle(style)==val;},getStyle:function(){return view&&view.getComputedStyle?function(prop){var el=this.dom,v,cs,out,display;if(el==document){return null;}
+prop=chkCache(prop);out=(v=el.style[prop])?v:(cs=view.getComputedStyle(el,""))?cs[prop]:null;if(prop=='marginRight'&&out!='0px'&&!supports.correctRightMargin){display=el.style.display;el.style.display='inline-block';out=view.getComputedStyle(el,'').marginRight;el.style.display=display;}
+if(prop=='backgroundColor'&&out=='rgba(0, 0, 0, 0)'&&!supports.correctTransparentColor){out='transparent';}
+return out;}:function(prop){var el=this.dom,m,cs;if(el==document)return null;if(prop=='opacity'){if(el.style.filter.match){if(m=el.style.filter.match(opacityRe)){var fv=parseFloat(m[1]);if(!isNaN(fv)){return fv?fv/100:0;}}}
+return 1;}
+prop=chkCache(prop);return el.style[prop]||((cs=el.currentStyle)?cs[prop]:null);};}(),getColor:function(attr,defaultValue,prefix){var v=this.getStyle(attr),color=(typeof prefix!='undefined')?prefix:'#',h;if(!v||(/transparent|inherit/.test(v))){return defaultValue;}
+if(/^r/.test(v)){Ext.each(v.slice(4,v.length-1).split(','),function(s){h=parseInt(s,10);color+=(h<16?'0':'')+h.toString(16);});}else{v=v.replace('#','');color+=v.length==3?v.replace(/^(\w)(\w)(\w)$/,'$1$1$2$2$3$3'):v;}
+return(color.length>5?color.toLowerCase():defaultValue);},setStyle:function(prop,value){var tmp,style;if(typeof prop!='object'){tmp={};tmp[prop]=value;prop=tmp;}
+for(style in prop){value=prop[style];style=='opacity'?this.setOpacity(value):this.dom.style[chkCache(style)]=value;}
+return this;},setOpacity:function(opacity,animate){var me=this,s=me.dom.style;if(!animate||!me.anim){if(Ext.isIE){var opac=opacity<1?'alpha(opacity='+opacity*100+')':'',val=s.filter.replace(opacityRe,'').replace(trimRe,'');s.zoom=1;s.filter=val+(val.length>0?' ':'')+opac;}else{s.opacity=opacity;}}else{me.anim({opacity:{to:opacity}},me.preanim(arguments,1),null,.35,'easeIn');}
+return me;},clearOpacity:function(){var style=this.dom.style;if(Ext.isIE){if(!Ext.isEmpty(style.filter)){style.filter=style.filter.replace(opacityRe,'').replace(trimRe,'');}}else{style.opacity=style['-moz-opacity']=style['-khtml-opacity']='';}
+return this;},getHeight:function(contentHeight){var me=this,dom=me.dom,hidden=Ext.isIE&&me.isStyle('display','none'),h=MATH.max(dom.offsetHeight,hidden?0:dom.clientHeight)||0;h=!contentHeight?h:h-me.getBorderWidth("tb")-me.getPadding("tb");return h<0?0:h;},getWidth:function(contentWidth){var me=this,dom=me.dom,hidden=Ext.isIE&&me.isStyle('display','none'),w=MATH.max(dom.offsetWidth,hidden?0:dom.clientWidth)||0;w=!contentWidth?w:w-me.getBorderWidth("lr")-me.getPadding("lr");return w<0?0:w;},setWidth:function(width,animate){var me=this;width=me.adjustWidth(width);!animate||!me.anim?me.dom.style.width=me.addUnits(width):me.anim({width:{to:width}},me.preanim(arguments,1));return me;},setHeight:function(height,animate){var me=this;height=me.adjustHeight(height);!animate||!me.anim?me.dom.style.height=me.addUnits(height):me.anim({height:{to:height}},me.preanim(arguments,1));return me;},getBorderWidth:function(side){return this.addStyles(side,borders);},getPadding:function(side){return this.addStyles(side,paddings);},clip:function(){var me=this,dom=me.dom;if(!data(dom,ISCLIPPED)){data(dom,ISCLIPPED,true);data(dom,ORIGINALCLIP,{o:me.getStyle(OVERFLOW),x:me.getStyle(OVERFLOWX),y:me.getStyle(OVERFLOWY)});me.setStyle(OVERFLOW,HIDDEN);me.setStyle(OVERFLOWX,HIDDEN);me.setStyle(OVERFLOWY,HIDDEN);}
+return me;},unclip:function(){var me=this,dom=me.dom;if(data(dom,ISCLIPPED)){data(dom,ISCLIPPED,false);var o=data(dom,ORIGINALCLIP);if(o.o){me.setStyle(OVERFLOW,o.o);}
+if(o.x){me.setStyle(OVERFLOWX,o.x);}
+if(o.y){me.setStyle(OVERFLOWY,o.y);}}
+return me;},addStyles:function(sides,styles){var ttlSize=0,sidesArr=sides.match(wordsRe),side,size,i,len=sidesArr.length;for(i=0;i<len;i++){side=sidesArr[i];size=side&&parseInt(this.getStyle(styles[side]),10);if(size){ttlSize+=MATH.abs(size);}}
+return ttlSize;},margins:margins};}());(function(){var D=Ext.lib.Dom,LEFT="left",RIGHT="right",TOP="top",BOTTOM="bottom",POSITION="position",STATIC="static",RELATIVE="relative",AUTO="auto",ZINDEX="z-index";Ext.Element.addMethods({getX:function(){return D.getX(this.dom);},getY:function(){return D.getY(this.dom);},getXY:function(){return D.getXY(this.dom);},getOffsetsTo:function(el){var o=this.getXY(),e=Ext.fly(el,'_internal').getXY();return[o[0]-e[0],o[1]-e[1]];},setX:function(x,animate){return this.setXY([x,this.getY()],this.animTest(arguments,animate,1));},setY:function(y,animate){return this.setXY([this.getX(),y],this.animTest(arguments,animate,1));},setLeft:function(left){this.setStyle(LEFT,this.addUnits(left));return this;},setTop:function(top){this.setStyle(TOP,this.addUnits(top));return this;},setRight:function(right){this.setStyle(RIGHT,this.addUnits(right));return this;},setBottom:function(bottom){this.setStyle(BOTTOM,this.addUnits(bottom));return this;},setXY:function(pos,animate){var me=this;if(!animate||!me.anim){D.setXY(me.dom,pos);}else{me.anim({points:{to:pos}},me.preanim(arguments,1),'motion');}
+return me;},setLocation:function(x,y,animate){return this.setXY([x,y],this.animTest(arguments,animate,2));},moveTo:function(x,y,animate){return this.setXY([x,y],this.animTest(arguments,animate,2));},getLeft:function(local){return!local?this.getX():parseInt(this.getStyle(LEFT),10)||0;},getRight:function(local){var me=this;return!local?me.getX()+me.getWidth():(me.getLeft(true)+me.getWidth())||0;},getTop:function(local){return!local?this.getY():parseInt(this.getStyle(TOP),10)||0;},getBottom:function(local){var me=this;return!local?me.getY()+me.getHeight():(me.getTop(true)+me.getHeight())||0;},position:function(pos,zIndex,x,y){var me=this;if(!pos&&me.isStyle(POSITION,STATIC)){me.setStyle(POSITION,RELATIVE);}else if(pos){me.setStyle(POSITION,pos);}
+if(zIndex){me.setStyle(ZINDEX,zIndex);}
+if(x||y)me.setXY([x||false,y||false]);},clearPositioning:function(value){value=value||'';this.setStyle({left:value,right:value,top:value,bottom:value,"z-index":"",position:STATIC});return this;},getPositioning:function(){var l=this.getStyle(LEFT);var t=this.getStyle(TOP);return{"position":this.getStyle(POSITION),"left":l,"right":l?"":this.getStyle(RIGHT),"top":t,"bottom":t?"":this.getStyle(BOTTOM),"z-index":this.getStyle(ZINDEX)};},setPositioning:function(pc){var me=this,style=me.dom.style;me.setStyle(pc);if(pc.right==AUTO){style.right="";}
+if(pc.bottom==AUTO){style.bottom="";}
+return me;},translatePoints:function(x,y){y=isNaN(x[1])?y:x[1];x=isNaN(x[0])?x:x[0];var me=this,relative=me.isStyle(POSITION,RELATIVE),o=me.getXY(),l=parseInt(me.getStyle(LEFT),10),t=parseInt(me.getStyle(TOP),10);l=!isNaN(l)?l:(relative?0:me.dom.offsetLeft);t=!isNaN(t)?t:(relative?0:me.dom.offsetTop);return{left:(x-o[0]+l),top:(y-o[1]+t)};},animTest:function(args,animate,i){return!!animate&&this.preanim?this.preanim(args,i):false;}});})();Ext.Element.addMethods({isScrollable:function(){var dom=this.dom;return dom.scrollHeight>dom.clientHeight||dom.scrollWidth>dom.clientWidth;},scrollTo:function(side,value){this.dom["scroll"+(/top/i.test(side)?"Top":"Left")]=value;return this;},getScroll:function(){var d=this.dom,doc=document,body=doc.body,docElement=doc.documentElement,l,t,ret;if(d==doc||d==body){if(Ext.isIE&&Ext.isStrict){l=docElement.scrollLeft;t=docElement.scrollTop;}else{l=window.pageXOffset;t=window.pageYOffset;}
+ret={left:l||(body?body.scrollLeft:0),top:t||(body?body.scrollTop:0)};}else{ret={left:d.scrollLeft,top:d.scrollTop};}
+return ret;}});Ext.Element.VISIBILITY=1;Ext.Element.DISPLAY=2;Ext.Element.OFFSETS=3;Ext.Element.ASCLASS=4;Ext.Element.visibilityCls='x-hide-nosize';Ext.Element.addMethods(function(){var El=Ext.Element,OPACITY="opacity",VISIBILITY="visibility",DISPLAY="display",HIDDEN="hidden",OFFSETS="offsets",ASCLASS="asclass",NONE="none",NOSIZE='nosize',ORIGINALDISPLAY='originalDisplay',VISMODE='visibilityMode',ISVISIBLE='isVisible',data=El.data,getDisplay=function(dom){var d=data(dom,ORIGINALDISPLAY);if(d===undefined){data(dom,ORIGINALDISPLAY,d='');}
+return d;},getVisMode=function(dom){var m=data(dom,VISMODE);if(m===undefined){data(dom,VISMODE,m=1);}
+return m;};return{originalDisplay:"",visibilityMode:1,setVisibilityMode:function(visMode){data(this.dom,VISMODE,visMode);return this;},animate:function(args,duration,onComplete,easing,animType){this.anim(args,{duration:duration,callback:onComplete,easing:easing},animType);return this;},anim:function(args,opt,animType,defaultDur,defaultEase,cb){animType=animType||'run';opt=opt||{};var me=this,anim=Ext.lib.Anim[animType](me.dom,args,(opt.duration||defaultDur)||.35,(opt.easing||defaultEase)||'easeOut',function(){if(cb)cb.call(me);if(opt.callback)opt.callback.call(opt.scope||me,me,opt);},me);opt.anim=anim;return anim;},preanim:function(a,i){return!a[i]?false:(typeof a[i]=='object'?a[i]:{duration:a[i+1],callback:a[i+2],easing:a[i+3]});},isVisible:function(){var me=this,dom=me.dom,visible=data(dom,ISVISIBLE);if(typeof visible=='boolean'){return visible;}
+visible=!me.isStyle(VISIBILITY,HIDDEN)&&!me.isStyle(DISPLAY,NONE)&&!((getVisMode(dom)==El.ASCLASS)&&me.hasClass(me.visibilityCls||El.visibilityCls));data(dom,ISVISIBLE,visible);return visible;},setVisible:function(visible,animate){var me=this,isDisplay,isVisibility,isOffsets,isNosize,dom=me.dom,visMode=getVisMode(dom);if(typeof animate=='string'){switch(animate){case DISPLAY:visMode=El.DISPLAY;break;case VISIBILITY:visMode=El.VISIBILITY;break;case OFFSETS:visMode=El.OFFSETS;break;case NOSIZE:case ASCLASS:visMode=El.ASCLASS;break;}
+me.setVisibilityMode(visMode);animate=false;}
+if(!animate||!me.anim){if(visMode==El.ASCLASS){me[visible?'removeClass':'addClass'](me.visibilityCls||El.visibilityCls);}else if(visMode==El.DISPLAY){return me.setDisplayed(visible);}else if(visMode==El.OFFSETS){if(!visible){me.hideModeStyles={position:me.getStyle('position'),top:me.getStyle('top'),left:me.getStyle('left')};me.applyStyles({position:'absolute',top:'-10000px',left:'-10000px'});}else{me.applyStyles(me.hideModeStyles||{position:'',top:'',left:''});delete me.hideModeStyles;}}else{me.fixDisplay();dom.style.visibility=visible?"visible":HIDDEN;}}else{if(visible){me.setOpacity(.01);me.setVisible(true);}
+me.anim({opacity:{to:(visible?1:0)}},me.preanim(arguments,1),null,.35,'easeIn',function(){visible||me.setVisible(false).setOpacity(1);});}
+data(dom,ISVISIBLE,visible);return me;},hasMetrics:function(){var dom=this.dom;return this.isVisible()||(getVisMode(dom)==El.VISIBILITY);},toggle:function(animate){var me=this;me.setVisible(!me.isVisible(),me.preanim(arguments,0));return me;},setDisplayed:function(value){if(typeof value=="boolean"){value=value?getDisplay(this.dom):NONE;}
+this.setStyle(DISPLAY,value);return this;},fixDisplay:function(){var me=this;if(me.isStyle(DISPLAY,NONE)){me.setStyle(VISIBILITY,HIDDEN);me.setStyle(DISPLAY,getDisplay(this.dom));if(me.isStyle(DISPLAY,NONE)){me.setStyle(DISPLAY,"block");}}},hide:function(animate){if(typeof animate=='string'){this.setVisible(false,animate);return this;}
+this.setVisible(false,this.preanim(arguments,0));return this;},show:function(animate){if(typeof animate=='string'){this.setVisible(true,animate);return this;}
+this.setVisible(true,this.preanim(arguments,0));return this;}};}());(function(){var NULL=null,UNDEFINED=undefined,TRUE=true,FALSE=false,SETX="setX",SETY="setY",SETXY="setXY",LEFT="left",BOTTOM="bottom",TOP="top",RIGHT="right",HEIGHT="height",WIDTH="width",POINTS="points",HIDDEN="hidden",ABSOLUTE="absolute",VISIBLE="visible",MOTION="motion",POSITION="position",EASEOUT="easeOut",flyEl=new Ext.Element.Flyweight(),queues={},getObject=function(o){return o||{};},fly=function(dom){flyEl.dom=dom;flyEl.id=Ext.id(dom);return flyEl;},getQueue=function(id){if(!queues[id]){queues[id]=[];}
+return queues[id];},setQueue=function(id,value){queues[id]=value;};Ext.enableFx=TRUE;Ext.Fx={switchStatements:function(key,fn,argHash){return fn.apply(this,argHash[key]);},slideIn:function(anchor,o){o=getObject(o);var me=this,dom=me.dom,st=dom.style,xy,r,b,wrap,after,st,args,pt,bw,bh;anchor=anchor||"t";me.queueFx(o,function(){xy=fly(dom).getXY();fly(dom).fixDisplay();r=fly(dom).getFxRestore();b={x:xy[0],y:xy[1],0:xy[0],1:xy[1],width:dom.offsetWidth,height:dom.offsetHeight};b.right=b.x+b.width;b.bottom=b.y+b.height;fly(dom).setWidth(b.width).setHeight(b.height);wrap=fly(dom).fxWrap(r.pos,o,HIDDEN);st.visibility=VISIBLE;st.position=ABSOLUTE;function after(){fly(dom).fxUnwrap(wrap,r.pos,o);st.width=r.width;st.height=r.height;fly(dom).afterFx(o);}
+pt={to:[b.x,b.y]};bw={to:b.width};bh={to:b.height};function argCalc(wrap,style,ww,wh,sXY,sXYval,s1,s2,w,h,p){var ret={};fly(wrap).setWidth(ww).setHeight(wh);if(fly(wrap)[sXY]){fly(wrap)[sXY](sXYval);}
+style[s1]=style[s2]="0";if(w){ret.width=w;}
+if(h){ret.height=h;}
+if(p){ret.points=p;}
+return ret;};args=fly(dom).switchStatements(anchor.toLowerCase(),argCalc,{t:[wrap,st,b.width,0,NULL,NULL,LEFT,BOTTOM,NULL,bh,NULL],l:[wrap,st,0,b.height,NULL,NULL,RIGHT,TOP,bw,NULL,NULL],r:[wrap,st,b.width,b.height,SETX,b.right,LEFT,TOP,NULL,NULL,pt],b:[wrap,st,b.width,b.height,SETY,b.bottom,LEFT,TOP,NULL,bh,pt],tl:[wrap,st,0,0,NULL,NULL,RIGHT,BOTTOM,bw,bh,pt],bl:[wrap,st,0,0,SETY,b.y+b.height,RIGHT,TOP,bw,bh,pt],br:[wrap,st,0,0,SETXY,[b.right,b.bottom],LEFT,TOP,bw,bh,pt],tr:[wrap,st,0,0,SETX,b.x+b.width,LEFT,BOTTOM,bw,bh,pt]});st.visibility=VISIBLE;fly(wrap).show();arguments.callee.anim=fly(wrap).fxanim(args,o,MOTION,.5,EASEOUT,after);});return me;},slideOut:function(anchor,o){o=getObject(o);var me=this,dom=me.dom,st=dom.style,xy=me.getXY(),wrap,r,b,a,zero={to:0};anchor=anchor||"t";me.queueFx(o,function(){r=fly(dom).getFxRestore();b={x:xy[0],y:xy[1],0:xy[0],1:xy[1],width:dom.offsetWidth,height:dom.offsetHeight};b.right=b.x+b.width;b.bottom=b.y+b.height;fly(dom).setWidth(b.width).setHeight(b.height);wrap=fly(dom).fxWrap(r.pos,o,VISIBLE);st.visibility=VISIBLE;st.position=ABSOLUTE;fly(wrap).setWidth(b.width).setHeight(b.height);function after(){o.useDisplay?fly(dom).setDisplayed(FALSE):fly(dom).hide();fly(dom).fxUnwrap(wrap,r.pos,o);st.width=r.width;st.height=r.height;fly(dom).afterFx(o);}
+function argCalc(style,s1,s2,p1,v1,p2,v2,p3,v3){var ret={};style[s1]=style[s2]="0";ret[p1]=v1;if(p2){ret[p2]=v2;}
+if(p3){ret[p3]=v3;}
+return ret;};a=fly(dom).switchStatements(anchor.toLowerCase(),argCalc,{t:[st,LEFT,BOTTOM,HEIGHT,zero],l:[st,RIGHT,TOP,WIDTH,zero],r:[st,LEFT,TOP,WIDTH,zero,POINTS,{to:[b.right,b.y]}],b:[st,LEFT,TOP,HEIGHT,zero,POINTS,{to:[b.x,b.bottom]}],tl:[st,RIGHT,BOTTOM,WIDTH,zero,HEIGHT,zero],bl:[st,RIGHT,TOP,WIDTH,zero,HEIGHT,zero,POINTS,{to:[b.x,b.bottom]}],br:[st,LEFT,TOP,WIDTH,zero,HEIGHT,zero,POINTS,{to:[b.x+b.width,b.bottom]}],tr:[st,LEFT,BOTTOM,WIDTH,zero,HEIGHT,zero,POINTS,{to:[b.right,b.y]}]});arguments.callee.anim=fly(wrap).fxanim(a,o,MOTION,.5,EASEOUT,after);});return me;},puff:function(o){o=getObject(o);var me=this,dom=me.dom,st=dom.style,width,height,r;me.queueFx(o,function(){width=fly(dom).getWidth();height=fly(dom).getHeight();fly(dom).clearOpacity();fly(dom).show();r=fly(dom).getFxRestore();function after(){o.useDisplay?fly(dom).setDisplayed(FALSE):fly(dom).hide();fly(dom).clearOpacity();fly(dom).setPositioning(r.pos);st.width=r.width;st.height=r.height;st.fontSize='';fly(dom).afterFx(o);}
+arguments.callee.anim=fly(dom).fxanim({width:{to:fly(dom).adjustWidth(width*2)},height:{to:fly(dom).adjustHeight(height*2)},points:{by:[-width*.5,-height*.5]},opacity:{to:0},fontSize:{to:200,unit:"%"}},o,MOTION,.5,EASEOUT,after);});return me;},switchOff:function(o){o=getObject(o);var me=this,dom=me.dom,st=dom.style,r;me.queueFx(o,function(){fly(dom).clearOpacity();fly(dom).clip();r=fly(dom).getFxRestore();function after(){o.useDisplay?fly(dom).setDisplayed(FALSE):fly(dom).hide();fly(dom).clearOpacity();fly(dom).setPositioning(r.pos);st.width=r.width;st.height=r.height;fly(dom).afterFx(o);};fly(dom).fxanim({opacity:{to:0.3}},NULL,NULL,.1,NULL,function(){fly(dom).clearOpacity();(function(){fly(dom).fxanim({height:{to:1},points:{by:[0,fly(dom).getHeight()*.5]}},o,MOTION,0.3,'easeIn',after);}).defer(100);});});return me;},highlight:function(color,o){o=getObject(o);var me=this,dom=me.dom,attr=o.attr||"backgroundColor",a={},restore;me.queueFx(o,function(){fly(dom).clearOpacity();fly(dom).show();function after(){dom.style[attr]=restore;fly(dom).afterFx(o);}
+restore=dom.style[attr];a[attr]={from:color||"ffff9c",to:o.endColor||fly(dom).getColor(attr)||"ffffff"};arguments.callee.anim=fly(dom).fxanim(a,o,'color',1,'easeIn',after);});return me;},frame:function(color,count,o){o=getObject(o);var me=this,dom=me.dom,proxy,active;me.queueFx(o,function(){color=color||'#C3DAF9';if(color.length==6){color='#'+color;}
+count=count||1;fly(dom).show();var xy=fly(dom).getXY(),b={x:xy[0],y:xy[1],0:xy[0],1:xy[1],width:dom.offsetWidth,height:dom.offsetHeight},queue=function(){proxy=fly(document.body||document.documentElement).createChild({style:{position:ABSOLUTE,'z-index':35000,border:'0px solid '+color}});return proxy.queueFx({},animFn);};arguments.callee.anim={isAnimated:true,stop:function(){count=0;proxy.stopFx();}};function animFn(){var scale=Ext.isBorderBox?2:1;active=proxy.anim({top:{from:b.y,to:b.y-20},left:{from:b.x,to:b.x-20},borderWidth:{from:0,to:10},opacity:{from:1,to:0},height:{from:b.height,to:b.height+20*scale},width:{from:b.width,to:b.width+20*scale}},{duration:o.duration||1,callback:function(){proxy.remove();--count>0?queue():fly(dom).afterFx(o);}});arguments.callee.anim={isAnimated:true,stop:function(){active.stop();}};};queue();});return me;},pause:function(seconds){var dom=this.dom,t;this.queueFx({},function(){t=setTimeout(function(){fly(dom).afterFx({});},seconds*1000);arguments.callee.anim={isAnimated:true,stop:function(){clearTimeout(t);fly(dom).afterFx({});}};});return this;},fadeIn:function(o){o=getObject(o);var me=this,dom=me.dom,to=o.endOpacity||1;me.queueFx(o,function(){fly(dom).setOpacity(0);fly(dom).fixDisplay();dom.style.visibility=VISIBLE;arguments.callee.anim=fly(dom).fxanim({opacity:{to:to}},o,NULL,.5,EASEOUT,function(){if(to==1){fly(dom).clearOpacity();}
+fly(dom).afterFx(o);});});return me;},fadeOut:function(o){o=getObject(o);var me=this,dom=me.dom,style=dom.style,to=o.endOpacity||0;me.queueFx(o,function(){arguments.callee.anim=fly(dom).fxanim({opacity:{to:to}},o,NULL,.5,EASEOUT,function(){if(to==0){Ext.Element.data(dom,'visibilityMode')==Ext.Element.DISPLAY||o.useDisplay?style.display="none":style.visibility=HIDDEN;fly(dom).clearOpacity();}
+fly(dom).afterFx(o);});});return me;},scale:function(w,h,o){this.shift(Ext.apply({},o,{width:w,height:h}));return this;},shift:function(o){o=getObject(o);var dom=this.dom,a={};this.queueFx(o,function(){for(var prop in o){if(o[prop]!=UNDEFINED){a[prop]={to:o[prop]};}}
+a.width?a.width.to=fly(dom).adjustWidth(o.width):a;a.height?a.height.to=fly(dom).adjustWidth(o.height):a;if(a.x||a.y||a.xy){a.points=a.xy||{to:[a.x?a.x.to:fly(dom).getX(),a.y?a.y.to:fly(dom).getY()]};}
+arguments.callee.anim=fly(dom).fxanim(a,o,MOTION,.35,EASEOUT,function(){fly(dom).afterFx(o);});});return this;},ghost:function(anchor,o){o=getObject(o);var me=this,dom=me.dom,st=dom.style,a={opacity:{to:0},points:{}},pt=a.points,r,w,h;anchor=anchor||"b";me.queueFx(o,function(){r=fly(dom).getFxRestore();w=fly(dom).getWidth();h=fly(dom).getHeight();function after(){o.useDisplay?fly(dom).setDisplayed(FALSE):fly(dom).hide();fly(dom).clearOpacity();fly(dom).setPositioning(r.pos);st.width=r.width;st.height=r.height;fly(dom).afterFx(o);}
+pt.by=fly(dom).switchStatements(anchor.toLowerCase(),function(v1,v2){return[v1,v2];},{t:[0,-h],l:[-w,0],r:[w,0],b:[0,h],tl:[-w,-h],bl:[-w,h],br:[w,h],tr:[w,-h]});arguments.callee.anim=fly(dom).fxanim(a,o,MOTION,.5,EASEOUT,after);});return me;},syncFx:function(){var me=this;me.fxDefaults=Ext.apply(me.fxDefaults||{},{block:FALSE,concurrent:TRUE,stopFx:FALSE});return me;},sequenceFx:function(){var me=this;me.fxDefaults=Ext.apply(me.fxDefaults||{},{block:FALSE,concurrent:FALSE,stopFx:FALSE});return me;},nextFx:function(){var ef=getQueue(this.dom.id)[0];if(ef){ef.call(this);}},hasActiveFx:function(){return getQueue(this.dom.id)[0];},stopFx:function(finish){var me=this,id=me.dom.id;if(me.hasActiveFx()){var cur=getQueue(id)[0];if(cur&&cur.anim){if(cur.anim.isAnimated){setQueue(id,[cur]);cur.anim.stop(finish!==undefined?finish:TRUE);}else{setQueue(id,[]);}}}
+return me;},beforeFx:function(o){if(this.hasActiveFx()&&!o.concurrent){if(o.stopFx){this.stopFx();return TRUE;}
+return FALSE;}
+return TRUE;},hasFxBlock:function(){var q=getQueue(this.dom.id);return q&&q[0]&&q[0].block;},queueFx:function(o,fn){var me=fly(this.dom);if(!me.hasFxBlock()){Ext.applyIf(o,me.fxDefaults);if(!o.concurrent){var run=me.beforeFx(o);fn.block=o.block;getQueue(me.dom.id).push(fn);if(run){me.nextFx();}}else{fn.call(me);}}
+return me;},fxWrap:function(pos,o,vis){var dom=this.dom,wrap,wrapXY;if(!o.wrap||!(wrap=Ext.getDom(o.wrap))){if(o.fixPosition){wrapXY=fly(dom).getXY();}
+var div=document.createElement("div");div.style.visibility=vis;wrap=dom.parentNode.insertBefore(div,dom);fly(wrap).setPositioning(pos);if(fly(wrap).isStyle(POSITION,"static")){fly(wrap).position("relative");}
+fly(dom).clearPositioning('auto');fly(wrap).clip();wrap.appendChild(dom);if(wrapXY){fly(wrap).setXY(wrapXY);}}
+return wrap;},fxUnwrap:function(wrap,pos,o){var dom=this.dom;fly(dom).clearPositioning();fly(dom).setPositioning(pos);if(!o.wrap){var pn=fly(wrap).dom.parentNode;pn.insertBefore(dom,wrap);fly(wrap).remove();}},getFxRestore:function(){var st=this.dom.style;return{pos:this.getPositioning(),width:st.width,height:st.height};},afterFx:function(o){var dom=this.dom,id=dom.id;if(o.afterStyle){fly(dom).setStyle(o.afterStyle);}
+if(o.afterCls){fly(dom).addClass(o.afterCls);}
+if(o.remove==TRUE){fly(dom).remove();}
+if(o.callback){o.callback.call(o.scope,fly(dom));}
+if(!o.concurrent){getQueue(id).shift();fly(dom).nextFx();}},fxanim:function(args,opt,animType,defaultDur,defaultEase,cb){animType=animType||'run';opt=opt||{};var anim=Ext.lib.Anim[animType](this.dom,args,(opt.duration||defaultDur)||.35,(opt.easing||defaultEase)||EASEOUT,cb,this);opt.anim=anim;return anim;}};Ext.Fx.resize=Ext.Fx.scale;Ext.Element.addMethods(Ext.Fx);})();Ext.CompositeElementLite=function(els,root){this.elements=[];this.add(els,root);this.el=new Ext.Element.Flyweight();};Ext.CompositeElementLite.prototype={isComposite:true,getElement:function(el){var e=this.el;e.dom=el;e.id=el.id;return e;},transformElement:function(el){return Ext.getDom(el);},getCount:function(){return this.elements.length;},add:function(els,root){var me=this,elements=me.elements;if(!els){return this;}
+if(typeof els=="string"){els=Ext.Element.selectorFunction(els,root);}else if(els.isComposite){els=els.elements;}else if(!Ext.isIterable(els)){els=[els];}
+for(var i=0,len=els.length;i<len;++i){elements.push(me.transformElement(els[i]));}
+return me;},invoke:function(fn,args){var me=this,els=me.elements,len=els.length,e,i;for(i=0;i<len;i++){e=els[i];if(e){Ext.Element.prototype[fn].apply(me.getElement(e),args);}}
+return me;},item:function(index){var me=this,el=me.elements[index],out=null;if(el){out=me.getElement(el);}
+return out;},addListener:function(eventName,handler,scope,opt){var els=this.elements,len=els.length,i,e;for(i=0;i<len;i++){e=els[i];if(e){Ext.EventManager.on(e,eventName,handler,scope||e,opt);}}
+return this;},each:function(fn,scope){var me=this,els=me.elements,len=els.length,i,e;for(i=0;i<len;i++){e=els[i];if(e){e=this.getElement(e);if(fn.call(scope||e,e,me,i)===false){break;}}}
+return me;},fill:function(els){var me=this;me.elements=[];me.add(els);return me;},filter:function(selector){var els=[],me=this,fn=Ext.isFunction(selector)?selector:function(el){return el.is(selector);};me.each(function(el,self,i){if(fn(el,i)!==false){els[els.length]=me.transformElement(el);}});me.elements=els;return me;},indexOf:function(el){return this.elements.indexOf(this.transformElement(el));},replaceElement:function(el,replacement,domReplace){var index=!isNaN(el)?el:this.indexOf(el),d;if(index>-1){replacement=Ext.getDom(replacement);if(domReplace){d=this.elements[index];d.parentNode.insertBefore(replacement,d);Ext.removeNode(d);}
+this.elements.splice(index,1,replacement);}
+return this;},clear:function(){this.elements=[];}};Ext.CompositeElementLite.prototype.on=Ext.CompositeElementLite.prototype.addListener;Ext.CompositeElementLite.importElementMethods=function(){var fnName,ElProto=Ext.Element.prototype,CelProto=Ext.CompositeElementLite.prototype;for(fnName in ElProto){if(typeof ElProto[fnName]=='function'){(function(fnName){CelProto[fnName]=CelProto[fnName]||function(){return this.invoke(fnName,arguments);};}).call(CelProto,fnName);}}};Ext.CompositeElementLite.importElementMethods();if(Ext.DomQuery){Ext.Element.selectorFunction=Ext.DomQuery.select;}
+Ext.Element.select=function(selector,root){var els;if(typeof selector=="string"){els=Ext.Element.selectorFunction(selector,root);}else if(selector.length!==undefined){els=selector;}else{throw"Invalid selector";}
+return new Ext.CompositeElementLite(els);};Ext.select=Ext.Element.select;(function(){var BEFOREREQUEST="beforerequest",REQUESTCOMPLETE="requestcomplete",REQUESTEXCEPTION="requestexception",UNDEFINED=undefined,LOAD='load',POST='POST',GET='GET',WINDOW=window;Ext.data.Connection=function(config){Ext.apply(this,config);this.addEvents(BEFOREREQUEST,REQUESTCOMPLETE,REQUESTEXCEPTION);Ext.data.Connection.superclass.constructor.call(this);};Ext.extend(Ext.data.Connection,Ext.util.Observable,{timeout:30000,autoAbort:false,disableCaching:true,disableCachingParam:'_dc',request:function(o){var me=this;if(me.fireEvent(BEFOREREQUEST,me,o)){if(o.el){if(!Ext.isEmpty(o.indicatorText)){me.indicatorText='<div class="loading-indicator">'+o.indicatorText+"</div>";}
+if(me.indicatorText){Ext.getDom(o.el).innerHTML=me.indicatorText;}
+o.success=(Ext.isFunction(o.success)?o.success:function(){}).createInterceptor(function(response){Ext.getDom(o.el).innerHTML=response.responseText;});}
+var p=o.params,url=o.url||me.url,method,cb={success:me.handleResponse,failure:me.handleFailure,scope:me,argument:{options:o},timeout:Ext.num(o.timeout,me.timeout)},form,serForm;if(Ext.isFunction(p)){p=p.call(o.scope||WINDOW,o);}
+p=Ext.urlEncode(me.extraParams,Ext.isObject(p)?Ext.urlEncode(p):p);if(Ext.isFunction(url)){url=url.call(o.scope||WINDOW,o);}
+if((form=Ext.getDom(o.form))){url=url||form.action;if(o.isUpload||(/multipart\/form-data/i.test(form.getAttribute("enctype")))){return me.doFormUpload.call(me,o,p,url);}
+serForm=Ext.lib.Ajax.serializeForm(form);p=p?(p+'&'+serForm):serForm;}
+method=o.method||me.method||((p||o.xmlData||o.jsonData)?POST:GET);if(method===GET&&(me.disableCaching&&o.disableCaching!==false)||o.disableCaching===true){var dcp=o.disableCachingParam||me.disableCachingParam;url=Ext.urlAppend(url,dcp+'='+(new Date().getTime()));}
+o.headers=Ext.apply(o.headers||{},me.defaultHeaders||{});if(o.autoAbort===true||me.autoAbort){me.abort();}
+if((method==GET||o.xmlData||o.jsonData)&&p){url=Ext.urlAppend(url,p);p='';}
+return(me.transId=Ext.lib.Ajax.request(method,url,cb,p,o));}else{return o.callback?o.callback.apply(o.scope,[o,UNDEFINED,UNDEFINED]):null;}},isLoading:function(transId){return transId?Ext.lib.Ajax.isCallInProgress(transId):!!this.transId;},abort:function(transId){if(transId||this.isLoading()){Ext.lib.Ajax.abort(transId||this.transId);}},handleResponse:function(response){this.transId=false;var options=response.argument.options;response.argument=options?options.argument:null;this.fireEvent(REQUESTCOMPLETE,this,response,options);if(options.success){options.success.call(options.scope,response,options);}
+if(options.callback){options.callback.call(options.scope,options,true,response);}},handleFailure:function(response,e){this.transId=false;var options=response.argument.options;response.argument=options?options.argument:null;this.fireEvent(REQUESTEXCEPTION,this,response,options,e);if(options.failure){options.failure.call(options.scope,response,options);}
+if(options.callback){options.callback.call(options.scope,options,false,response);}},doFormUpload:function(o,ps,url){var id=Ext.id(),doc=document,frame=doc.createElement('iframe'),form=Ext.getDom(o.form),hiddens=[],hd,encoding='multipart/form-data',buf={target:form.target,method:form.method,encoding:form.encoding,enctype:form.enctype,action:form.action};Ext.fly(frame).set({id:id,name:id,cls:'x-hidden',src:Ext.SSL_SECURE_URL});doc.body.appendChild(frame);if(Ext.isIE){document.frames[id].name=id;}
+Ext.fly(form).set({target:id,method:POST,enctype:encoding,encoding:encoding,action:url||buf.action});Ext.iterate(Ext.urlDecode(ps,false),function(k,v){hd=doc.createElement('input');Ext.fly(hd).set({type:'hidden',value:v,name:k});form.appendChild(hd);hiddens.push(hd);});function cb(){var me=this,r={responseText:'',responseXML:null,argument:o.argument},doc,firstChild;try{doc=frame.contentWindow.document||frame.contentDocument||WINDOW.frames[id].document;if(doc){if(doc.body){if(/textarea/i.test((firstChild=doc.body.firstChild||{}).tagName)){r.responseText=firstChild.value;}else{r.responseText=doc.body.innerHTML;}}
+r.responseXML=doc.XMLDocument||doc;}}
+catch(e){}
+Ext.EventManager.removeListener(frame,LOAD,cb,me);me.fireEvent(REQUESTCOMPLETE,me,r,o);function runCallback(fn,scope,args){if(Ext.isFunction(fn)){fn.apply(scope,args);}}
+runCallback(o.success,o.scope,[r,o]);runCallback(o.callback,o.scope,[o,true,r]);if(!me.debugUploads){setTimeout(function(){Ext.removeNode(frame);},100);}}
+Ext.EventManager.on(frame,LOAD,cb,this);form.submit();Ext.fly(form).set(buf);Ext.each(hiddens,function(h){Ext.removeNode(h);});}});})();Ext.Ajax=new Ext.data.Connection({autoAbort:false,serializeForm:function(form){return Ext.lib.Ajax.serializeForm(form);}});Ext.util.JSON=new(function(){var useHasOwn=!!{}.hasOwnProperty,isNative=function(){var useNative=null;return function(){if(useNative===null){useNative=Ext.USE_NATIVE_JSON&&window.JSON&&JSON.toString()=='[object JSON]';}
+return useNative;};}(),pad=function(n){return n<10?"0"+n:n;},doDecode=function(json){return eval("("+json+")");},doEncode=function(o){if(!Ext.isDefined(o)||o===null){return"null";}else if(Ext.isArray(o)){return encodeArray(o);}else if(Ext.isDate(o)){return Ext.util.JSON.encodeDate(o);}else if(Ext.isString(o)){return encodeString(o);}else if(typeof o=="number"){return isFinite(o)?String(o):"null";}else if(Ext.isBoolean(o)){return String(o);}else{var a=["{"],b,i,v;for(i in o){if(!o.getElementsByTagName){if(!useHasOwn||o.hasOwnProperty(i)){v=o[i];switch(typeof v){case"undefined":case"function":case"unknown":break;default:if(b){a.push(',');}
+a.push(doEncode(i),":",v===null?"null":doEncode(v));b=true;}}}}
+a.push("}");return a.join("");}},m={"\b":'\\b',"\t":'\\t',"\n":'\\n',"\f":'\\f',"\r":'\\r','"':'\\"',"\\":'\\\\'},encodeString=function(s){if(/["\\\x00-\x1f]/.test(s)){return'"'+s.replace(/([\x00-\x1f\\"])/g,function(a,b){var c=m[b];if(c){return c;}
+c=b.charCodeAt();return"\\u00"+
+Math.floor(c/16).toString(16)+
+(c%16).toString(16);})+'"';}
+return'"'+s+'"';},encodeArray=function(o){var a=["["],b,i,l=o.length,v;for(i=0;i<l;i+=1){v=o[i];switch(typeof v){case"undefined":case"function":case"unknown":break;default:if(b){a.push(',');}
+a.push(v===null?"null":Ext.util.JSON.encode(v));b=true;}}
+a.push("]");return a.join("");};this.encodeDate=function(o){return'"'+o.getFullYear()+"-"+
+pad(o.getMonth()+1)+"-"+
+pad(o.getDate())+"T"+
+pad(o.getHours())+":"+
+pad(o.getMinutes())+":"+
+pad(o.getSeconds())+'"';};this.encode=function(){var ec;return function(o){if(!ec){ec=isNative()?JSON.stringify:doEncode;}
+return ec(o);};}();this.decode=function(){var dc;return function(json){if(!dc){dc=isNative()?JSON.parse:doDecode;}
+return dc(json);};}();})();Ext.encode=Ext.util.JSON.encode;Ext.decode=Ext.util.JSON.decode;Ext.EventManager=function(){var docReadyEvent,docReadyProcId,docReadyState=false,DETECT_NATIVE=Ext.isGecko||Ext.isWebKit||Ext.isSafari,E=Ext.lib.Event,D=Ext.lib.Dom,DOC=document,WINDOW=window,DOMCONTENTLOADED="DOMContentLoaded",COMPLETE='complete',propRe=/^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,specialElCache=[];function getId(el){var id=false,i=0,len=specialElCache.length,skip=false,o;if(el){if(el.getElementById||el.navigator){for(;i<len;++i){o=specialElCache[i];if(o.el===el){id=o.id;break;}}
+if(!id){id=Ext.id(el);specialElCache.push({id:id,el:el});skip=true;}}else{id=Ext.id(el);}
+if(!Ext.elCache[id]){Ext.Element.addToCache(new Ext.Element(el),id);if(skip){Ext.elCache[id].skipGC=true;}}}
+return id;}
+function addListener(el,ename,fn,task,wrap,scope){el=Ext.getDom(el);var id=getId(el),es=Ext.elCache[id].events,wfn;wfn=E.on(el,ename,wrap);es[ename]=es[ename]||[];es[ename].push([fn,wrap,scope,wfn,task]);if(el.addEventListener&&ename=="mousewheel"){var args=["DOMMouseScroll",wrap,false];el.addEventListener.apply(el,args);Ext.EventManager.addListener(WINDOW,'unload',function(){el.removeEventListener.apply(el,args);});}
+if(el==DOC&&ename=="mousedown"){Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);}}
+function doScrollChk(){if(window!=top){return false;}
+try{DOC.documentElement.doScroll('left');}catch(e){return false;}
+fireDocReady();return true;}
+function checkReadyState(e){if(Ext.isIE&&doScrollChk()){return true;}
+if(DOC.readyState==COMPLETE){fireDocReady();return true;}
+docReadyState||(docReadyProcId=setTimeout(arguments.callee,2));return false;}
+var styles;function checkStyleSheets(e){styles||(styles=Ext.query('style, link[rel=stylesheet]'));if(styles.length==DOC.styleSheets.length){fireDocReady();return true;}
+docReadyState||(docReadyProcId=setTimeout(arguments.callee,2));return false;}
+function OperaDOMContentLoaded(e){DOC.removeEventListener(DOMCONTENTLOADED,arguments.callee,false);checkStyleSheets();}
+function fireDocReady(e){if(!docReadyState){docReadyState=true;if(docReadyProcId){clearTimeout(docReadyProcId);}
+if(DETECT_NATIVE){DOC.removeEventListener(DOMCONTENTLOADED,fireDocReady,false);}
+if(Ext.isIE&&checkReadyState.bindIE){DOC.detachEvent('onreadystatechange',checkReadyState);}
+E.un(WINDOW,"load",arguments.callee);}
+if(docReadyEvent&&!Ext.isReady){Ext.isReady=true;docReadyEvent.fire();docReadyEvent.listeners=[];}}
+function initDocReady(){docReadyEvent||(docReadyEvent=new Ext.util.Event());if(DETECT_NATIVE){DOC.addEventListener(DOMCONTENTLOADED,fireDocReady,false);}
+if(Ext.isIE){if(!checkReadyState()){checkReadyState.bindIE=true;DOC.attachEvent('onreadystatechange',checkReadyState);}}else if(Ext.isOpera){(DOC.readyState==COMPLETE&&checkStyleSheets())||DOC.addEventListener(DOMCONTENTLOADED,OperaDOMContentLoaded,false);}else if(Ext.isWebKit){checkReadyState();}
+E.on(WINDOW,"load",fireDocReady);}
+function createTargeted(h,o){return function(){var args=Ext.toArray(arguments);if(o.target==Ext.EventObject.setEvent(args[0]).target){h.apply(this,args);}};}
+function createBuffered(h,o,task){return function(e){task.delay(o.buffer,h,null,[new Ext.EventObjectImpl(e)]);};}
+function createSingle(h,el,ename,fn,scope){return function(e){Ext.EventManager.removeListener(el,ename,fn,scope);h(e);};}
+function createDelayed(h,o,fn){return function(e){var task=new Ext.util.DelayedTask(h);if(!fn.tasks){fn.tasks=[];}
+fn.tasks.push(task);task.delay(o.delay||10,h,null,[new Ext.EventObjectImpl(e)]);};}
+function listen(element,ename,opt,fn,scope){var o=(!opt||typeof opt=="boolean")?{}:opt,el=Ext.getDom(element),task;fn=fn||o.fn;scope=scope||o.scope;if(!el){throw"Error listening for \""+ename+'\". Element "'+element+'" doesn\'t exist.';}
+function h(e){if(!Ext){return;}
+e=Ext.EventObject.setEvent(e);var t;if(o.delegate){if(!(t=e.getTarget(o.delegate,el))){return;}}else{t=e.target;}
+if(o.stopEvent){e.stopEvent();}
+if(o.preventDefault){e.preventDefault();}
+if(o.stopPropagation){e.stopPropagation();}
+if(o.normalized===false){e=e.browserEvent;}
+fn.call(scope||el,e,t,o);}
+if(o.target){h=createTargeted(h,o);}
+if(o.delay){h=createDelayed(h,o,fn);}
+if(o.single){h=createSingle(h,el,ename,fn,scope);}
+if(o.buffer){task=new Ext.util.DelayedTask(h);h=createBuffered(h,o,task);}
+addListener(el,ename,fn,task,h,scope);return h;}
+var pub={addListener:function(element,eventName,fn,scope,options){if(typeof eventName=='object'){var o=eventName,e,val;for(e in o){val=o[e];if(!propRe.test(e)){if(Ext.isFunction(val)){listen(element,e,o,val,o.scope);}else{listen(element,e,val);}}}}else{listen(element,eventName,options,fn,scope);}},removeListener:function(el,eventName,fn,scope){el=Ext.getDom(el);var id=getId(el),f=el&&(Ext.elCache[id].events)[eventName]||[],wrap,i,l,k,len,fnc;for(i=0,len=f.length;i<len;i++){if(Ext.isArray(fnc=f[i])&&fnc[0]==fn&&(!scope||fnc[2]==scope)){if(fnc[4]){fnc[4].cancel();}
+k=fn.tasks&&fn.tasks.length;if(k){while(k--){fn.tasks[k].cancel();}
+delete fn.tasks;}
+wrap=fnc[1];E.un(el,eventName,E.extAdapter?fnc[3]:wrap);if(wrap&&el.addEventListener&&eventName=="mousewheel"){el.removeEventListener("DOMMouseScroll",wrap,false);}
+if(wrap&&el==DOC&&eventName=="mousedown"){Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);}
+f.splice(i,1);if(f.length===0){delete Ext.elCache[id].events[eventName];}
+for(k in Ext.elCache[id].events){return false;}
+Ext.elCache[id].events={};return false;}}},removeAll:function(el){el=Ext.getDom(el);var id=getId(el),ec=Ext.elCache[id]||{},es=ec.events||{},f,i,len,ename,fn,k,wrap;for(ename in es){if(es.hasOwnProperty(ename)){f=es[ename];for(i=0,len=f.length;i<len;i++){fn=f[i];if(fn[4]){fn[4].cancel();}
+if(fn[0].tasks&&(k=fn[0].tasks.length)){while(k--){fn[0].tasks[k].cancel();}
+delete fn.tasks;}
+wrap=fn[1];E.un(el,ename,E.extAdapter?fn[3]:wrap);if(el.addEventListener&&wrap&&ename=="mousewheel"){el.removeEventListener("DOMMouseScroll",wrap,false);}
+if(wrap&&el==DOC&&ename=="mousedown"){Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);}}}}
+if(Ext.elCache[id]){Ext.elCache[id].events={};}},getListeners:function(el,eventName){el=Ext.getDom(el);var id=getId(el),ec=Ext.elCache[id]||{},es=ec.events||{},results=[];if(es&&es[eventName]){return es[eventName];}else{return null;}},purgeElement:function(el,recurse,eventName){el=Ext.getDom(el);var id=getId(el),ec=Ext.elCache[id]||{},es=ec.events||{},i,f,len;if(eventName){if(es&&es.hasOwnProperty(eventName)){f=es[eventName];for(i=0,len=f.length;i<len;i++){Ext.EventManager.removeListener(el,eventName,f[i][0]);}}}else{Ext.EventManager.removeAll(el);}
+if(recurse&&el&&el.childNodes){for(i=0,len=el.childNodes.length;i<len;i++){Ext.EventManager.purgeElement(el.childNodes[i],recurse,eventName);}}},_unload:function(){var el;for(el in Ext.elCache){Ext.EventManager.removeAll(el);}
+delete Ext.elCache;delete Ext.Element._flyweights;var c,conn,tid,ajax=Ext.lib.Ajax;(typeof ajax.conn=='object')?conn=ajax.conn:conn={};for(tid in conn){c=conn[tid];if(c){ajax.abort({conn:c,tId:tid});}}},onDocumentReady:function(fn,scope,options){if(Ext.isReady){docReadyEvent||(docReadyEvent=new Ext.util.Event());docReadyEvent.addListener(fn,scope,options);docReadyEvent.fire();docReadyEvent.listeners=[];}else{if(!docReadyEvent){initDocReady();}
+options=options||{};options.delay=options.delay||1;docReadyEvent.addListener(fn,scope,options);}},fireDocReady:fireDocReady};pub.on=pub.addListener;pub.un=pub.removeListener;pub.stoppedMouseDownEvent=new Ext.util.Event();return pub;}();Ext.onReady=Ext.EventManager.onDocumentReady;(function(){var initExtCss=function(){var bd=document.body||document.getElementsByTagName('body')[0];if(!bd){return false;}
+var cls=[' ',Ext.isIE?"ext-ie "+(Ext.isIE6?'ext-ie6':(Ext.isIE7?'ext-ie7':'ext-ie8')):Ext.isGecko?"ext-gecko "+(Ext.isGecko2?'ext-gecko2':'ext-gecko3'):Ext.isOpera?"ext-opera":Ext.isWebKit?"ext-webkit":""];if(Ext.isSafari){cls.push("ext-safari "+(Ext.isSafari2?'ext-safari2':(Ext.isSafari3?'ext-safari3':'ext-safari4')));}else if(Ext.isChrome){cls.push("ext-chrome");}
+if(Ext.isMac){cls.push("ext-mac");}
+if(Ext.isLinux){cls.push("ext-linux");}
+if(Ext.isStrict||Ext.isBorderBox){var p=bd.parentNode;if(p){Ext.fly(p,'_internal').addClass(((Ext.isStrict&&Ext.isIE)||(!Ext.enableForcedBoxModel&&!Ext.isIE))?' ext-strict':' ext-border-box');}}
+if(Ext.enableForcedBoxModel&&!Ext.isIE){Ext.isForcedBorderBox=true;cls.push("ext-forced-border-box");}
+Ext.fly(bd,'_internal').addClass(cls);return true;};if(!initExtCss()){Ext.onReady(initExtCss);}})();(function(){var supports=Ext.apply(Ext.supports,{correctRightMargin:true,correctTransparentColor:true,cssFloat:true});var supportTests=function(){var div=document.createElement('div'),doc=document,view,last;div.innerHTML='<div style="height:30px;width:50px;"><div style="height:20px;width:20px;"></div></div><div style="float:left;background-color:transparent;">';doc.body.appendChild(div);last=div.lastChild;if((view=doc.defaultView)){if(view.getComputedStyle(div.firstChild.firstChild,null).marginRight!='0px'){supports.correctRightMargin=false;}
+if(view.getComputedStyle(last,null).backgroundColor!='transparent'){supports.correctTransparentColor=false;}}
+supports.cssFloat=!!last.style.cssFloat;doc.body.removeChild(div);};if(Ext.isReady){supportTests();}else{Ext.onReady(supportTests);}})();Ext.EventObject=function(){var E=Ext.lib.Event,clickRe=/(dbl)?click/,safariKeys={3:13,63234:37,63235:39,63232:38,63233:40,63276:33,63277:34,63272:46,63273:36,63275:35},btnMap=Ext.isIE?{1:0,4:1,2:2}:{0:0,1:1,2:2};Ext.EventObjectImpl=function(e){if(e){this.setEvent(e.browserEvent||e);}};Ext.EventObjectImpl.prototype={setEvent:function(e){var me=this;if(e==me||(e&&e.browserEvent)){return e;}
+me.browserEvent=e;if(e){me.button=e.button?btnMap[e.button]:(e.which?e.which-1:-1);if(clickRe.test(e.type)&&me.button==-1){me.button=0;}
+me.type=e.type;me.shiftKey=e.shiftKey;me.ctrlKey=e.ctrlKey||e.metaKey||false;me.altKey=e.altKey;me.keyCode=e.keyCode;me.charCode=e.charCode;me.target=E.getTarget(e);me.xy=E.getXY(e);}else{me.button=-1;me.shiftKey=false;me.ctrlKey=false;me.altKey=false;me.keyCode=0;me.charCode=0;me.target=null;me.xy=[0,0];}
+return me;},stopEvent:function(){var me=this;if(me.browserEvent){if(me.browserEvent.type=='mousedown'){Ext.EventManager.stoppedMouseDownEvent.fire(me);}
+E.stopEvent(me.browserEvent);}},preventDefault:function(){if(this.browserEvent){E.preventDefault(this.browserEvent);}},stopPropagation:function(){var me=this;if(me.browserEvent){if(me.browserEvent.type=='mousedown'){Ext.EventManager.stoppedMouseDownEvent.fire(me);}
+E.stopPropagation(me.browserEvent);}},getCharCode:function(){return this.charCode||this.keyCode;},getKey:function(){return this.normalizeKey(this.keyCode||this.charCode);},normalizeKey:function(k){return Ext.isSafari?(safariKeys[k]||k):k;},getPageX:function(){return this.xy[0];},getPageY:function(){return this.xy[1];},getXY:function(){return this.xy;},getTarget:function(selector,maxDepth,returnEl){return selector?Ext.fly(this.target).findParent(selector,maxDepth,returnEl):(returnEl?Ext.get(this.target):this.target);},getRelatedTarget:function(){return this.browserEvent?E.getRelatedTarget(this.browserEvent):null;},getWheelDelta:function(){var e=this.browserEvent;var delta=0;if(e.wheelDelta){delta=e.wheelDelta/120;}else if(e.detail){delta=-e.detail/3;}
+return delta;},within:function(el,related,allowEl){if(el){var t=this[related?"getRelatedTarget":"getTarget"]();return t&&((allowEl?(t==Ext.getDom(el)):false)||Ext.fly(el).contains(t));}
+return false;}};return new Ext.EventObjectImpl();}();Ext.Loader=Ext.apply({},{load:function(fileList,callback,scope,preserveOrder){var scope=scope||this,head=document.getElementsByTagName("head")[0],fragment=document.createDocumentFragment(),numFiles=fileList.length,loadedFiles=0,me=this;var loadFileIndex=function(index){head.appendChild(me.buildScriptTag(fileList[index],onFileLoaded));};var onFileLoaded=function(){loadedFiles++;if(numFiles==loadedFiles&&typeof callback=='function'){callback.call(scope);}else{if(preserveOrder===true){loadFileIndex(loadedFiles);}}};if(preserveOrder===true){loadFileIndex.call(this,0);}else{Ext.each(fileList,function(file,index){fragment.appendChild(this.buildScriptTag(file,onFileLoaded));},this);head.appendChild(fragment);}},buildScriptTag:function(filename,callback){var script=document.createElement('script');script.type="text/javascript";script.src=filename;if(script.readyState){script.onreadystatechange=function(){if(script.readyState=="loaded"||script.readyState=="complete"){script.onreadystatechange=null;callback();}};}else{script.onload=callback;}
+return script;}});Ext.ns("Ext.grid","Ext.list","Ext.dd","Ext.tree","Ext.form","Ext.menu","Ext.state","Ext.layout","Ext.app","Ext.ux","Ext.chart","Ext.direct");Ext.apply(Ext,function(){var E=Ext,idSeed=0,scrollWidth=null;return{emptyFn:function(){},BLANK_IMAGE_URL:Ext.isIE6||Ext.isIE7||Ext.isAir?'http:/'+'/www.extjs.com/s.gif':'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',extendX:function(supr,fn){return Ext.extend(supr,fn(supr.prototype));},getDoc:function(){return Ext.get(document);},num:function(v,defaultValue){v=Number(Ext.isEmpty(v)||Ext.isArray(v)||typeof v=='boolean'||(typeof v=='string'&&v.trim().length==0)?NaN:v);return isNaN(v)?defaultValue:v;},value:function(v,defaultValue,allowBlank){return Ext.isEmpty(v,allowBlank)?defaultValue:v;},escapeRe:function(s){return s.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");},sequence:function(o,name,fn,scope){o[name]=o[name].createSequence(fn,scope);},addBehaviors:function(o){if(!Ext.isReady){Ext.onReady(function(){Ext.addBehaviors(o);});}else{var cache={},parts,b,s;for(b in o){if((parts=b.split('@'))[1]){s=parts[0];if(!cache[s]){cache[s]=Ext.select(s);}
+cache[s].on(parts[1],o[b]);}}
+cache=null;}},getScrollBarWidth:function(force){if(!Ext.isReady){return 0;}
+if(force===true||scrollWidth===null){var div=Ext.getBody().createChild('<div class="x-hide-offsets" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),child=div.child('div',true);var w1=child.offsetWidth;div.setStyle('overflow',(Ext.isWebKit||Ext.isGecko)?'auto':'scroll');var w2=child.offsetWidth;div.remove();scrollWidth=w1-w2+2;}
+return scrollWidth;},combine:function(){var as=arguments,l=as.length,r=[];for(var i=0;i<l;i++){var a=as[i];if(Ext.isArray(a)){r=r.concat(a);}else if(a.length!==undefined&&!a.substr){r=r.concat(Array.prototype.slice.call(a,0));}else{r.push(a);}}
+return r;},copyTo:function(dest,source,names){if(typeof names=='string'){names=names.split(/[,;\s]/);}
+Ext.each(names,function(name){if(source.hasOwnProperty(name)){dest[name]=source[name];}},this);return dest;},destroy:function(){Ext.each(arguments,function(arg){if(arg){if(Ext.isArray(arg)){this.destroy.apply(this,arg);}else if(typeof arg.destroy=='function'){arg.destroy();}else if(arg.dom){arg.remove();}}},this);},destroyMembers:function(o,arg1,arg2,etc){for(var i=1,a=arguments,len=a.length;i<len;i++){Ext.destroy(o[a[i]]);delete o[a[i]];}},clean:function(arr){var ret=[];Ext.each(arr,function(v){if(!!v){ret.push(v);}});return ret;},unique:function(arr){var ret=[],collect={};Ext.each(arr,function(v){if(!collect[v]){ret.push(v);}
+collect[v]=true;});return ret;},flatten:function(arr){var worker=[];function rFlatten(a){Ext.each(a,function(v){if(Ext.isArray(v)){rFlatten(v);}else{worker.push(v);}});return worker;}
+return rFlatten(arr);},min:function(arr,comp){var ret=arr[0];comp=comp||function(a,b){return a<b?-1:1;};Ext.each(arr,function(v){ret=comp(ret,v)==-1?ret:v;});return ret;},max:function(arr,comp){var ret=arr[0];comp=comp||function(a,b){return a>b?1:-1;};Ext.each(arr,function(v){ret=comp(ret,v)==1?ret:v;});return ret;},mean:function(arr){return arr.length>0?Ext.sum(arr)/arr.length:undefined;},sum:function(arr){var ret=0;Ext.each(arr,function(v){ret+=v;});return ret;},partition:function(arr,truth){var ret=[[],[]];Ext.each(arr,function(v,i,a){ret[(truth&&truth(v,i,a))||(!truth&&v)?0:1].push(v);});return ret;},invoke:function(arr,methodName){var ret=[],args=Array.prototype.slice.call(arguments,2);Ext.each(arr,function(v,i){if(v&&typeof v[methodName]=='function'){ret.push(v[methodName].apply(v,args));}else{ret.push(undefined);}});return ret;},pluck:function(arr,prop){var ret=[];Ext.each(arr,function(v){ret.push(v[prop]);});return ret;},zip:function(){var parts=Ext.partition(arguments,function(val){return typeof val!='function';}),arrs=parts[0],fn=parts[1][0],len=Ext.max(Ext.pluck(arrs,"length")),ret=[];for(var i=0;i<len;i++){ret[i]=[];if(fn){ret[i]=fn.apply(fn,Ext.pluck(arrs,i));}else{for(var j=0,aLen=arrs.length;j<aLen;j++){ret[i].push(arrs[j][i]);}}}
+return ret;},getCmp:function(id){return Ext.ComponentMgr.get(id);},useShims:E.isIE6||(E.isMac&&E.isGecko2),type:function(o){if(o===undefined||o===null){return false;}
+if(o.htmlElement){return'element';}
+var t=typeof o;if(t=='object'&&o.nodeName){switch(o.nodeType){case 1:return'element';case 3:return(/\S/).test(o.nodeValue)?'textnode':'whitespace';}}
+if(t=='object'||t=='function'){switch(o.constructor){case Array:return'array';case RegExp:return'regexp';case Date:return'date';}
+if(typeof o.length=='number'&&typeof o.item=='function'){return'nodelist';}}
+return t;},intercept:function(o,name,fn,scope){o[name]=o[name].createInterceptor(fn,scope);},callback:function(cb,scope,args,delay){if(typeof cb=='function'){if(delay){cb.defer(delay,scope,args||[]);}else{cb.apply(scope,args||[]);}}}};}());Ext.apply(Function.prototype,{createSequence:function(fcn,scope){var method=this;return(typeof fcn!='function')?this:function(){var retval=method.apply(this||window,arguments);fcn.apply(scope||this||window,arguments);return retval;};}});Ext.applyIf(String,{escape:function(string){return string.replace(/('|\\)/g,"\\$1");},leftPad:function(val,size,ch){var result=String(val);if(!ch){ch=" ";}
+while(result.length<size){result=ch+result;}
+return result;}});String.prototype.toggle=function(value,other){return this==value?other:value;};String.prototype.trim=function(){var re=/^\s+|\s+$/g;return function(){return this.replace(re,"");};}();Date.prototype.getElapsed=function(date){return Math.abs((date||new Date()).getTime()-this.getTime());};Ext.applyIf(Number.prototype,{constrain:function(min,max){return Math.min(Math.max(this,min),max);}});Ext.lib.Dom.getRegion=function(el){return Ext.lib.Region.getRegion(el);};Ext.lib.Region=function(t,r,b,l){var me=this;me.top=t;me[1]=t;me.right=r;me.bottom=b;me.left=l;me[0]=l;};Ext.lib.Region.prototype={contains:function(region){var me=this;return(region.left>=me.left&&region.right<=me.right&&region.top>=me.top&&region.bottom<=me.bottom);},getArea:function(){var me=this;return((me.bottom-me.top)*(me.right-me.left));},intersect:function(region){var me=this,t=Math.max(me.top,region.top),r=Math.min(me.right,region.right),b=Math.min(me.bottom,region.bottom),l=Math.max(me.left,region.left);if(b>=t&&r>=l){return new Ext.lib.Region(t,r,b,l);}},union:function(region){var me=this,t=Math.min(me.top,region.top),r=Math.max(me.right,region.right),b=Math.max(me.bottom,region.bottom),l=Math.min(me.left,region.left);return new Ext.lib.Region(t,r,b,l);},constrainTo:function(r){var me=this;me.top=me.top.constrain(r.top,r.bottom);me.bottom=me.bottom.constrain(r.top,r.bottom);me.left=me.left.constrain(r.left,r.right);me.right=me.right.constrain(r.left,r.right);return me;},adjust:function(t,l,b,r){var me=this;me.top+=t;me.left+=l;me.right+=r;me.bottom+=b;return me;}};Ext.lib.Region.getRegion=function(el){var p=Ext.lib.Dom.getXY(el),t=p[1],r=p[0]+el.offsetWidth,b=p[1]+el.offsetHeight,l=p[0];return new Ext.lib.Region(t,r,b,l);};Ext.lib.Point=function(x,y){if(Ext.isArray(x)){y=x[1];x=x[0];}
+var me=this;me.x=me.right=me.left=me[0]=x;me.y=me.top=me.bottom=me[1]=y;};Ext.lib.Point.prototype=new Ext.lib.Region();Ext.apply(Ext.DomHelper,function(){var pub,afterbegin='afterbegin',afterend='afterend',beforebegin='beforebegin',beforeend='beforeend',confRe=/tag|children|cn|html$/i;function doInsert(el,o,returnElement,pos,sibling,append){el=Ext.getDom(el);var newNode;if(pub.useDom){newNode=createDom(o,null);if(append){el.appendChild(newNode);}else{(sibling=='firstChild'?el:el.parentNode).insertBefore(newNode,el[sibling]||el);}}else{newNode=Ext.DomHelper.insertHtml(pos,el,Ext.DomHelper.createHtml(o));}
+return returnElement?Ext.get(newNode,true):newNode;}
+function createDom(o,parentNode){var el,doc=document,useSet,attr,val,cn;if(Ext.isArray(o)){el=doc.createDocumentFragment();for(var i=0,l=o.length;i<l;i++){createDom(o[i],el);}}else if(typeof o=='string'){el=doc.createTextNode(o);}else{el=doc.createElement(o.tag||'div');useSet=!!el.setAttribute;for(var attr in o){if(!confRe.test(attr)){val=o[attr];if(attr=='cls'){el.className=val;}else{if(useSet){el.setAttribute(attr,val);}else{el[attr]=val;}}}}
+Ext.DomHelper.applyStyles(el,o.style);if((cn=o.children||o.cn)){createDom(cn,el);}else if(o.html){el.innerHTML=o.html;}}
+if(parentNode){parentNode.appendChild(el);}
+return el;}
+pub={createTemplate:function(o){var html=Ext.DomHelper.createHtml(o);return new Ext.Template(html);},useDom:false,insertBefore:function(el,o,returnElement){return doInsert(el,o,returnElement,beforebegin);},insertAfter:function(el,o,returnElement){return doInsert(el,o,returnElement,afterend,'nextSibling');},insertFirst:function(el,o,returnElement){return doInsert(el,o,returnElement,afterbegin,'firstChild');},append:function(el,o,returnElement){return doInsert(el,o,returnElement,beforeend,'',true);},createDom:createDom};return pub;}());Ext.apply(Ext.Template.prototype,{disableFormats:false,re:/\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,argsRe:/^\s*['"](.*)["']\s*$/,compileARe:/\\/g,compileBRe:/(\r\n|\n)/g,compileCRe:/'/g,applyTemplate:function(values){var me=this,useF=me.disableFormats!==true,fm=Ext.util.Format,tpl=me;if(me.compiled){return me.compiled(values);}
+function fn(m,name,format,args){if(format&&useF){if(format.substr(0,5)=="this."){return tpl.call(format.substr(5),values[name],values);}else{if(args){var re=me.argsRe;args=args.split(',');for(var i=0,len=args.length;i<len;i++){args[i]=args[i].replace(re,"$1");}
+args=[values[name]].concat(args);}else{args=[values[name]];}
+return fm[format].apply(fm,args);}}else{return values[name]!==undefined?values[name]:"";}}
+return me.html.replace(me.re,fn);},compile:function(){var me=this,fm=Ext.util.Format,useF=me.disableFormats!==true,sep=Ext.isGecko?"+":",",body;function fn(m,name,format,args){if(format&&useF){args=args?','+args:"";if(format.substr(0,5)!="this."){format="fm."+format+'(';}else{format='this.call("'+format.substr(5)+'", ';args=", values";}}else{args='';format="(values['"+name+"'] == undefined ? '' : ";}
+return"'"+sep+format+"values['"+name+"']"+args+")"+sep+"'";}
+if(Ext.isGecko){body="this.compiled = function(values){ return '"+
+me.html.replace(me.compileARe,'\\\\').replace(me.compileBRe,'\\n').replace(me.compileCRe,"\\'").replace(me.re,fn)+"';};";}else{body=["this.compiled = function(values){ return ['"];body.push(me.html.replace(me.compileARe,'\\\\').replace(me.compileBRe,'\\n').replace(me.compileCRe,"\\'").replace(me.re,fn));body.push("'].join('');};");body=body.join('');}
+eval(body);return me;},call:function(fnName,value,allValues){return this[fnName](value,allValues);}});Ext.Template.prototype.apply=Ext.Template.prototype.applyTemplate;Ext.util.Functions={createInterceptor:function(origFn,newFn,scope){var method=origFn;if(!Ext.isFunction(newFn)){return origFn;}
+else{return function(){var me=this,args=arguments;newFn.target=me;newFn.method=origFn;return(newFn.apply(scope||me||window,args)!==false)?origFn.apply(me||window,args):null;};}},createDelegate:function(fn,obj,args,appendArgs){if(!Ext.isFunction(fn)){return fn;}
+return function(){var callArgs=args||arguments;if(appendArgs===true){callArgs=Array.prototype.slice.call(arguments,0);callArgs=callArgs.concat(args);}
+else if(Ext.isNumber(appendArgs)){callArgs=Array.prototype.slice.call(arguments,0);var applyArgs=[appendArgs,0].concat(args);Array.prototype.splice.apply(callArgs,applyArgs);}
+return fn.apply(obj||window,callArgs);};},defer:function(fn,millis,obj,args,appendArgs){fn=Ext.util.Functions.createDelegate(fn,obj,args,appendArgs);if(millis>0){return setTimeout(fn,millis);}
+fn();return 0;},createSequence:function(origFn,newFn,scope){if(!Ext.isFunction(newFn)){return origFn;}
+else{return function(){var retval=origFn.apply(this||window,arguments);newFn.apply(scope||this||window,arguments);return retval;};}}};Ext.defer=Ext.util.Functions.defer;Ext.createInterceptor=Ext.util.Functions.createInterceptor;Ext.createSequence=Ext.util.Functions.createSequence;Ext.createDelegate=Ext.util.Functions.createDelegate;Ext.apply(Ext.util.Observable.prototype,function(){function getMethodEvent(method){var e=(this.methodEvents=this.methodEvents||{})[method],returnValue,v,cancel,obj=this;if(!e){this.methodEvents[method]=e={};e.originalFn=this[method];e.methodName=method;e.before=[];e.after=[];var makeCall=function(fn,scope,args){if((v=fn.apply(scope||obj,args))!==undefined){if(typeof v=='object'){if(v.returnValue!==undefined){returnValue=v.returnValue;}else{returnValue=v;}
+cancel=!!v.cancel;}
+else
+if(v===false){cancel=true;}
+else{returnValue=v;}}};this[method]=function(){var args=Array.prototype.slice.call(arguments,0),b;returnValue=v=undefined;cancel=false;for(var i=0,len=e.before.length;i<len;i++){b=e.before[i];makeCall(b.fn,b.scope,args);if(cancel){return returnValue;}}
+if((v=e.originalFn.apply(obj,args))!==undefined){returnValue=v;}
+for(var i=0,len=e.after.length;i<len;i++){b=e.after[i];makeCall(b.fn,b.scope,args);if(cancel){return returnValue;}}
+return returnValue;};}
+return e;}
+return{beforeMethod:function(method,fn,scope){getMethodEvent.call(this,method).before.push({fn:fn,scope:scope});},afterMethod:function(method,fn,scope){getMethodEvent.call(this,method).after.push({fn:fn,scope:scope});},removeMethodListener:function(method,fn,scope){var e=this.getMethodEvent(method);for(var i=0,len=e.before.length;i<len;i++){if(e.before[i].fn==fn&&e.before[i].scope==scope){e.before.splice(i,1);return;}}
+for(var i=0,len=e.after.length;i<len;i++){if(e.after[i].fn==fn&&e.after[i].scope==scope){e.after.splice(i,1);return;}}},relayEvents:function(o,events){var me=this;function createHandler(ename){return function(){return me.fireEvent.apply(me,[ename].concat(Array.prototype.slice.call(arguments,0)));};}
+for(var i=0,len=events.length;i<len;i++){var ename=events[i];me.events[ename]=me.events[ename]||true;o.on(ename,createHandler(ename),me);}},enableBubble:function(events){var me=this;if(!Ext.isEmpty(events)){events=Ext.isArray(events)?events:Array.prototype.slice.call(arguments,0);for(var i=0,len=events.length;i<len;i++){var ename=events[i];ename=ename.toLowerCase();var ce=me.events[ename]||true;if(typeof ce=='boolean'){ce=new Ext.util.Event(me,ename);me.events[ename]=ce;}
+ce.bubble=true;}}}};}());Ext.util.Observable.capture=function(o,fn,scope){o.fireEvent=o.fireEvent.createInterceptor(fn,scope);};Ext.util.Observable.observeClass=function(c,listeners){if(c){if(!c.fireEvent){Ext.apply(c,new Ext.util.Observable());Ext.util.Observable.capture(c.prototype,c.fireEvent,c);}
+if(typeof listeners=='object'){c.on(listeners);}
+return c;}};Ext.apply(Ext.EventManager,function(){var resizeEvent,resizeTask,textEvent,textSize,D=Ext.lib.Dom,propRe=/^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,curWidth=0,curHeight=0,useKeydown=Ext.isWebKit?Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1])>=525:!((Ext.isGecko&&!Ext.isWindows)||Ext.isOpera);return{doResizeEvent:function(){var h=D.getViewHeight(),w=D.getViewWidth();if(curHeight!=h||curWidth!=w){resizeEvent.fire(curWidth=w,curHeight=h);}},onWindowResize:function(fn,scope,options){if(!resizeEvent){resizeEvent=new Ext.util.Event();resizeTask=new Ext.util.DelayedTask(this.doResizeEvent);Ext.EventManager.on(window,"resize",this.fireWindowResize,this);}
+resizeEvent.addListener(fn,scope,options);},fireWindowResize:function(){if(resizeEvent){resizeTask.delay(100);}},onTextResize:function(fn,scope,options){if(!textEvent){textEvent=new Ext.util.Event();var textEl=new Ext.Element(document.createElement('div'));textEl.dom.className='x-text-resize';textEl.dom.innerHTML='X';textEl.appendTo(document.body);textSize=textEl.dom.offsetHeight;setInterval(function(){if(textEl.dom.offsetHeight!=textSize){textEvent.fire(textSize,textSize=textEl.dom.offsetHeight);}},this.textResizeInterval);}
+textEvent.addListener(fn,scope,options);},removeResizeListener:function(fn,scope){if(resizeEvent){resizeEvent.removeListener(fn,scope);}},fireResize:function(){if(resizeEvent){resizeEvent.fire(D.getViewWidth(),D.getViewHeight());}},textResizeInterval:50,ieDeferSrc:false,getKeyEvent:function(){return useKeydown?'keydown':'keypress';},useKeydown:useKeydown};}());Ext.EventManager.on=Ext.EventManager.addListener;Ext.apply(Ext.EventObjectImpl.prototype,{BACKSPACE:8,TAB:9,NUM_CENTER:12,ENTER:13,RETURN:13,SHIFT:16,CTRL:17,CONTROL:17,ALT:18,PAUSE:19,CAPS_LOCK:20,ESC:27,SPACE:32,PAGE_UP:33,PAGEUP:33,PAGE_DOWN:34,PAGEDOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,PRINT_SCREEN:44,INSERT:45,DELETE:46,ZERO:48,ONE:49,TWO:50,THREE:51,FOUR:52,FIVE:53,SIX:54,SEVEN:55,EIGHT:56,NINE:57,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,CONTEXT_MENU:93,NUM_ZERO:96,NUM_ONE:97,NUM_TWO:98,NUM_THREE:99,NUM_FOUR:100,NUM_FIVE:101,NUM_SIX:102,NUM_SEVEN:103,NUM_EIGHT:104,NUM_NINE:105,NUM_MULTIPLY:106,NUM_PLUS:107,NUM_MINUS:109,NUM_PERIOD:110,NUM_DIVISION:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,isNavKeyPress:function(){var me=this,k=this.normalizeKey(me.keyCode);return(k>=33&&k<=40)||k==me.RETURN||k==me.TAB||k==me.ESC;},isSpecialKey:function(){var k=this.normalizeKey(this.keyCode);return(this.type=='keypress'&&this.ctrlKey)||this.isNavKeyPress()||(k==this.BACKSPACE)||(k>=16&&k<=20)||(k>=44&&k<=46);},getPoint:function(){return new Ext.lib.Point(this.xy[0],this.xy[1]);},hasModifier:function(){return((this.ctrlKey||this.altKey)||this.shiftKey);}});Ext.Element.addMethods({swallowEvent:function(eventName,preventDefault){var me=this;function fn(e){e.stopPropagation();if(preventDefault){e.preventDefault();}}
+if(Ext.isArray(eventName)){Ext.each(eventName,function(e){me.on(e,fn);});return me;}
+me.on(eventName,fn);return me;},relayEvent:function(eventName,observable){this.on(eventName,function(e){observable.fireEvent(eventName,e);});},clean:function(forceReclean){var me=this,dom=me.dom,n=dom.firstChild,ni=-1;if(Ext.Element.data(dom,'isCleaned')&&forceReclean!==true){return me;}
+while(n){var nx=n.nextSibling;if(n.nodeType==3&&!(/\S/.test(n.nodeValue))){dom.removeChild(n);}else{n.nodeIndex=++ni;}
+n=nx;}
+Ext.Element.data(dom,'isCleaned',true);return me;},load:function(){var updateManager=this.getUpdater();updateManager.update.apply(updateManager,arguments);return this;},getUpdater:function(){return this.updateManager||(this.updateManager=new Ext.Updater(this));},update:function(html,loadScripts,callback){if(!this.dom){return this;}
+html=html||"";if(loadScripts!==true){this.dom.innerHTML=html;if(typeof callback=='function'){callback();}
+return this;}
+var id=Ext.id(),dom=this.dom;html+='<span id="'+id+'"></span>';Ext.lib.Event.onAvailable(id,function(){var DOC=document,hd=DOC.getElementsByTagName("head")[0],re=/(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,srcRe=/\ssrc=([\'\"])(.*?)\1/i,typeRe=/\stype=([\'\"])(.*?)\1/i,match,attrs,srcMatch,typeMatch,el,s;while((match=re.exec(html))){attrs=match[1];srcMatch=attrs?attrs.match(srcRe):false;if(srcMatch&&srcMatch[2]){s=DOC.createElement("script");s.src=srcMatch[2];typeMatch=attrs.match(typeRe);if(typeMatch&&typeMatch[2]){s.type=typeMatch[2];}
+hd.appendChild(s);}else if(match[2]&&match[2].length>0){if(window.execScript){window.execScript(match[2]);}else{window.eval(match[2]);}}}
+el=DOC.getElementById(id);if(el){Ext.removeNode(el);}
+if(typeof callback=='function'){callback();}});dom.innerHTML=html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,"");return this;},removeAllListeners:function(){this.removeAnchor();Ext.EventManager.removeAll(this.dom);return this;},createProxy:function(config,renderTo,matchBox){config=(typeof config=='object')?config:{tag:"div",cls:config};var me=this,proxy=renderTo?Ext.DomHelper.append(renderTo,config,true):Ext.DomHelper.insertBefore(me.dom,config,true);if(matchBox&&me.setBox&&me.getBox){proxy.setBox(me.getBox());}
+return proxy;}});Ext.Element.prototype.getUpdateManager=Ext.Element.prototype.getUpdater;Ext.Element.addMethods({getAnchorXY:function(anchor,local,s){anchor=(anchor||"tl").toLowerCase();s=s||{};var me=this,vp=me.dom==document.body||me.dom==document,w=s.width||vp?Ext.lib.Dom.getViewWidth():me.getWidth(),h=s.height||vp?Ext.lib.Dom.getViewHeight():me.getHeight(),xy,r=Math.round,o=me.getXY(),scroll=me.getScroll(),extraX=vp?scroll.left:!local?o[0]:0,extraY=vp?scroll.top:!local?o[1]:0,hash={c:[r(w*0.5),r(h*0.5)],t:[r(w*0.5),0],l:[0,r(h*0.5)],r:[w,r(h*0.5)],b:[r(w*0.5),h],tl:[0,0],bl:[0,h],br:[w,h],tr:[w,0]};xy=hash[anchor];return[xy[0]+extraX,xy[1]+extraY];},anchorTo:function(el,alignment,offsets,animate,monitorScroll,callback){var me=this,dom=me.dom,scroll=!Ext.isEmpty(monitorScroll),action=function(){Ext.fly(dom).alignTo(el,alignment,offsets,animate);Ext.callback(callback,Ext.fly(dom));},anchor=this.getAnchor();this.removeAnchor();Ext.apply(anchor,{fn:action,scroll:scroll});Ext.EventManager.onWindowResize(action,null);if(scroll){Ext.EventManager.on(window,'scroll',action,null,{buffer:!isNaN(monitorScroll)?monitorScroll:50});}
+action.call(me);return me;},removeAnchor:function(){var me=this,anchor=this.getAnchor();if(anchor&&anchor.fn){Ext.EventManager.removeResizeListener(anchor.fn);if(anchor.scroll){Ext.EventManager.un(window,'scroll',anchor.fn);}
+delete anchor.fn;}
+return me;},getAnchor:function(){var data=Ext.Element.data,dom=this.dom;if(!dom){return;}
+var anchor=data(dom,'_anchor');if(!anchor){anchor=data(dom,'_anchor',{});}
+return anchor;},getAlignToXY:function(el,p,o){el=Ext.get(el);if(!el||!el.dom){throw"Element.alignToXY with an element that doesn't exist";}
+o=o||[0,0];p=(!p||p=="?"?"tl-bl?":(!(/-/).test(p)&&p!==""?"tl-"+p:p||"tl-bl")).toLowerCase();var me=this,d=me.dom,a1,a2,x,y,w,h,r,dw=Ext.lib.Dom.getViewWidth()-10,dh=Ext.lib.Dom.getViewHeight()-10,p1y,p1x,p2y,p2x,swapY,swapX,doc=document,docElement=doc.documentElement,docBody=doc.body,scrollX=(docElement.scrollLeft||docBody.scrollLeft||0)+5,scrollY=(docElement.scrollTop||docBody.scrollTop||0)+5,c=false,p1="",p2="",m=p.match(/^([a-z]+)-([a-z]+)(\?)?$/);if(!m){throw"Element.alignTo with an invalid alignment "+p;}
+p1=m[1];p2=m[2];c=!!m[3];a1=me.getAnchorXY(p1,true);a2=el.getAnchorXY(p2,false);x=a2[0]-a1[0]+o[0];y=a2[1]-a1[1]+o[1];if(c){w=me.getWidth();h=me.getHeight();r=el.getRegion();p1y=p1.charAt(0);p1x=p1.charAt(p1.length-1);p2y=p2.charAt(0);p2x=p2.charAt(p2.length-1);swapY=((p1y=="t"&&p2y=="b")||(p1y=="b"&&p2y=="t"));swapX=((p1x=="r"&&p2x=="l")||(p1x=="l"&&p2x=="r"));if(x+w>dw+scrollX){x=swapX?r.left-w:dw+scrollX-w;}
+if(x<scrollX){x=swapX?r.right:scrollX;}
+if(y+h>dh+scrollY){y=swapY?r.top-h:dh+scrollY-h;}
+if(y<scrollY){y=swapY?r.bottom:scrollY;}}
+return[x,y];},alignTo:function(element,position,offsets,animate){var me=this;return me.setXY(me.getAlignToXY(element,position,offsets),me.preanim&&!!animate?me.preanim(arguments,3):false);},adjustForConstraints:function(xy,parent,offsets){return this.getConstrainToXY(parent||document,false,offsets,xy)||xy;},getConstrainToXY:function(el,local,offsets,proposedXY){var os={top:0,left:0,bottom:0,right:0};return function(el,local,offsets,proposedXY){el=Ext.get(el);offsets=offsets?Ext.applyIf(offsets,os):os;var vw,vh,vx=0,vy=0;if(el.dom==document.body||el.dom==document){vw=Ext.lib.Dom.getViewWidth();vh=Ext.lib.Dom.getViewHeight();}else{vw=el.dom.clientWidth;vh=el.dom.clientHeight;if(!local){var vxy=el.getXY();vx=vxy[0];vy=vxy[1];}}
+var s=el.getScroll();vx+=offsets.left+s.left;vy+=offsets.top+s.top;vw-=offsets.right;vh-=offsets.bottom;var vr=vx+vw,vb=vy+vh,xy=proposedXY||(!local?this.getXY():[this.getLeft(true),this.getTop(true)]),x=xy[0],y=xy[1],offset=this.getConstrainOffset(),w=this.dom.offsetWidth+offset,h=this.dom.offsetHeight+offset;var moved=false;if((x+w)>vr){x=vr-w;moved=true;}
+if((y+h)>vb){y=vb-h;moved=true;}
+if(x<vx){x=vx;moved=true;}
+if(y<vy){y=vy;moved=true;}
+return moved?[x,y]:false;};}(),getConstrainOffset:function(){return 0;},getCenterXY:function(){return this.getAlignToXY(document,'c-c');},center:function(centerIn){return this.alignTo(centerIn||document,'c-c');}});Ext.Element.addMethods({select:function(selector,unique){return Ext.Element.select(selector,unique,this.dom);}});Ext.apply(Ext.Element.prototype,function(){var GETDOM=Ext.getDom,GET=Ext.get,DH=Ext.DomHelper;return{insertSibling:function(el,where,returnDom){var me=this,rt,isAfter=(where||'before').toLowerCase()=='after',insertEl;if(Ext.isArray(el)){insertEl=me;Ext.each(el,function(e){rt=Ext.fly(insertEl,'_internal').insertSibling(e,where,returnDom);if(isAfter){insertEl=rt;}});return rt;}
+el=el||{};if(el.nodeType||el.dom){rt=me.dom.parentNode.insertBefore(GETDOM(el),isAfter?me.dom.nextSibling:me.dom);if(!returnDom){rt=GET(rt);}}else{if(isAfter&&!me.dom.nextSibling){rt=DH.append(me.dom.parentNode,el,!returnDom);}else{rt=DH[isAfter?'insertAfter':'insertBefore'](me.dom,el,!returnDom);}}
+return rt;}};}());Ext.Element.boxMarkup='<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';Ext.Element.addMethods(function(){var INTERNAL="_internal",pxMatch=/(\d+\.?\d+)px/;return{applyStyles:function(style){Ext.DomHelper.applyStyles(this.dom,style);return this;},getStyles:function(){var ret={};Ext.each(arguments,function(v){ret[v]=this.getStyle(v);},this);return ret;},setOverflow:function(v){var dom=this.dom;if(v=='auto'&&Ext.isMac&&Ext.isGecko2){dom.style.overflow='hidden';(function(){dom.style.overflow='auto';}).defer(1);}else{dom.style.overflow=v;}},boxWrap:function(cls){cls=cls||'x-box';var el=Ext.get(this.insertHtml("beforeBegin","<div class='"+cls+"'>"+String.format(Ext.Element.boxMarkup,cls)+"</div>"));Ext.DomQuery.selectNode('.'+cls+'-mc',el.dom).appendChild(this.dom);return el;},setSize:function(width,height,animate){var me=this;if(typeof width=='object'){height=width.height;width=width.width;}
+width=me.adjustWidth(width);height=me.adjustHeight(height);if(!animate||!me.anim){me.dom.style.width=me.addUnits(width);me.dom.style.height=me.addUnits(height);}else{me.anim({width:{to:width},height:{to:height}},me.preanim(arguments,2));}
+return me;},getComputedHeight:function(){var me=this,h=Math.max(me.dom.offsetHeight,me.dom.clientHeight);if(!h){h=parseFloat(me.getStyle('height'))||0;if(!me.isBorderBox()){h+=me.getFrameWidth('tb');}}
+return h;},getComputedWidth:function(){var w=Math.max(this.dom.offsetWidth,this.dom.clientWidth);if(!w){w=parseFloat(this.getStyle('width'))||0;if(!this.isBorderBox()){w+=this.getFrameWidth('lr');}}
+return w;},getFrameWidth:function(sides,onlyContentBox){return onlyContentBox&&this.isBorderBox()?0:(this.getPadding(sides)+this.getBorderWidth(sides));},addClassOnOver:function(className){this.hover(function(){Ext.fly(this,INTERNAL).addClass(className);},function(){Ext.fly(this,INTERNAL).removeClass(className);});return this;},addClassOnFocus:function(className){this.on("focus",function(){Ext.fly(this,INTERNAL).addClass(className);},this.dom);this.on("blur",function(){Ext.fly(this,INTERNAL).removeClass(className);},this.dom);return this;},addClassOnClick:function(className){var dom=this.dom;this.on("mousedown",function(){Ext.fly(dom,INTERNAL).addClass(className);var d=Ext.getDoc(),fn=function(){Ext.fly(dom,INTERNAL).removeClass(className);d.removeListener("mouseup",fn);};d.on("mouseup",fn);});return this;},getViewSize:function(){var doc=document,d=this.dom,isDoc=(d==doc||d==doc.body);if(isDoc){var extdom=Ext.lib.Dom;return{width:extdom.getViewWidth(),height:extdom.getViewHeight()};}else{return{width:d.clientWidth,height:d.clientHeight};}},getStyleSize:function(){var me=this,w,h,doc=document,d=this.dom,isDoc=(d==doc||d==doc.body),s=d.style;if(isDoc){var extdom=Ext.lib.Dom;return{width:extdom.getViewWidth(),height:extdom.getViewHeight()};}
+if(s.width&&s.width!='auto'){w=parseFloat(s.width);if(me.isBorderBox()){w-=me.getFrameWidth('lr');}}
+if(s.height&&s.height!='auto'){h=parseFloat(s.height);if(me.isBorderBox()){h-=me.getFrameWidth('tb');}}
+return{width:w||me.getWidth(true),height:h||me.getHeight(true)};},getSize:function(contentSize){return{width:this.getWidth(contentSize),height:this.getHeight(contentSize)};},repaint:function(){var dom=this.dom;this.addClass("x-repaint");setTimeout(function(){Ext.fly(dom).removeClass("x-repaint");},1);return this;},unselectable:function(){this.dom.unselectable="on";return this.swallowEvent("selectstart",true).applyStyles("-moz-user-select:none;-khtml-user-select:none;").addClass("x-unselectable");},getMargins:function(side){var me=this,key,hash={t:"top",l:"left",r:"right",b:"bottom"},o={};if(!side){for(key in me.margins){o[hash[key]]=parseFloat(me.getStyle(me.margins[key]))||0;}
+return o;}else{return me.addStyles.call(me,side,me.margins);}}};}());Ext.Element.addMethods({setBox:function(box,adjust,animate){var me=this,w=box.width,h=box.height;if((adjust&&!me.autoBoxAdjust)&&!me.isBorderBox()){w-=(me.getBorderWidth("lr")+me.getPadding("lr"));h-=(me.getBorderWidth("tb")+me.getPadding("tb"));}
+me.setBounds(box.x,box.y,w,h,me.animTest.call(me,arguments,animate,2));return me;},getBox:function(contentBox,local){var me=this,xy,left,top,getBorderWidth=me.getBorderWidth,getPadding=me.getPadding,l,r,t,b;if(!local){xy=me.getXY();}else{left=parseInt(me.getStyle("left"),10)||0;top=parseInt(me.getStyle("top"),10)||0;xy=[left,top];}
+var el=me.dom,w=el.offsetWidth,h=el.offsetHeight,bx;if(!contentBox){bx={x:xy[0],y:xy[1],0:xy[0],1:xy[1],width:w,height:h};}else{l=getBorderWidth.call(me,"l")+getPadding.call(me,"l");r=getBorderWidth.call(me,"r")+getPadding.call(me,"r");t=getBorderWidth.call(me,"t")+getPadding.call(me,"t");b=getBorderWidth.call(me,"b")+getPadding.call(me,"b");bx={x:xy[0]+l,y:xy[1]+t,0:xy[0]+l,1:xy[1]+t,width:w-(l+r),height:h-(t+b)};}
+bx.right=bx.x+bx.width;bx.bottom=bx.y+bx.height;return bx;},move:function(direction,distance,animate){var me=this,xy=me.getXY(),x=xy[0],y=xy[1],left=[x-distance,y],right=[x+distance,y],top=[x,y-distance],bottom=[x,y+distance],hash={l:left,left:left,r:right,right:right,t:top,top:top,up:top,b:bottom,bottom:bottom,down:bottom};direction=direction.toLowerCase();me.moveTo(hash[direction][0],hash[direction][1],me.animTest.call(me,arguments,animate,2));},setLeftTop:function(left,top){var me=this,style=me.dom.style;style.left=me.addUnits(left);style.top=me.addUnits(top);return me;},getRegion:function(){return Ext.lib.Dom.getRegion(this.dom);},setBounds:function(x,y,width,height,animate){var me=this;if(!animate||!me.anim){me.setSize(width,height);me.setLocation(x,y);}else{me.anim({points:{to:[x,y]},width:{to:me.adjustWidth(width)},height:{to:me.adjustHeight(height)}},me.preanim(arguments,4),'motion');}
+return me;},setRegion:function(region,animate){return this.setBounds(region.left,region.top,region.right-region.left,region.bottom-region.top,this.animTest.call(this,arguments,animate,1));}});Ext.Element.addMethods({scrollTo:function(side,value,animate){var top=/top/i.test(side),me=this,dom=me.dom,prop;if(!animate||!me.anim){prop='scroll'+(top?'Top':'Left');dom[prop]=value;}
+else{prop='scroll'+(top?'Left':'Top');me.anim({scroll:{to:top?[dom[prop],value]:[value,dom[prop]]}},me.preanim(arguments,2),'scroll');}
+return me;},scrollIntoView:function(container,hscroll){var c=Ext.getDom(container)||Ext.getBody().dom,el=this.dom,o=this.getOffsetsTo(c),l=o[0]+c.scrollLeft,t=o[1]+c.scrollTop,b=t+el.offsetHeight,r=l+el.offsetWidth,ch=c.clientHeight,ct=parseInt(c.scrollTop,10),cl=parseInt(c.scrollLeft,10),cb=ct+ch,cr=cl+c.clientWidth;if(el.offsetHeight>ch||t<ct){c.scrollTop=t;}
+else if(b>cb){c.scrollTop=b-ch;}
+c.scrollTop=c.scrollTop;if(hscroll!==false){if(el.offsetWidth>c.clientWidth||l<cl){c.scrollLeft=l;}
+else if(r>cr){c.scrollLeft=r-c.clientWidth;}
+c.scrollLeft=c.scrollLeft;}
+return this;},scrollChildIntoView:function(child,hscroll){Ext.fly(child,'_scrollChildIntoView').scrollIntoView(this,hscroll);},scroll:function(direction,distance,animate){if(!this.isScrollable()){return false;}
+var el=this.dom,l=el.scrollLeft,t=el.scrollTop,w=el.scrollWidth,h=el.scrollHeight,cw=el.clientWidth,ch=el.clientHeight,scrolled=false,v,hash={l:Math.min(l+distance,w-cw),r:v=Math.max(l-distance,0),t:Math.max(t-distance,0),b:Math.min(t+distance,h-ch)};hash.d=hash.b;hash.u=hash.t;direction=direction.substr(0,1);if((v=hash[direction])>-1){scrolled=true;this.scrollTo(direction=='l'||direction=='r'?'left':'top',v,this.preanim(arguments,2));}
+return scrolled;}});Ext.Element.addMethods(function(){var VISIBILITY="visibility",DISPLAY="display",HIDDEN="hidden",NONE="none",XMASKED="x-masked",XMASKEDRELATIVE="x-masked-relative",data=Ext.Element.data;return{isVisible:function(deep){var vis=!this.isStyle(VISIBILITY,HIDDEN)&&!this.isStyle(DISPLAY,NONE),p=this.dom.parentNode;if(deep!==true||!vis){return vis;}
+while(p&&!(/^body/i.test(p.tagName))){if(!Ext.fly(p,'_isVisible').isVisible()){return false;}
+p=p.parentNode;}
+return true;},isDisplayed:function(){return!this.isStyle(DISPLAY,NONE);},enableDisplayMode:function(display){this.setVisibilityMode(Ext.Element.DISPLAY);if(!Ext.isEmpty(display)){data(this.dom,'originalDisplay',display);}
+return this;},mask:function(msg,msgCls){var me=this,dom=me.dom,dh=Ext.DomHelper,EXTELMASKMSG="ext-el-mask-msg",el,mask;if(!(/^body/i.test(dom.tagName)&&me.getStyle('position')=='static')){me.addClass(XMASKEDRELATIVE);}
+if(el=data(dom,'maskMsg')){el.remove();}
+if(el=data(dom,'mask')){el.remove();}
+mask=dh.append(dom,{cls:"ext-el-mask"},true);data(dom,'mask',mask);me.addClass(XMASKED);mask.setDisplayed(true);if(typeof msg=='string'){var mm=dh.append(dom,{cls:EXTELMASKMSG,cn:{tag:'div'}},true);data(dom,'maskMsg',mm);mm.dom.className=msgCls?EXTELMASKMSG+" "+msgCls:EXTELMASKMSG;mm.dom.firstChild.innerHTML=msg;mm.setDisplayed(true);mm.center(me);}
+if(Ext.isIE&&!(Ext.isIE7&&Ext.isStrict)&&me.getStyle('height')=='auto'){mask.setSize(undefined,me.getHeight());}
+return mask;},unmask:function(){var me=this,dom=me.dom,mask=data(dom,'mask'),maskMsg=data(dom,'maskMsg');if(mask){if(maskMsg){maskMsg.remove();data(dom,'maskMsg',undefined);}
+mask.remove();data(dom,'mask',undefined);me.removeClass([XMASKED,XMASKEDRELATIVE]);}},isMasked:function(){var m=data(this.dom,'mask');return m&&m.isVisible();},createShim:function(){var el=document.createElement('iframe'),shim;el.frameBorder='0';el.className='ext-shim';el.src=Ext.SSL_SECURE_URL;shim=Ext.get(this.dom.parentNode.insertBefore(el,this.dom));shim.autoBoxAdjust=false;return shim;}};}());Ext.Element.addMethods({addKeyListener:function(key,fn,scope){var config;if(typeof key!='object'||Ext.isArray(key)){config={key:key,fn:fn,scope:scope};}else{config={key:key.key,shift:key.shift,ctrl:key.ctrl,alt:key.alt,fn:fn,scope:scope};}
+return new Ext.KeyMap(this,config);},addKeyMap:function(config){return new Ext.KeyMap(this,config);}});Ext.CompositeElementLite.importElementMethods();Ext.apply(Ext.CompositeElementLite.prototype,{addElements:function(els,root){if(!els){return this;}
+if(typeof els=="string"){els=Ext.Element.selectorFunction(els,root);}
+var yels=this.elements;Ext.each(els,function(e){yels.push(Ext.get(e));});return this;},first:function(){return this.item(0);},last:function(){return this.item(this.getCount()-1);},contains:function(el){return this.indexOf(el)!=-1;},removeElement:function(keys,removeDom){var me=this,els=this.elements,el;Ext.each(keys,function(val){if((el=(els[val]||els[val=me.indexOf(val)]))){if(removeDom){if(el.dom){el.remove();}else{Ext.removeNode(el);}}
+els.splice(val,1);}});return this;}});Ext.CompositeElement=Ext.extend(Ext.CompositeElementLite,{constructor:function(els,root){this.elements=[];this.add(els,root);},getElement:function(el){return el;},transformElement:function(el){return Ext.get(el);}});Ext.Element.select=function(selector,unique,root){var els;if(typeof selector=="string"){els=Ext.Element.selectorFunction(selector,root);}else if(selector.length!==undefined){els=selector;}else{throw"Invalid selector";}
+return(unique===true)?new Ext.CompositeElement(els):new Ext.CompositeElementLite(els);};Ext.select=Ext.Element.select;Ext.UpdateManager=Ext.Updater=Ext.extend(Ext.util.Observable,function(){var BEFOREUPDATE="beforeupdate",UPDATE="update",FAILURE="failure";function processSuccess(response){var me=this;me.transaction=null;if(response.argument.form&&response.argument.reset){try{response.argument.form.reset();}catch(e){}}
+if(me.loadScripts){me.renderer.render(me.el,response,me,updateComplete.createDelegate(me,[response]));}else{me.renderer.render(me.el,response,me);updateComplete.call(me,response);}}
+function updateComplete(response,type,success){this.fireEvent(type||UPDATE,this.el,response);if(Ext.isFunction(response.argument.callback)){response.argument.callback.call(response.argument.scope,this.el,Ext.isEmpty(success)?true:false,response,response.argument.options);}}
+function processFailure(response){updateComplete.call(this,response,FAILURE,!!(this.transaction=null));}
+return{constructor:function(el,forceNew){var me=this;el=Ext.get(el);if(!forceNew&&el.updateManager){return el.updateManager;}
+me.el=el;me.defaultUrl=null;me.addEvents(BEFOREUPDATE,UPDATE,FAILURE);Ext.apply(me,Ext.Updater.defaults);me.transaction=null;me.refreshDelegate=me.refresh.createDelegate(me);me.updateDelegate=me.update.createDelegate(me);me.formUpdateDelegate=(me.formUpdate||function(){}).createDelegate(me);me.renderer=me.renderer||me.getDefaultRenderer();Ext.Updater.superclass.constructor.call(me);},setRenderer:function(renderer){this.renderer=renderer;},getRenderer:function(){return this.renderer;},getDefaultRenderer:function(){return new Ext.Updater.BasicRenderer();},setDefaultUrl:function(defaultUrl){this.defaultUrl=defaultUrl;},getEl:function(){return this.el;},update:function(url,params,callback,discardUrl){var me=this,cfg,callerScope;if(me.fireEvent(BEFOREUPDATE,me.el,url,params)!==false){if(Ext.isObject(url)){cfg=url;url=cfg.url;params=params||cfg.params;callback=callback||cfg.callback;discardUrl=discardUrl||cfg.discardUrl;callerScope=cfg.scope;if(!Ext.isEmpty(cfg.nocache)){me.disableCaching=cfg.nocache;};if(!Ext.isEmpty(cfg.text)){me.indicatorText='<div class="loading-indicator">'+cfg.text+"</div>";};if(!Ext.isEmpty(cfg.scripts)){me.loadScripts=cfg.scripts;};if(!Ext.isEmpty(cfg.timeout)){me.timeout=cfg.timeout;};}
+me.showLoading();if(!discardUrl){me.defaultUrl=url;}
+if(Ext.isFunction(url)){url=url.call(me);}
+var o=Ext.apply({},{url:url,params:(Ext.isFunction(params)&&callerScope)?params.createDelegate(callerScope):params,success:processSuccess,failure:processFailure,scope:me,callback:undefined,timeout:(me.timeout*1000),disableCaching:me.disableCaching,argument:{"options":cfg,"url":url,"form":null,"callback":callback,"scope":callerScope||window,"params":params}},cfg);me.transaction=Ext.Ajax.request(o);}},formUpdate:function(form,url,reset,callback){var me=this;if(me.fireEvent(BEFOREUPDATE,me.el,form,url)!==false){if(Ext.isFunction(url)){url=url.call(me);}
+form=Ext.getDom(form);me.transaction=Ext.Ajax.request({form:form,url:url,success:processSuccess,failure:processFailure,scope:me,timeout:(me.timeout*1000),argument:{"url":url,"form":form,"callback":callback,"reset":reset}});me.showLoading.defer(1,me);}},startAutoRefresh:function(interval,url,params,callback,refreshNow){var me=this;if(refreshNow){me.update(url||me.defaultUrl,params,callback,true);}
+if(me.autoRefreshProcId){clearInterval(me.autoRefreshProcId);}
+me.autoRefreshProcId=setInterval(me.update.createDelegate(me,[url||me.defaultUrl,params,callback,true]),interval*1000);},stopAutoRefresh:function(){if(this.autoRefreshProcId){clearInterval(this.autoRefreshProcId);delete this.autoRefreshProcId;}},isAutoRefreshing:function(){return!!this.autoRefreshProcId;},showLoading:function(){if(this.showLoadIndicator){this.el.dom.innerHTML=this.indicatorText;}},abort:function(){if(this.transaction){Ext.Ajax.abort(this.transaction);}},isUpdating:function(){return this.transaction?Ext.Ajax.isLoading(this.transaction):false;},refresh:function(callback){if(this.defaultUrl){this.update(this.defaultUrl,null,callback,true);}}};}());Ext.Updater.defaults={timeout:30,disableCaching:false,showLoadIndicator:true,indicatorText:'<div class="loading-indicator">Loading...</div>',loadScripts:false,sslBlankUrl:Ext.SSL_SECURE_URL};Ext.Updater.updateElement=function(el,url,params,options){var um=Ext.get(el).getUpdater();Ext.apply(um,options);um.update(url,params,options?options.callback:null);};Ext.Updater.BasicRenderer=function(){};Ext.Updater.BasicRenderer.prototype={render:function(el,response,updateManager,callback){el.update(response.responseText,updateManager.loadScripts,callback);}};(function(){Date.useStrict=false;function xf(format){var args=Array.prototype.slice.call(arguments,1);return format.replace(/\{(\d+)\}/g,function(m,i){return args[i];});}
+Date.formatCodeToRegex=function(character,currentGroup){var p=Date.parseCodes[character];if(p){p=typeof p=='function'?p():p;Date.parseCodes[character]=p;}
+return p?Ext.applyIf({c:p.c?xf(p.c,currentGroup||"{0}"):p.c},p):{g:0,c:null,s:Ext.escapeRe(character)};};var $f=Date.formatCodeToRegex;Ext.apply(Date,{parseFunctions:{"M$":function(input,strict){var re=new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');var r=(input||'').match(re);return r?new Date(((r[1]||'')+r[2])*1):null;}},parseRegexes:[],formatFunctions:{"M$":function(){return'\\/Date('+this.getTime()+')\\/';}},y2kYear:50,MILLI:"ms",SECOND:"s",MINUTE:"mi",HOUR:"h",DAY:"d",MONTH:"mo",YEAR:"y",defaults:{},dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNumbers:{Jan:0,Feb:1,Mar:2,Apr:3,May:4,Jun:5,Jul:6,Aug:7,Sep:8,Oct:9,Nov:10,Dec:11},getShortMonthName:function(month){return Date.monthNames[month].substring(0,3);},getShortDayName:function(day){return Date.dayNames[day].substring(0,3);},getMonthNumber:function(name){return Date.monthNumbers[name.substring(0,1).toUpperCase()+name.substring(1,3).toLowerCase()];},formatCodes:{d:"String.leftPad(this.getDate(), 2, '0')",D:"Date.getShortDayName(this.getDay())",j:"this.getDate()",l:"Date.dayNames[this.getDay()]",N:"(this.getDay() ? this.getDay() : 7)",S:"this.getSuffix()",w:"this.getDay()",z:"this.getDayOfYear()",W:"String.leftPad(this.getWeekOfYear(), 2, '0')",F:"Date.monthNames[this.getMonth()]",m:"String.leftPad(this.getMonth() + 1, 2, '0')",M:"Date.getShortMonthName(this.getMonth())",n:"(this.getMonth() + 1)",t:"this.getDaysInMonth()",L:"(this.isLeapYear() ? 1 : 0)",o:"(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",Y:"String.leftPad(this.getFullYear(), 4, '0')",y:"('' + this.getFullYear()).substring(2, 4)",a:"(this.getHours() < 12 ? 'am' : 'pm')",A:"(this.getHours() < 12 ? 'AM' : 'PM')",g:"((this.getHours() % 12) ? this.getHours() % 12 : 12)",G:"this.getHours()",h:"String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",H:"String.leftPad(this.getHours(), 2, '0')",i:"String.leftPad(this.getMinutes(), 2, '0')",s:"String.leftPad(this.getSeconds(), 2, '0')",u:"String.leftPad(this.getMilliseconds(), 3, '0')",O:"this.getGMTOffset()",P:"this.getGMTOffset(true)",T:"this.getTimezone()",Z:"(this.getTimezoneOffset() * -60)",c:function(){for(var c="Y-m-dTH:i:sP",code=[],i=0,l=c.length;i<l;++i){var e=c.charAt(i);code.push(e=="T"?"'T'":Date.getFormatCode(e));}
+return code.join(" + ");},U:"Math.round(this.getTime() / 1000)"},isValid:function(y,m,d,h,i,s,ms){h=h||0;i=i||0;s=s||0;ms=ms||0;var dt=new Date(y<100?100:y,m-1,d,h,i,s,ms).add(Date.YEAR,y<100?y-100:0);return y==dt.getFullYear()&&m==dt.getMonth()+1&&d==dt.getDate()&&h==dt.getHours()&&i==dt.getMinutes()&&s==dt.getSeconds()&&ms==dt.getMilliseconds();},parseDate:function(input,format,strict){var p=Date.parseFunctions;if(p[format]==null){Date.createParser(format);}
+return p[format](input,Ext.isDefined(strict)?strict:Date.useStrict);},getFormatCode:function(character){var f=Date.formatCodes[character];if(f){f=typeof f=='function'?f():f;Date.formatCodes[character]=f;}
+return f||("'"+String.escape(character)+"'");},createFormat:function(format){var code=[],special=false,ch='';for(var i=0;i<format.length;++i){ch=format.charAt(i);if(!special&&ch=="\\"){special=true;}else if(special){special=false;code.push("'"+String.escape(ch)+"'");}else{code.push(Date.getFormatCode(ch));}}
+Date.formatFunctions[format]=new Function("return "+code.join('+'));},createParser:function(){var code=["var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,","def = Date.defaults,","results = String(input).match(Date.parseRegexes[{0}]);","if(results){","{1}","if(u != null){","v = new Date(u * 1000);","}else{","dt = (new Date()).clearTime();","y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));","m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));","d = Ext.num(d, Ext.num(def.d, dt.getDate()));","h  = Ext.num(h, Ext.num(def.h, dt.getHours()));","i  = Ext.num(i, Ext.num(def.i, dt.getMinutes()));","s  = Ext.num(s, Ext.num(def.s, dt.getSeconds()));","ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));","if(z >= 0 && y >= 0){","v = new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);","v = !strict? v : (strict === true && (z <= 364 || (v.isLeapYear() && z <= 365))? v.add(Date.DAY, z) : null);","}else if(strict === true && !Date.isValid(y, m + 1, d, h, i, s, ms)){","v = null;","}else{","v = new Date(y < 100 ? 100 : y, m, d, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);","}","}","}","if(v){","if(zz != null){","v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);","}else if(o){","v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));","}","}","return v;"].join('\n');return function(format){var regexNum=Date.parseRegexes.length,currentGroup=1,calc=[],regex=[],special=false,ch="",i=0,obj,last;for(;i<format.length;++i){ch=format.charAt(i);if(!special&&ch=="\\"){special=true;}else if(special){special=false;regex.push(String.escape(ch));}else{obj=$f(ch,currentGroup);currentGroup+=obj.g;regex.push(obj.s);if(obj.g&&obj.c){if(obj.calcLast){last=obj.c;}else{calc.push(obj.c);}}}}
+if(last){calc.push(last);}
+Date.parseRegexes[regexNum]=new RegExp("^"+regex.join('')+"$",'i');Date.parseFunctions[format]=new Function("input","strict",xf(code,regexNum,calc.join('')));};}(),parseCodes:{d:{g:1,c:"d = parseInt(results[{0}], 10);\n",s:"(\\d{2})"},j:{g:1,c:"d = parseInt(results[{0}], 10);\n",s:"(\\d{1,2})"},D:function(){for(var a=[],i=0;i<7;a.push(Date.getShortDayName(i)),++i);return{g:0,c:null,s:"(?:"+a.join("|")+")"};},l:function(){return{g:0,c:null,s:"(?:"+Date.dayNames.join("|")+")"};},N:{g:0,c:null,s:"[1-7]"},S:{g:0,c:null,s:"(?:st|nd|rd|th)"},w:{g:0,c:null,s:"[0-6]"},z:{g:1,c:"z = parseInt(results[{0}], 10);\n",s:"(\\d{1,3})"},W:{g:0,c:null,s:"(?:\\d{2})"},F:function(){return{g:1,c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n",s:"("+Date.monthNames.join("|")+")"};},M:function(){for(var a=[],i=0;i<12;a.push(Date.getShortMonthName(i)),++i);return Ext.applyIf({s:"("+a.join("|")+")"},$f("F"));},m:{g:1,c:"m = parseInt(results[{0}], 10) - 1;\n",s:"(\\d{2})"},n:{g:1,c:"m = parseInt(results[{0}], 10) - 1;\n",s:"(\\d{1,2})"},t:{g:0,c:null,s:"(?:\\d{2})"},L:{g:0,c:null,s:"(?:1|0)"},o:function(){return $f("Y");},Y:{g:1,c:"y = parseInt(results[{0}], 10);\n",s:"(\\d{4})"},y:{g:1,c:"var ty = parseInt(results[{0}], 10);\n"
++"y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",s:"(\\d{1,2})"},a:function(){return $f("A");},A:{calcLast:true,g:1,c:"if (/(am)/i.test(results[{0}])) {\n"
++"if (!h || h == 12) { h = 0; }\n"
++"} else { if (!h || h < 12) { h = (h || 0) + 12; }}",s:"(AM|PM|am|pm)"},g:function(){return $f("G");},G:{g:1,c:"h = parseInt(results[{0}], 10);\n",s:"(\\d{1,2})"},h:function(){return $f("H");},H:{g:1,c:"h = parseInt(results[{0}], 10);\n",s:"(\\d{2})"},i:{g:1,c:"i = parseInt(results[{0}], 10);\n",s:"(\\d{2})"},s:{g:1,c:"s = parseInt(results[{0}], 10);\n",s:"(\\d{2})"},u:{g:1,c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",s:"(\\d+)"},O:{g:1,c:["o = results[{0}];","var sn = o.substring(0,1),","hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),","mn = o.substring(3,5) % 60;","o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"].join("\n"),s:"([+\-]\\d{4})"},P:{g:1,c:["o = results[{0}];","var sn = o.substring(0,1),","hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),","mn = o.substring(4,6) % 60;","o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"].join("\n"),s:"([+\-]\\d{2}:\\d{2})"},T:{g:0,c:null,s:"[A-Z]{1,4}"},Z:{g:1,c:"zz = results[{0}] * 1;\n"
++"zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",s:"([+\-]?\\d{1,5})"},c:function(){var calc=[],arr=[$f("Y",1),$f("m",2),$f("d",3),$f("h",4),$f("i",5),$f("s",6),{c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"},{c:["if(results[8]) {","if(results[8] == 'Z'){","zz = 0;","}else if (results[8].indexOf(':') > -1){",$f("P",8).c,"}else{",$f("O",8).c,"}","}"].join('\n')}];for(var i=0,l=arr.length;i<l;++i){calc.push(arr[i].c);}
+return{g:1,c:calc.join(""),s:[arr[0].s,"(?:","-",arr[1].s,"(?:","-",arr[2].s,"(?:","(?:T| )?",arr[3].s,":",arr[4].s,"(?::",arr[5].s,")?","(?:(?:\\.|,)(\\d+))?","(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?",")?",")?",")?"].join("")};},U:{g:1,c:"u = parseInt(results[{0}], 10);\n",s:"(-?\\d+)"}}});}());Ext.apply(Date.prototype,{dateFormat:function(format){if(Date.formatFunctions[format]==null){Date.createFormat(format);}
+return Date.formatFunctions[format].call(this);},getTimezone:function(){return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/,"$1$2").replace(/[^A-Z]/g,"");},getGMTOffset:function(colon){return(this.getTimezoneOffset()>0?"-":"+")
++String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset())/60),2,"0")
++(colon?":":"")
++String.leftPad(Math.abs(this.getTimezoneOffset()%60),2,"0");},getDayOfYear:function(){var num=0,d=this.clone(),m=this.getMonth(),i;for(i=0,d.setDate(1),d.setMonth(0);i<m;d.setMonth(++i)){num+=d.getDaysInMonth();}
+return num+this.getDate()-1;},getWeekOfYear:function(){var ms1d=864e5,ms7d=7*ms1d;return function(){var DC3=Date.UTC(this.getFullYear(),this.getMonth(),this.getDate()+3)/ms1d,AWN=Math.floor(DC3/7),Wyr=new Date(AWN*ms7d).getUTCFullYear();return AWN-Math.floor(Date.UTC(Wyr,0,7)/ms7d)+1;};}(),isLeapYear:function(){var year=this.getFullYear();return!!((year&3)==0&&(year%100||(year%400==0&&year)));},getFirstDayOfMonth:function(){var day=(this.getDay()-(this.getDate()-1))%7;return(day<0)?(day+7):day;},getLastDayOfMonth:function(){return this.getLastDateOfMonth().getDay();},getFirstDateOfMonth:function(){return new Date(this.getFullYear(),this.getMonth(),1);},getLastDateOfMonth:function(){return new Date(this.getFullYear(),this.getMonth(),this.getDaysInMonth());},getDaysInMonth:function(){var daysInMonth=[31,28,31,30,31,30,31,31,30,31,30,31];return function(){var m=this.getMonth();return m==1&&this.isLeapYear()?29:daysInMonth[m];};}(),getSuffix:function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}},clone:function(){return new Date(this.getTime());},isDST:function(){return new Date(this.getFullYear(),0,1).getTimezoneOffset()!=this.getTimezoneOffset();},clearTime:function(clone){if(clone){return this.clone().clearTime();}
+var d=this.getDate();this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);if(this.getDate()!=d){for(var hr=1,c=this.add(Date.HOUR,hr);c.getDate()!=d;hr++,c=this.add(Date.HOUR,hr));this.setDate(d);this.setHours(c.getHours());}
+return this;},add:function(interval,value){var d=this.clone();if(!interval||value===0)return d;switch(interval.toLowerCase()){case Date.MILLI:d.setMilliseconds(this.getMilliseconds()+value);break;case Date.SECOND:d.setSeconds(this.getSeconds()+value);break;case Date.MINUTE:d.setMinutes(this.getMinutes()+value);break;case Date.HOUR:d.setHours(this.getHours()+value);break;case Date.DAY:d.setDate(this.getDate()+value);break;case Date.MONTH:var day=this.getDate();if(day>28){day=Math.min(day,this.getFirstDateOfMonth().add('mo',value).getLastDateOfMonth().getDate());}
+d.setDate(day);d.setMonth(this.getMonth()+value);break;case Date.YEAR:d.setFullYear(this.getFullYear()+value);break;}
+return d;},between:function(start,end){var t=this.getTime();return start.getTime()<=t&&t<=end.getTime();}});Date.prototype.format=Date.prototype.dateFormat;if(Ext.isSafari&&(navigator.userAgent.match(/WebKit\/(\d+)/)[1]||NaN)<420){Ext.apply(Date.prototype,{_xMonth:Date.prototype.setMonth,_xDate:Date.prototype.setDate,setMonth:function(num){if(num<=-1){var n=Math.ceil(-num),back_year=Math.ceil(n/12),month=(n%12)?12-n%12:0;this.setFullYear(this.getFullYear()-back_year);return this._xMonth(month);}else{return this._xMonth(num);}},setDate:function(d){return this.setTime(this.getTime()-(this.getDate()-d)*864e5);}});}
+Ext.util.MixedCollection=function(allowFunctions,keyFn){this.items=[];this.map={};this.keys=[];this.length=0;this.addEvents('clear','add','replace','remove','sort');this.allowFunctions=allowFunctions===true;if(keyFn){this.getKey=keyFn;}
+Ext.util.MixedCollection.superclass.constructor.call(this);};Ext.extend(Ext.util.MixedCollection,Ext.util.Observable,{allowFunctions:false,add:function(key,o){if(arguments.length==1){o=arguments[0];key=this.getKey(o);}
+if(typeof key!='undefined'&&key!==null){var old=this.map[key];if(typeof old!='undefined'){return this.replace(key,o);}
+this.map[key]=o;}
+this.length++;this.items.push(o);this.keys.push(key);this.fireEvent('add',this.length-1,o,key);return o;},getKey:function(o){return o.id;},replace:function(key,o){if(arguments.length==1){o=arguments[0];key=this.getKey(o);}
+var old=this.map[key];if(typeof key=='undefined'||key===null||typeof old=='undefined'){return this.add(key,o);}
+var index=this.indexOfKey(key);this.items[index]=o;this.map[key]=o;this.fireEvent('replace',key,old,o);return o;},addAll:function(objs){if(arguments.length>1||Ext.isArray(objs)){var args=arguments.length>1?arguments:objs;for(var i=0,len=args.length;i<len;i++){this.add(args[i]);}}else{for(var key in objs){if(this.allowFunctions||typeof objs[key]!='function'){this.add(key,objs[key]);}}}},each:function(fn,scope){var items=[].concat(this.items);for(var i=0,len=items.length;i<len;i++){if(fn.call(scope||items[i],items[i],i,len)===false){break;}}},eachKey:function(fn,scope){for(var i=0,len=this.keys.length;i<len;i++){fn.call(scope||window,this.keys[i],this.items[i],i,len);}},find:function(fn,scope){for(var i=0,len=this.items.length;i<len;i++){if(fn.call(scope||window,this.items[i],this.keys[i])){return this.items[i];}}
+return null;},insert:function(index,key,o){if(arguments.length==2){o=arguments[1];key=this.getKey(o);}
+if(this.containsKey(key)){this.suspendEvents();this.removeKey(key);this.resumeEvents();}
+if(index>=this.length){return this.add(key,o);}
+this.length++;this.items.splice(index,0,o);if(typeof key!='undefined'&&key!==null){this.map[key]=o;}
+this.keys.splice(index,0,key);this.fireEvent('add',index,o,key);return o;},remove:function(o){return this.removeAt(this.indexOf(o));},removeAt:function(index){if(index<this.length&&index>=0){this.length--;var o=this.items[index];this.items.splice(index,1);var key=this.keys[index];if(typeof key!='undefined'){delete this.map[key];}
+this.keys.splice(index,1);this.fireEvent('remove',o,key);return o;}
+return false;},removeKey:function(key){return this.removeAt(this.indexOfKey(key));},getCount:function(){return this.length;},indexOf:function(o){return this.items.indexOf(o);},indexOfKey:function(key){return this.keys.indexOf(key);},item:function(key){var mk=this.map[key],item=mk!==undefined?mk:(typeof key=='number')?this.items[key]:undefined;return typeof item!='function'||this.allowFunctions?item:null;},itemAt:function(index){return this.items[index];},key:function(key){return this.map[key];},contains:function(o){return this.indexOf(o)!=-1;},containsKey:function(key){return typeof this.map[key]!='undefined';},clear:function(){this.length=0;this.items=[];this.keys=[];this.map={};this.fireEvent('clear');},first:function(){return this.items[0];},last:function(){return this.items[this.length-1];},_sort:function(property,dir,fn){var i,len,dsc=String(dir).toUpperCase()=='DESC'?-1:1,c=[],keys=this.keys,items=this.items;fn=fn||function(a,b){return a-b;};for(i=0,len=items.length;i<len;i++){c[c.length]={key:keys[i],value:items[i],index:i};}
+c.sort(function(a,b){var v=fn(a[property],b[property])*dsc;if(v===0){v=(a.index<b.index?-1:1);}
+return v;});for(i=0,len=c.length;i<len;i++){items[i]=c[i].value;keys[i]=c[i].key;}
+this.fireEvent('sort',this);},sort:function(dir,fn){this._sort('value',dir,fn);},reorder:function(mapping){this.suspendEvents();var items=this.items,index=0,length=items.length,order=[],remaining=[],oldIndex;for(oldIndex in mapping){order[mapping[oldIndex]]=items[oldIndex];}
+for(index=0;index<length;index++){if(mapping[index]==undefined){remaining.push(items[index]);}}
+for(index=0;index<length;index++){if(order[index]==undefined){order[index]=remaining.shift();}}
+this.clear();this.addAll(order);this.resumeEvents();this.fireEvent('sort',this);},keySort:function(dir,fn){this._sort('key',dir,fn||function(a,b){var v1=String(a).toUpperCase(),v2=String(b).toUpperCase();return v1>v2?1:(v1<v2?-1:0);});},getRange:function(start,end){var items=this.items;if(items.length<1){return[];}
+start=start||0;end=Math.min(typeof end=='undefined'?this.length-1:end,this.length-1);var i,r=[];if(start<=end){for(i=start;i<=end;i++){r[r.length]=items[i];}}else{for(i=start;i>=end;i--){r[r.length]=items[i];}}
+return r;},filter:function(property,value,anyMatch,caseSensitive){if(Ext.isEmpty(value,false)){return this.clone();}
+value=this.createValueMatcher(value,anyMatch,caseSensitive);return this.filterBy(function(o){return o&&value.test(o[property]);});},filterBy:function(fn,scope){var r=new Ext.util.MixedCollection();r.getKey=this.getKey;var k=this.keys,it=this.items;for(var i=0,len=it.length;i<len;i++){if(fn.call(scope||this,it[i],k[i])){r.add(k[i],it[i]);}}
+return r;},findIndex:function(property,value,start,anyMatch,caseSensitive){if(Ext.isEmpty(value,false)){return-1;}
+value=this.createValueMatcher(value,anyMatch,caseSensitive);return this.findIndexBy(function(o){return o&&value.test(o[property]);},null,start);},findIndexBy:function(fn,scope,start){var k=this.keys,it=this.items;for(var i=(start||0),len=it.length;i<len;i++){if(fn.call(scope||this,it[i],k[i])){return i;}}
+return-1;},createValueMatcher:function(value,anyMatch,caseSensitive,exactMatch){if(!value.exec){var er=Ext.escapeRe;value=String(value);if(anyMatch===true){value=er(value);}else{value='^'+er(value);if(exactMatch===true){value+='$';}}
+value=new RegExp(value,caseSensitive?'':'i');}
+return value;},clone:function(){var r=new Ext.util.MixedCollection();var k=this.keys,it=this.items;for(var i=0,len=it.length;i<len;i++){r.add(k[i],it[i]);}
+r.getKey=this.getKey;return r;}});Ext.util.MixedCollection.prototype.get=Ext.util.MixedCollection.prototype.item;Ext.AbstractManager=Ext.extend(Object,{typeName:'type',constructor:function(config){Ext.apply(this,config||{});this.all=new Ext.util.MixedCollection();this.types={};},get:function(id){return this.all.get(id);},register:function(item){this.all.add(item);},unregister:function(item){this.all.remove(item);},registerType:function(type,cls){this.types[type]=cls;cls[this.typeName]=type;},isRegistered:function(type){return this.types[type]!==undefined;},create:function(config,defaultType){var type=config[this.typeName]||config.type||defaultType,Constructor=this.types[type];if(Constructor==undefined){throw new Error(String.format("The '{0}' type has not been registered with this manager",type));}
+return new Constructor(config);},onAvailable:function(id,fn,scope){var all=this.all;all.on("add",function(index,o){if(o.id==id){fn.call(scope||o,o);all.un("add",fn,scope);}});}});Ext.util.Format=function(){var trimRe=/^\s+|\s+$/g,stripTagsRE=/<\/?[^>]+>/gi,stripScriptsRe=/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,nl2brRe=/\r?\n/g;return{ellipsis:function(value,len,word){if(value&&value.length>len){if(word){var vs=value.substr(0,len-2),index=Math.max(vs.lastIndexOf(' '),vs.lastIndexOf('.'),vs.lastIndexOf('!'),vs.lastIndexOf('?'));if(index==-1||index<(len-15)){return value.substr(0,len-3)+"...";}else{return vs.substr(0,index)+"...";}}else{return value.substr(0,len-3)+"...";}}
+return value;},undef:function(value){return value!==undefined?value:"";},defaultValue:function(value,defaultValue){return value!==undefined&&value!==''?value:defaultValue;},htmlEncode:function(value){return!value?value:String(value).replace(/&/g,"&amp;").replace(/>/g,"&gt;").replace(/</g,"&lt;").replace(/"/g,"&quot;");},htmlDecode:function(value){return!value?value:String(value).replace(/&gt;/g,">").replace(/&lt;/g,"<").replace(/&quot;/g,'"').replace(/&amp;/g,"&");},trim:function(value){return String(value).replace(trimRe,"");},substr:function(value,start,length){return String(value).substr(start,length);},lowercase:function(value){return String(value).toLowerCase();},uppercase:function(value){return String(value).toUpperCase();},capitalize:function(value){return!value?value:value.charAt(0).toUpperCase()+value.substr(1).toLowerCase();},call:function(value,fn){if(arguments.length>2){var args=Array.prototype.slice.call(arguments,2);args.unshift(value);return eval(fn).apply(window,args);}else{return eval(fn).call(window,value);}},usMoney:function(v){v=(Math.round((v-0)*100))/100;v=(v==Math.floor(v))?v+".00":((v*10==Math.floor(v*10))?v+"0":v);v=String(v);var ps=v.split('.'),whole=ps[0],sub=ps[1]?'.'+ps[1]:'.00',r=/(\d+)(\d{3})/;while(r.test(whole)){whole=whole.replace(r,'$1'+','+'$2');}
+v=whole+sub;if(v.charAt(0)=='-'){return'-$'+v.substr(1);}
+return"$"+v;},date:function(v,format){if(!v){return"";}
+if(!Ext.isDate(v)){v=new Date(Date.parse(v));}
+return v.dateFormat(format||"m/d/Y");},dateRenderer:function(format){return function(v){return Ext.util.Format.date(v,format);};},stripTags:function(v){return!v?v:String(v).replace(stripTagsRE,"");},stripScripts:function(v){return!v?v:String(v).replace(stripScriptsRe,"");},fileSize:function(size){if(size<1024){return size+" bytes";}else if(size<1048576){return(Math.round(((size*10)/1024))/10)+" KB";}else{return(Math.round(((size*10)/1048576))/10)+" MB";}},math:function(){var fns={};return function(v,a){if(!fns[a]){fns[a]=new Function('v','return v '+a+';');}
+return fns[a](v);};}(),round:function(value,precision){var result=Number(value);if(typeof precision=='number'){precision=Math.pow(10,precision);result=Math.round(value*precision)/precision;}
+return result;},number:function(v,format){if(!format){return v;}
+v=Ext.num(v,NaN);if(isNaN(v)){return'';}
+var comma=',',dec='.',i18n=false,neg=v<0;v=Math.abs(v);if(format.substr(format.length-2)=='/i'){format=format.substr(0,format.length-2);i18n=true;comma='.';dec=',';}
+var hasComma=format.indexOf(comma)!=-1,psplit=(i18n?format.replace(/[^\d\,]/g,''):format.replace(/[^\d\.]/g,'')).split(dec);if(1<psplit.length){v=v.toFixed(psplit[1].length);}else if(2<psplit.length){throw('NumberFormatException: invalid format, formats should have no more than 1 period: '+format);}else{v=v.toFixed(0);}
+var fnum=v.toString();psplit=fnum.split('.');if(hasComma){var cnum=psplit[0],parr=[],j=cnum.length,m=Math.floor(j/3),n=cnum.length%3||3,i;for(i=0;i<j;i+=n){if(i!=0){n=3;}
+parr[parr.length]=cnum.substr(i,n);m-=1;}
+fnum=parr.join(comma);if(psplit[1]){fnum+=dec+psplit[1];}}else{if(psplit[1]){fnum=psplit[0]+dec+psplit[1];}}
+return(neg?'-':'')+format.replace(/[\d,?\.?]+/,fnum);},numberRenderer:function(format){return function(v){return Ext.util.Format.number(v,format);};},plural:function(v,s,p){return v+' '+(v==1?s:(p?p:s+'s'));},nl2br:function(v){return Ext.isEmpty(v)?'':v.replace(nl2brRe,'<br/>');}};}();Ext.XTemplate=function(){Ext.XTemplate.superclass.constructor.apply(this,arguments);var me=this,s=me.html,re=/<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,nameRe=/^<tpl\b[^>]*?for="(.*?)"/,ifRe=/^<tpl\b[^>]*?if="(.*?)"/,execRe=/^<tpl\b[^>]*?exec="(.*?)"/,m,id=0,tpls=[],VALUES='values',PARENT='parent',XINDEX='xindex',XCOUNT='xcount',RETURN='return ',WITHVALUES='with(values){ ';s=['<tpl>',s,'</tpl>'].join('');while((m=s.match(re))){var m2=m[0].match(nameRe),m3=m[0].match(ifRe),m4=m[0].match(execRe),exp=null,fn=null,exec=null,name=m2&&m2[1]?m2[1]:'';if(m3){exp=m3&&m3[1]?m3[1]:null;if(exp){fn=new Function(VALUES,PARENT,XINDEX,XCOUNT,WITHVALUES+RETURN+(Ext.util.Format.htmlDecode(exp))+'; }');}}
+if(m4){exp=m4&&m4[1]?m4[1]:null;if(exp){exec=new Function(VALUES,PARENT,XINDEX,XCOUNT,WITHVALUES+(Ext.util.Format.htmlDecode(exp))+'; }');}}
+if(name){switch(name){case'.':name=new Function(VALUES,PARENT,WITHVALUES+RETURN+VALUES+'; }');break;case'..':name=new Function(VALUES,PARENT,WITHVALUES+RETURN+PARENT+'; }');break;default:name=new Function(VALUES,PARENT,WITHVALUES+RETURN+name+'; }');}}
+tpls.push({id:id,target:name,exec:exec,test:fn,body:m[1]||''});s=s.replace(m[0],'{xtpl'+id+'}');++id;}
+for(var i=tpls.length-1;i>=0;--i){me.compileTpl(tpls[i]);}
+me.master=tpls[tpls.length-1];me.tpls=tpls;};Ext.extend(Ext.XTemplate,Ext.Template,{re:/\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,codeRe:/\{\[((?:\\\]|.|\n)*?)\]\}/g,applySubTemplate:function(id,values,parent,xindex,xcount){var me=this,len,t=me.tpls[id],vs,buf=[];if((t.test&&!t.test.call(me,values,parent,xindex,xcount))||(t.exec&&t.exec.call(me,values,parent,xindex,xcount))){return'';}
+vs=t.target?t.target.call(me,values,parent):values;len=vs.length;parent=t.target?values:parent;if(t.target&&Ext.isArray(vs)){for(var i=0,len=vs.length;i<len;i++){buf[buf.length]=t.compiled.call(me,vs[i],parent,i+1,len);}
+return buf.join('');}
+return t.compiled.call(me,vs,parent,xindex,xcount);},compileTpl:function(tpl){var fm=Ext.util.Format,useF=this.disableFormats!==true,sep=Ext.isGecko?"+":",",body;function fn(m,name,format,args,math){if(name.substr(0,4)=='xtpl'){return"'"+sep+'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";}
+var v;if(name==='.'){v='values';}else if(name==='#'){v='xindex';}else if(name.indexOf('.')!=-1){v=name;}else{v="values['"+name+"']";}
+if(math){v='('+v+math+')';}
+if(format&&useF){args=args?','+args:"";if(format.substr(0,5)!="this."){format="fm."+format+'(';}else{format='this.call("'+format.substr(5)+'", ';args=", values";}}else{args='';format="("+v+" === undefined ? '' : ";}
+return"'"+sep+format+v+args+")"+sep+"'";}
+function codeFn(m,code){return"'"+sep+'('+code.replace(/\\'/g,"'")+')'+sep+"'";}
+if(Ext.isGecko){body="tpl.compiled = function(values, parent, xindex, xcount){ return '"+
+tpl.body.replace(/(\r\n|\n)/g,'\\n').replace(/'/g,"\\'").replace(this.re,fn).replace(this.codeRe,codeFn)+"';};";}else{body=["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];body.push(tpl.body.replace(/(\r\n|\n)/g,'\\n').replace(/'/g,"\\'").replace(this.re,fn).replace(this.codeRe,codeFn));body.push("'].join('');};");body=body.join('');}
+eval(body);return this;},applyTemplate:function(values){return this.master.compiled.call(this,values,{},1,1);},compile:function(){return this;}});Ext.XTemplate.prototype.apply=Ext.XTemplate.prototype.applyTemplate;Ext.XTemplate.from=function(el){el=Ext.getDom(el);return new Ext.XTemplate(el.value||el.innerHTML);};Ext.util.CSS=function(){var rules=null;var doc=document;var camelRe=/(-[a-z])/gi;var camelFn=function(m,a){return a.charAt(1).toUpperCase();};return{createStyleSheet:function(cssText,id){var ss;var head=doc.getElementsByTagName("head")[0];var rules=doc.createElement("style");rules.setAttribute("type","text/css");if(id){rules.setAttribute("id",id);}
+if(Ext.isIE){head.appendChild(rules);ss=rules.styleSheet;ss.cssText=cssText;}else{try{rules.appendChild(doc.createTextNode(cssText));}catch(e){rules.cssText=cssText;}
+head.appendChild(rules);ss=rules.styleSheet?rules.styleSheet:(rules.sheet||doc.styleSheets[doc.styleSheets.length-1]);}
+this.cacheStyleSheet(ss);return ss;},removeStyleSheet:function(id){var existing=doc.getElementById(id);if(existing){existing.parentNode.removeChild(existing);}},swapStyleSheet:function(id,url){this.removeStyleSheet(id);var ss=doc.createElement("link");ss.setAttribute("rel","stylesheet");ss.setAttribute("type","text/css");ss.setAttribute("id",id);ss.setAttribute("href",url);doc.getElementsByTagName("head")[0].appendChild(ss);},refreshCache:function(){return this.getRules(true);},cacheStyleSheet:function(ss){if(!rules){rules={};}
+try{var ssRules=ss.cssRules||ss.rules;for(var j=ssRules.length-1;j>=0;--j){rules[ssRules[j].selectorText.toLowerCase()]=ssRules[j];}}catch(e){}},getRules:function(refreshCache){if(rules===null||refreshCache){rules={};var ds=doc.styleSheets;for(var i=0,len=ds.length;i<len;i++){try{this.cacheStyleSheet(ds[i]);}catch(e){}}}
+return rules;},getRule:function(selector,refreshCache){var rs=this.getRules(refreshCache);if(!Ext.isArray(selector)){return rs[selector.toLowerCase()];}
+for(var i=0;i<selector.length;i++){if(rs[selector[i]]){return rs[selector[i].toLowerCase()];}}
+return null;},updateRule:function(selector,property,value){if(!Ext.isArray(selector)){var rule=this.getRule(selector);if(rule){rule.style[property.replace(camelRe,camelFn)]=value;return true;}}else{for(var i=0;i<selector.length;i++){if(this.updateRule(selector[i],property,value)){return true;}}}
+return false;}};}();Ext.util.ClickRepeater=Ext.extend(Ext.util.Observable,{constructor:function(el,config){this.el=Ext.get(el);this.el.unselectable();Ext.apply(this,config);this.addEvents("mousedown","click","mouseup");if(!this.disabled){this.disabled=true;this.enable();}
+if(this.handler){this.on("click",this.handler,this.scope||this);}
+Ext.util.ClickRepeater.superclass.constructor.call(this);},interval:20,delay:250,preventDefault:true,stopDefault:false,timer:0,enable:function(){if(this.disabled){this.el.on('mousedown',this.handleMouseDown,this);if(Ext.isIE){this.el.on('dblclick',this.handleDblClick,this);}
+if(this.preventDefault||this.stopDefault){this.el.on('click',this.eventOptions,this);}}
+this.disabled=false;},disable:function(force){if(force||!this.disabled){clearTimeout(this.timer);if(this.pressClass){this.el.removeClass(this.pressClass);}
+Ext.getDoc().un('mouseup',this.handleMouseUp,this);this.el.removeAllListeners();}
+this.disabled=true;},setDisabled:function(disabled){this[disabled?'disable':'enable']();},eventOptions:function(e){if(this.preventDefault){e.preventDefault();}
+if(this.stopDefault){e.stopEvent();}},destroy:function(){this.disable(true);Ext.destroy(this.el);this.purgeListeners();},handleDblClick:function(e){clearTimeout(this.timer);this.el.blur();this.fireEvent("mousedown",this,e);this.fireEvent("click",this,e);},handleMouseDown:function(e){clearTimeout(this.timer);this.el.blur();if(this.pressClass){this.el.addClass(this.pressClass);}
+this.mousedownTime=new Date();Ext.getDoc().on("mouseup",this.handleMouseUp,this);this.el.on("mouseout",this.handleMouseOut,this);this.fireEvent("mousedown",this,e);this.fireEvent("click",this,e);if(this.accelerate){this.delay=400;}
+this.timer=this.click.defer(this.delay||this.interval,this,[e]);},click:function(e){this.fireEvent("click",this,e);this.timer=this.click.defer(this.accelerate?this.easeOutExpo(this.mousedownTime.getElapsed(),400,-390,12000):this.interval,this,[e]);},easeOutExpo:function(t,b,c,d){return(t==d)?b+c:c*(-Math.pow(2,-10*t/d)+1)+b;},handleMouseOut:function(){clearTimeout(this.timer);if(this.pressClass){this.el.removeClass(this.pressClass);}
+this.el.on("mouseover",this.handleMouseReturn,this);},handleMouseReturn:function(){this.el.un("mouseover",this.handleMouseReturn,this);if(this.pressClass){this.el.addClass(this.pressClass);}
+this.click();},handleMouseUp:function(e){clearTimeout(this.timer);this.el.un("mouseover",this.handleMouseReturn,this);this.el.un("mouseout",this.handleMouseOut,this);Ext.getDoc().un("mouseup",this.handleMouseUp,this);this.el.removeClass(this.pressClass);this.fireEvent("mouseup",this,e);}});Ext.KeyNav=function(el,config){this.el=Ext.get(el);Ext.apply(this,config);if(!this.disabled){this.disabled=true;this.enable();}};Ext.KeyNav.prototype={disabled:false,defaultEventAction:"stopEvent",forceKeyDown:false,relay:function(e){var k=e.getKey(),h=this.keyToHandler[k];if(h&&this[h]){if(this.doRelay(e,this[h],h)!==true){e[this.defaultEventAction]();}}},doRelay:function(e,h,hname){return h.call(this.scope||this,e,hname);},enter:false,left:false,right:false,up:false,down:false,tab:false,esc:false,pageUp:false,pageDown:false,del:false,home:false,end:false,keyToHandler:{37:"left",39:"right",38:"up",40:"down",33:"pageUp",34:"pageDown",46:"del",36:"home",35:"end",13:"enter",27:"esc",9:"tab"},stopKeyUp:function(e){var k=e.getKey();if(k>=37&&k<=40){e.stopEvent();}},destroy:function(){this.disable();},enable:function(){if(this.disabled){if(Ext.isSafari2){this.el.on('keyup',this.stopKeyUp,this);}
+this.el.on(this.isKeydown()?'keydown':'keypress',this.relay,this);this.disabled=false;}},disable:function(){if(!this.disabled){if(Ext.isSafari2){this.el.un('keyup',this.stopKeyUp,this);}
+this.el.un(this.isKeydown()?'keydown':'keypress',this.relay,this);this.disabled=true;}},setDisabled:function(disabled){this[disabled?"disable":"enable"]();},isKeydown:function(){return this.forceKeyDown||Ext.EventManager.useKeydown;}};Ext.KeyMap=function(el,config,eventName){this.el=Ext.get(el);this.eventName=eventName||"keydown";this.bindings=[];if(config){this.addBinding(config);}
+this.enable();};Ext.KeyMap.prototype={stopEvent:false,addBinding:function(config){if(Ext.isArray(config)){Ext.each(config,function(c){this.addBinding(c);},this);return;}
+var keyCode=config.key,fn=config.fn||config.handler,scope=config.scope;if(config.stopEvent){this.stopEvent=config.stopEvent;}
+if(typeof keyCode=="string"){var ks=[];var keyString=keyCode.toUpperCase();for(var j=0,len=keyString.length;j<len;j++){ks.push(keyString.charCodeAt(j));}
+keyCode=ks;}
+var keyArray=Ext.isArray(keyCode);var handler=function(e){if(this.checkModifiers(config,e)){var k=e.getKey();if(keyArray){for(var i=0,len=keyCode.length;i<len;i++){if(keyCode[i]==k){if(this.stopEvent){e.stopEvent();}
+fn.call(scope||window,k,e);return;}}}else{if(k==keyCode){if(this.stopEvent){e.stopEvent();}
+fn.call(scope||window,k,e);}}}};this.bindings.push(handler);},checkModifiers:function(config,e){var val,key,keys=['shift','ctrl','alt'];for(var i=0,len=keys.length;i<len;++i){key=keys[i];val=config[key];if(!(val===undefined||(val===e[key+'Key']))){return false;}}
+return true;},on:function(key,fn,scope){var keyCode,shift,ctrl,alt;if(typeof key=="object"&&!Ext.isArray(key)){keyCode=key.key;shift=key.shift;ctrl=key.ctrl;alt=key.alt;}else{keyCode=key;}
+this.addBinding({key:keyCode,shift:shift,ctrl:ctrl,alt:alt,fn:fn,scope:scope});},handleKeyDown:function(e){if(this.enabled){var b=this.bindings;for(var i=0,len=b.length;i<len;i++){b[i].call(this,e);}}},isEnabled:function(){return this.enabled;},enable:function(){if(!this.enabled){this.el.on(this.eventName,this.handleKeyDown,this);this.enabled=true;}},disable:function(){if(this.enabled){this.el.removeListener(this.eventName,this.handleKeyDown,this);this.enabled=false;}},setDisabled:function(disabled){this[disabled?"disable":"enable"]();}};Ext.util.TextMetrics=function(){var shared;return{measure:function(el,text,fixedWidth){if(!shared){shared=Ext.util.TextMetrics.Instance(el,fixedWidth);}
+shared.bind(el);shared.setFixedWidth(fixedWidth||'auto');return shared.getSize(text);},createInstance:function(el,fixedWidth){return Ext.util.TextMetrics.Instance(el,fixedWidth);}};}();Ext.util.TextMetrics.Instance=function(bindTo,fixedWidth){var ml=new Ext.Element(document.createElement('div'));document.body.appendChild(ml.dom);ml.position('absolute');ml.setLeftTop(-1000,-1000);ml.hide();if(fixedWidth){ml.setWidth(fixedWidth);}
+var instance={getSize:function(text){ml.update(text);var s=ml.getSize();ml.update('');return s;},bind:function(el){ml.setStyle(Ext.fly(el).getStyles('font-size','font-style','font-weight','font-family','line-height','text-transform','letter-spacing'));},setFixedWidth:function(width){ml.setWidth(width);},getWidth:function(text){ml.dom.style.width='auto';return this.getSize(text).width;},getHeight:function(text){return this.getSize(text).height;}};instance.bind(bindTo);return instance;};Ext.Element.addMethods({getTextWidth:function(text,min,max){return(Ext.util.TextMetrics.measure(this.dom,Ext.value(text,this.dom.innerHTML,true)).width).constrain(min||0,max||1000000);}});Ext.util.Cookies={set:function(name,value){var argv=arguments;var argc=arguments.length;var expires=(argc>2)?argv[2]:null;var path=(argc>3)?argv[3]:'/';var domain=(argc>4)?argv[4]:null;var secure=(argc>5)?argv[5]:false;document.cookie=name+"="+escape(value)+((expires===null)?"":("; expires="+expires.toGMTString()))+((path===null)?"":("; path="+path))+((domain===null)?"":("; domain="+domain))+((secure===true)?"; secure":"");},get:function(name){var arg=name+"=";var alen=arg.length;var clen=document.cookie.length;var i=0;var j=0;while(i<clen){j=i+alen;if(document.cookie.substring(i,j)==arg){return Ext.util.Cookies.getCookieVal(j);}
+i=document.cookie.indexOf(" ",i)+1;if(i===0){break;}}
+return null;},clear:function(name){if(Ext.util.Cookies.get(name)){document.cookie=name+"="+"; expires=Thu, 01-Jan-70 00:00:01 GMT";}},getCookieVal:function(offset){var endstr=document.cookie.indexOf(";",offset);if(endstr==-1){endstr=document.cookie.length;}
+return unescape(document.cookie.substring(offset,endstr));}};Ext.handleError=function(e){throw e;};Ext.Error=function(message){this.message=(this.lang[message])?this.lang[message]:message;};Ext.Error.prototype=new Error();Ext.apply(Ext.Error.prototype,{lang:{},name:'Ext.Error',getName:function(){return this.name;},getMessage:function(){return this.message;},toJson:function(){return Ext.encode(this);}});Ext.ComponentMgr=function(){var all=new Ext.util.MixedCollection();var types={};var ptypes={};return{register:function(c){all.add(c);},unregister:function(c){all.remove(c);},get:function(id){return all.get(id);},onAvailable:function(id,fn,scope){all.on("add",function(index,o){if(o.id==id){fn.call(scope||o,o);all.un("add",fn,scope);}});},all:all,types:types,ptypes:ptypes,isRegistered:function(xtype){return types[xtype]!==undefined;},isPluginRegistered:function(ptype){return ptypes[ptype]!==undefined;},registerType:function(xtype,cls){types[xtype]=cls;cls.xtype=xtype;},create:function(config,defaultType){return config.render?config:new types[config.xtype||defaultType](config);},registerPlugin:function(ptype,cls){ptypes[ptype]=cls;cls.ptype=ptype;},createPlugin:function(config,defaultType){var PluginCls=ptypes[config.ptype||defaultType];if(PluginCls.init){return PluginCls;}else{return new PluginCls(config);}}};}();Ext.reg=Ext.ComponentMgr.registerType;Ext.preg=Ext.ComponentMgr.registerPlugin;Ext.create=Ext.ComponentMgr.create;Ext.Component=function(config){config=config||{};if(config.initialConfig){if(config.isAction){this.baseAction=config;}
+config=config.initialConfig;}else if(config.tagName||config.dom||Ext.isString(config)){config={applyTo:config,id:config.id||config};}
+this.initialConfig=config;Ext.apply(this,config);this.addEvents('added','disable','enable','beforeshow','show','beforehide','hide','removed','beforerender','render','afterrender','beforedestroy','destroy','beforestaterestore','staterestore','beforestatesave','statesave');this.getId();Ext.ComponentMgr.register(this);Ext.Component.superclass.constructor.call(this);if(this.baseAction){this.baseAction.addComponent(this);}
+this.initComponent();if(this.plugins){if(Ext.isArray(this.plugins)){for(var i=0,len=this.plugins.length;i<len;i++){this.plugins[i]=this.initPlugin(this.plugins[i]);}}else{this.plugins=this.initPlugin(this.plugins);}}
+if(this.stateful!==false){this.initState();}
+if(this.applyTo){this.applyToMarkup(this.applyTo);delete this.applyTo;}else if(this.renderTo){this.render(this.renderTo);delete this.renderTo;}};Ext.Component.AUTO_ID=1000;Ext.extend(Ext.Component,Ext.util.Observable,{disabled:false,hidden:false,autoEl:'div',disabledClass:'x-item-disabled',allowDomMove:true,autoShow:false,hideMode:'display',hideParent:false,rendered:false,tplWriteMode:'overwrite',bubbleEvents:[],ctype:'Ext.Component',actionMode:'el',getActionEl:function(){return this[this.actionMode];},initPlugin:function(p){if(p.ptype&&!Ext.isFunction(p.init)){p=Ext.ComponentMgr.createPlugin(p);}else if(Ext.isString(p)){p=Ext.ComponentMgr.createPlugin({ptype:p});}
+p.init(this);return p;},initComponent:function(){if(this.listeners){this.on(this.listeners);delete this.listeners;}
+this.enableBubble(this.bubbleEvents);},render:function(container,position){if(!this.rendered&&this.fireEvent('beforerender',this)!==false){if(!container&&this.el){this.el=Ext.get(this.el);container=this.el.dom.parentNode;this.allowDomMove=false;}
+this.container=Ext.get(container);if(this.ctCls){this.container.addClass(this.ctCls);}
+this.rendered=true;if(position!==undefined){if(Ext.isNumber(position)){position=this.container.dom.childNodes[position];}else{position=Ext.getDom(position);}}
+this.onRender(this.container,position||null);if(this.autoShow){this.el.removeClass(['x-hidden','x-hide-'+this.hideMode]);}
+if(this.cls){this.el.addClass(this.cls);delete this.cls;}
+if(this.style){this.el.applyStyles(this.style);delete this.style;}
+if(this.overCls){this.el.addClassOnOver(this.overCls);}
+this.fireEvent('render',this);var contentTarget=this.getContentTarget();if(this.html){contentTarget.update(Ext.DomHelper.markup(this.html));delete this.html;}
+if(this.contentEl){var ce=Ext.getDom(this.contentEl);Ext.fly(ce).removeClass(['x-hidden','x-hide-display']);contentTarget.appendChild(ce);}
+if(this.tpl){if(!this.tpl.compile){this.tpl=new Ext.XTemplate(this.tpl);}
+if(this.data){this.tpl[this.tplWriteMode](contentTarget,this.data);delete this.data;}}
+this.afterRender(this.container);if(this.hidden){this.doHide();}
+if(this.disabled){this.disable(true);}
+if(this.stateful!==false){this.initStateEvents();}
+this.fireEvent('afterrender',this);}
+return this;},update:function(htmlOrData,loadScripts,cb){var contentTarget=this.getContentTarget();if(this.tpl&&typeof htmlOrData!=="string"){this.tpl[this.tplWriteMode](contentTarget,htmlOrData||{});}else{var html=Ext.isObject(htmlOrData)?Ext.DomHelper.markup(htmlOrData):htmlOrData;contentTarget.update(html,loadScripts,cb);}},onAdded:function(container,pos){this.ownerCt=container;this.initRef();this.fireEvent('added',this,container,pos);},onRemoved:function(){this.removeRef();this.fireEvent('removed',this,this.ownerCt);delete this.ownerCt;},initRef:function(){if(this.ref&&!this.refOwner){var levels=this.ref.split('/'),last=levels.length,i=0,t=this;while(t&&i<last){t=t.ownerCt;++i;}
+if(t){t[this.refName=levels[--i]]=this;this.refOwner=t;}}},removeRef:function(){if(this.refOwner&&this.refName){delete this.refOwner[this.refName];delete this.refOwner;}},initState:function(){if(Ext.state.Manager){var id=this.getStateId();if(id){var state=Ext.state.Manager.get(id);if(state){if(this.fireEvent('beforestaterestore',this,state)!==false){this.applyState(Ext.apply({},state));this.fireEvent('staterestore',this,state);}}}}},getStateId:function(){return this.stateId||((/^(ext-comp-|ext-gen)/).test(String(this.id))?null:this.id);},initStateEvents:function(){if(this.stateEvents){for(var i=0,e;e=this.stateEvents[i];i++){this.on(e,this.saveState,this,{delay:100});}}},applyState:function(state){if(state){Ext.apply(this,state);}},getState:function(){return null;},saveState:function(){if(Ext.state.Manager&&this.stateful!==false){var id=this.getStateId();if(id){var state=this.getState();if(this.fireEvent('beforestatesave',this,state)!==false){Ext.state.Manager.set(id,state);this.fireEvent('statesave',this,state);}}}},applyToMarkup:function(el){this.allowDomMove=false;this.el=Ext.get(el);this.render(this.el.dom.parentNode);},addClass:function(cls){if(this.el){this.el.addClass(cls);}else{this.cls=this.cls?this.cls+' '+cls:cls;}
+return this;},removeClass:function(cls){if(this.el){this.el.removeClass(cls);}else if(this.cls){this.cls=this.cls.split(' ').remove(cls).join(' ');}
+return this;},onRender:function(ct,position){if(!this.el&&this.autoEl){if(Ext.isString(this.autoEl)){this.el=document.createElement(this.autoEl);}else{var div=document.createElement('div');Ext.DomHelper.overwrite(div,this.autoEl);this.el=div.firstChild;}
+if(!this.el.id){this.el.id=this.getId();}}
+if(this.el){this.el=Ext.get(this.el);if(this.allowDomMove!==false){ct.dom.insertBefore(this.el.dom,position);if(div){Ext.removeNode(div);div=null;}}}},getAutoCreate:function(){var cfg=Ext.isObject(this.autoCreate)?this.autoCreate:Ext.apply({},this.defaultAutoCreate);if(this.id&&!cfg.id){cfg.id=this.id;}
+return cfg;},afterRender:Ext.emptyFn,destroy:function(){if(!this.isDestroyed){if(this.fireEvent('beforedestroy',this)!==false){this.destroying=true;this.beforeDestroy();if(this.ownerCt&&this.ownerCt.remove){this.ownerCt.remove(this,false);}
+if(this.rendered){this.el.remove();if(this.actionMode=='container'||this.removeMode=='container'){this.container.remove();}}
+if(this.focusTask&&this.focusTask.cancel){this.focusTask.cancel();}
+this.onDestroy();Ext.ComponentMgr.unregister(this);this.fireEvent('destroy',this);this.purgeListeners();this.destroying=false;this.isDestroyed=true;}}},deleteMembers:function(){var args=arguments;for(var i=0,len=args.length;i<len;++i){delete this[args[i]];}},beforeDestroy:Ext.emptyFn,onDestroy:Ext.emptyFn,getEl:function(){return this.el;},getContentTarget:function(){return this.el;},getId:function(){return this.id||(this.id='ext-comp-'+(++Ext.Component.AUTO_ID));},getItemId:function(){return this.itemId||this.getId();},focus:function(selectText,delay){if(delay){this.focusTask=new Ext.util.DelayedTask(this.focus,this,[selectText,false]);this.focusTask.delay(Ext.isNumber(delay)?delay:10);return this;}
+if(this.rendered&&!this.isDestroyed){this.el.focus();if(selectText===true){this.el.dom.select();}}
+return this;},blur:function(){if(this.rendered){this.el.blur();}
+return this;},disable:function(silent){if(this.rendered){this.onDisable();}
+this.disabled=true;if(silent!==true){this.fireEvent('disable',this);}
+return this;},onDisable:function(){this.getActionEl().addClass(this.disabledClass);this.el.dom.disabled=true;},enable:function(){if(this.rendered){this.onEnable();}
+this.disabled=false;this.fireEvent('enable',this);return this;},onEnable:function(){this.getActionEl().removeClass(this.disabledClass);this.el.dom.disabled=false;},setDisabled:function(disabled){return this[disabled?'disable':'enable']();},show:function(){if(this.fireEvent('beforeshow',this)!==false){this.hidden=false;if(this.autoRender){this.render(Ext.isBoolean(this.autoRender)?Ext.getBody():this.autoRender);}
+if(this.rendered){this.onShow();}
+this.fireEvent('show',this);}
+return this;},onShow:function(){this.getVisibilityEl().removeClass('x-hide-'+this.hideMode);},hide:function(){if(this.fireEvent('beforehide',this)!==false){this.doHide();this.fireEvent('hide',this);}
+return this;},doHide:function(){this.hidden=true;if(this.rendered){this.onHide();}},onHide:function(){this.getVisibilityEl().addClass('x-hide-'+this.hideMode);},getVisibilityEl:function(){return this.hideParent?this.container:this.getActionEl();},setVisible:function(visible){return this[visible?'show':'hide']();},isVisible:function(){return this.rendered&&this.getVisibilityEl().isVisible();},cloneConfig:function(overrides){overrides=overrides||{};var id=overrides.id||Ext.id();var cfg=Ext.applyIf(overrides,this.initialConfig);cfg.id=id;return new this.constructor(cfg);},getXType:function(){return this.constructor.xtype;},isXType:function(xtype,shallow){if(Ext.isFunction(xtype)){xtype=xtype.xtype;}else if(Ext.isObject(xtype)){xtype=xtype.constructor.xtype;}
+return!shallow?('/'+this.getXTypes()+'/').indexOf('/'+xtype+'/')!=-1:this.constructor.xtype==xtype;},getXTypes:function(){var tc=this.constructor;if(!tc.xtypes){var c=[],sc=this;while(sc&&sc.constructor.xtype){c.unshift(sc.constructor.xtype);sc=sc.constructor.superclass;}
+tc.xtypeChain=c;tc.xtypes=c.join('/');}
+return tc.xtypes;},findParentBy:function(fn){for(var p=this.ownerCt;(p!=null)&&!fn(p,this);p=p.ownerCt);return p||null;},findParentByType:function(xtype,shallow){return this.findParentBy(function(c){return c.isXType(xtype,shallow);});},bubble:function(fn,scope,args){var p=this;while(p){if(fn.apply(scope||p,args||[p])===false){break;}
+p=p.ownerCt;}
+return this;},getPositionEl:function(){return this.positionEl||this.el;},purgeListeners:function(){Ext.Component.superclass.purgeListeners.call(this);if(this.mons){this.on('beforedestroy',this.clearMons,this,{single:true});}},clearMons:function(){Ext.each(this.mons,function(m){m.item.un(m.ename,m.fn,m.scope);},this);this.mons=[];},createMons:function(){if(!this.mons){this.mons=[];this.on('beforedestroy',this.clearMons,this,{single:true});}},mon:function(item,ename,fn,scope,opt){this.createMons();if(Ext.isObject(ename)){var propRe=/^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;var o=ename;for(var e in o){if(propRe.test(e)){continue;}
+if(Ext.isFunction(o[e])){this.mons.push({item:item,ename:e,fn:o[e],scope:o.scope});item.on(e,o[e],o.scope,o);}else{this.mons.push({item:item,ename:e,fn:o[e],scope:o.scope});item.on(e,o[e]);}}
+return;}
+this.mons.push({item:item,ename:ename,fn:fn,scope:scope});item.on(ename,fn,scope,opt);},mun:function(item,ename,fn,scope){var found,mon;this.createMons();for(var i=0,len=this.mons.length;i<len;++i){mon=this.mons[i];if(item===mon.item&&ename==mon.ename&&fn===mon.fn&&scope===mon.scope){this.mons.splice(i,1);item.un(ename,fn,scope);found=true;break;}}
+return found;},nextSibling:function(){if(this.ownerCt){var index=this.ownerCt.items.indexOf(this);if(index!=-1&&index+1<this.ownerCt.items.getCount()){return this.ownerCt.items.itemAt(index+1);}}
+return null;},previousSibling:function(){if(this.ownerCt){var index=this.ownerCt.items.indexOf(this);if(index>0){return this.ownerCt.items.itemAt(index-1);}}
+return null;},getBubbleTarget:function(){return this.ownerCt;}});Ext.reg('component',Ext.Component);Ext.Action=Ext.extend(Object,{constructor:function(config){this.initialConfig=config;this.itemId=config.itemId=(config.itemId||config.id||Ext.id());this.items=[];},isAction:true,setText:function(text){this.initialConfig.text=text;this.callEach('setText',[text]);},getText:function(){return this.initialConfig.text;},setIconClass:function(cls){this.initialConfig.iconCls=cls;this.callEach('setIconClass',[cls]);},getIconClass:function(){return this.initialConfig.iconCls;},setDisabled:function(v){this.initialConfig.disabled=v;this.callEach('setDisabled',[v]);},enable:function(){this.setDisabled(false);},disable:function(){this.setDisabled(true);},isDisabled:function(){return this.initialConfig.disabled;},setHidden:function(v){this.initialConfig.hidden=v;this.callEach('setVisible',[!v]);},show:function(){this.setHidden(false);},hide:function(){this.setHidden(true);},isHidden:function(){return this.initialConfig.hidden;},setHandler:function(fn,scope){this.initialConfig.handler=fn;this.initialConfig.scope=scope;this.callEach('setHandler',[fn,scope]);},each:function(fn,scope){Ext.each(this.items,fn,scope);},callEach:function(fnName,args){var cs=this.items;for(var i=0,len=cs.length;i<len;i++){cs[i][fnName].apply(cs[i],args);}},addComponent:function(comp){this.items.push(comp);comp.on('destroy',this.removeComponent,this);},removeComponent:function(comp){this.items.remove(comp);},execute:function(){this.initialConfig.handler.apply(this.initialConfig.scope||window,arguments);}});(function(){Ext.Layer=function(config,existingEl){config=config||{};var dh=Ext.DomHelper,cp=config.parentEl,pel=cp?Ext.getDom(cp):document.body;if(existingEl){this.dom=Ext.getDom(existingEl);}
+if(!this.dom){var o=config.dh||{tag:'div',cls:'x-layer'};this.dom=dh.append(pel,o);}
+if(config.cls){this.addClass(config.cls);}
+this.constrain=config.constrain!==false;this.setVisibilityMode(Ext.Element.VISIBILITY);if(config.id){this.id=this.dom.id=config.id;}else{this.id=Ext.id(this.dom);}
+this.zindex=config.zindex||this.getZIndex();this.position('absolute',this.zindex);if(config.shadow){this.shadowOffset=config.shadowOffset||4;this.shadow=new Ext.Shadow({offset:this.shadowOffset,mode:config.shadow});}else{this.shadowOffset=0;}
+this.useShim=config.shim!==false&&Ext.useShims;this.useDisplay=config.useDisplay;this.hide();};var supr=Ext.Element.prototype;var shims=[];Ext.extend(Ext.Layer,Ext.Element,{getZIndex:function(){return this.zindex||parseInt((this.getShim()||this).getStyle('z-index'),10)||11000;},getShim:function(){if(!this.useShim){return null;}
+if(this.shim){return this.shim;}
+var shim=shims.shift();if(!shim){shim=this.createShim();shim.enableDisplayMode('block');shim.dom.style.display='none';shim.dom.style.visibility='visible';}
+var pn=this.dom.parentNode;if(shim.dom.parentNode!=pn){pn.insertBefore(shim.dom,this.dom);}
+shim.setStyle('z-index',this.getZIndex()-2);this.shim=shim;return shim;},hideShim:function(){if(this.shim){this.shim.setDisplayed(false);shims.push(this.shim);delete this.shim;}},disableShadow:function(){if(this.shadow){this.shadowDisabled=true;this.shadow.hide();this.lastShadowOffset=this.shadowOffset;this.shadowOffset=0;}},enableShadow:function(show){if(this.shadow){this.shadowDisabled=false;this.shadowOffset=this.lastShadowOffset;delete this.lastShadowOffset;if(show){this.sync(true);}}},sync:function(doShow){var shadow=this.shadow;if(!this.updating&&this.isVisible()&&(shadow||this.useShim)){var shim=this.getShim(),w=this.getWidth(),h=this.getHeight(),l=this.getLeft(true),t=this.getTop(true);if(shadow&&!this.shadowDisabled){if(doShow&&!shadow.isVisible()){shadow.show(this);}else{shadow.realign(l,t,w,h);}
+if(shim){if(doShow){shim.show();}
+var shadowAdj=shadow.el.getXY(),shimStyle=shim.dom.style,shadowSize=shadow.el.getSize();shimStyle.left=(shadowAdj[0])+'px';shimStyle.top=(shadowAdj[1])+'px';shimStyle.width=(shadowSize.width)+'px';shimStyle.height=(shadowSize.height)+'px';}}else if(shim){if(doShow){shim.show();}
+shim.setSize(w,h);shim.setLeftTop(l,t);}}},destroy:function(){this.hideShim();if(this.shadow){this.shadow.hide();}
+this.removeAllListeners();Ext.removeNode(this.dom);delete this.dom;},remove:function(){this.destroy();},beginUpdate:function(){this.updating=true;},endUpdate:function(){this.updating=false;this.sync(true);},hideUnders:function(negOffset){if(this.shadow){this.shadow.hide();}
+this.hideShim();},constrainXY:function(){if(this.constrain){var vw=Ext.lib.Dom.getViewWidth(),vh=Ext.lib.Dom.getViewHeight();var s=Ext.getDoc().getScroll();var xy=this.getXY();var x=xy[0],y=xy[1];var so=this.shadowOffset;var w=this.dom.offsetWidth+so,h=this.dom.offsetHeight+so;var moved=false;if((x+w)>vw+s.left){x=vw-w-so;moved=true;}
+if((y+h)>vh+s.top){y=vh-h-so;moved=true;}
+if(x<s.left){x=s.left;moved=true;}
+if(y<s.top){y=s.top;moved=true;}
+if(moved){if(this.avoidY){var ay=this.avoidY;if(y<=ay&&(y+h)>=ay){y=ay-h-5;}}
+xy=[x,y];this.storeXY(xy);supr.setXY.call(this,xy);this.sync();}}
+return this;},getConstrainOffset:function(){return this.shadowOffset;},isVisible:function(){return this.visible;},showAction:function(){this.visible=true;if(this.useDisplay===true){this.setDisplayed('');}else if(this.lastXY){supr.setXY.call(this,this.lastXY);}else if(this.lastLT){supr.setLeftTop.call(this,this.lastLT[0],this.lastLT[1]);}},hideAction:function(){this.visible=false;if(this.useDisplay===true){this.setDisplayed(false);}else{this.setLeftTop(-10000,-10000);}},setVisible:function(v,a,d,c,e){if(v){this.showAction();}
+if(a&&v){var cb=function(){this.sync(true);if(c){c();}}.createDelegate(this);supr.setVisible.call(this,true,true,d,cb,e);}else{if(!v){this.hideUnders(true);}
+var cb=c;if(a){cb=function(){this.hideAction();if(c){c();}}.createDelegate(this);}
+supr.setVisible.call(this,v,a,d,cb,e);if(v){this.sync(true);}else if(!a){this.hideAction();}}
+return this;},storeXY:function(xy){delete this.lastLT;this.lastXY=xy;},storeLeftTop:function(left,top){delete this.lastXY;this.lastLT=[left,top];},beforeFx:function(){this.beforeAction();return Ext.Layer.superclass.beforeFx.apply(this,arguments);},afterFx:function(){Ext.Layer.superclass.afterFx.apply(this,arguments);this.sync(this.isVisible());},beforeAction:function(){if(!this.updating&&this.shadow){this.shadow.hide();}},setLeft:function(left){this.storeLeftTop(left,this.getTop(true));supr.setLeft.apply(this,arguments);this.sync();return this;},setTop:function(top){this.storeLeftTop(this.getLeft(true),top);supr.setTop.apply(this,arguments);this.sync();return this;},setLeftTop:function(left,top){this.storeLeftTop(left,top);supr.setLeftTop.apply(this,arguments);this.sync();return this;},setXY:function(xy,a,d,c,e){this.fixDisplay();this.beforeAction();this.storeXY(xy);var cb=this.createCB(c);supr.setXY.call(this,xy,a,d,cb,e);if(!a){cb();}
+return this;},createCB:function(c){var el=this;return function(){el.constrainXY();el.sync(true);if(c){c();}};},setX:function(x,a,d,c,e){this.setXY([x,this.getY()],a,d,c,e);return this;},setY:function(y,a,d,c,e){this.setXY([this.getX(),y],a,d,c,e);return this;},setSize:function(w,h,a,d,c,e){this.beforeAction();var cb=this.createCB(c);supr.setSize.call(this,w,h,a,d,cb,e);if(!a){cb();}
+return this;},setWidth:function(w,a,d,c,e){this.beforeAction();var cb=this.createCB(c);supr.setWidth.call(this,w,a,d,cb,e);if(!a){cb();}
+return this;},setHeight:function(h,a,d,c,e){this.beforeAction();var cb=this.createCB(c);supr.setHeight.call(this,h,a,d,cb,e);if(!a){cb();}
+return this;},setBounds:function(x,y,w,h,a,d,c,e){this.beforeAction();var cb=this.createCB(c);if(!a){this.storeXY([x,y]);supr.setXY.call(this,[x,y]);supr.setSize.call(this,w,h,a,d,cb,e);cb();}else{supr.setBounds.call(this,x,y,w,h,a,d,cb,e);}
+return this;},setZIndex:function(zindex){this.zindex=zindex;this.setStyle('z-index',zindex+2);if(this.shadow){this.shadow.setZIndex(zindex+1);}
+if(this.shim){this.shim.setStyle('z-index',zindex);}
+return this;}});})();Ext.Shadow=function(config){Ext.apply(this,config);if(typeof this.mode!="string"){this.mode=this.defaultMode;}
+var o=this.offset,a={h:0},rad=Math.floor(this.offset/2);switch(this.mode.toLowerCase()){case"drop":a.w=0;a.l=a.t=o;a.t-=1;if(Ext.isIE){a.l-=this.offset+rad;a.t-=this.offset+rad;a.w-=rad;a.h-=rad;a.t+=1;}
+break;case"sides":a.w=(o*2);a.l=-o;a.t=o-1;if(Ext.isIE){a.l-=(this.offset-rad);a.t-=this.offset+rad;a.l+=1;a.w-=(this.offset-rad)*2;a.w-=rad+1;a.h-=1;}
+break;case"frame":a.w=a.h=(o*2);a.l=a.t=-o;a.t+=1;a.h-=2;if(Ext.isIE){a.l-=(this.offset-rad);a.t-=(this.offset-rad);a.l+=1;a.w-=(this.offset+rad+1);a.h-=(this.offset+rad);a.h+=1;}
+break;};this.adjusts=a;};Ext.Shadow.prototype={offset:4,defaultMode:"drop",show:function(target){target=Ext.get(target);if(!this.el){this.el=Ext.Shadow.Pool.pull();if(this.el.dom.nextSibling!=target.dom){this.el.insertBefore(target);}}
+this.el.setStyle("z-index",this.zIndex||parseInt(target.getStyle("z-index"),10)-1);if(Ext.isIE){this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";}
+this.realign(target.getLeft(true),target.getTop(true),target.getWidth(),target.getHeight());this.el.dom.style.display="block";},isVisible:function(){return this.el?true:false;},realign:function(l,t,w,h){if(!this.el){return;}
+var a=this.adjusts,d=this.el.dom,s=d.style,iea=0,sw=(w+a.w),sh=(h+a.h),sws=sw+"px",shs=sh+"px",cn,sww;s.left=(l+a.l)+"px";s.top=(t+a.t)+"px";if(s.width!=sws||s.height!=shs){s.width=sws;s.height=shs;if(!Ext.isIE){cn=d.childNodes;sww=Math.max(0,(sw-12))+"px";cn[0].childNodes[1].style.width=sww;cn[1].childNodes[1].style.width=sww;cn[2].childNodes[1].style.width=sww;cn[1].style.height=Math.max(0,(sh-12))+"px";}}},hide:function(){if(this.el){this.el.dom.style.display="none";Ext.Shadow.Pool.push(this.el);delete this.el;}},setZIndex:function(z){this.zIndex=z;if(this.el){this.el.setStyle("z-index",z);}}};Ext.Shadow.Pool=function(){var p=[],markup=Ext.isIE?'<div class="x-ie-shadow"></div>':'<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';return{pull:function(){var sh=p.shift();if(!sh){sh=Ext.get(Ext.DomHelper.insertHtml("beforeBegin",document.body.firstChild,markup));sh.autoBoxAdjust=false;}
+return sh;},push:function(sh){p.push(sh);}};}();Ext.BoxComponent=Ext.extend(Ext.Component,{initComponent:function(){Ext.BoxComponent.superclass.initComponent.call(this);this.addEvents('resize','move');},boxReady:false,deferHeight:false,setSize:function(w,h){if(typeof w=='object'){h=w.height;w=w.width;}
+if(Ext.isDefined(w)&&Ext.isDefined(this.boxMinWidth)&&(w<this.boxMinWidth)){w=this.boxMinWidth;}
+if(Ext.isDefined(h)&&Ext.isDefined(this.boxMinHeight)&&(h<this.boxMinHeight)){h=this.boxMinHeight;}
+if(Ext.isDefined(w)&&Ext.isDefined(this.boxMaxWidth)&&(w>this.boxMaxWidth)){w=this.boxMaxWidth;}
+if(Ext.isDefined(h)&&Ext.isDefined(this.boxMaxHeight)&&(h>this.boxMaxHeight)){h=this.boxMaxHeight;}
+if(!this.boxReady){this.width=w;this.height=h;return this;}
+if(this.cacheSizes!==false&&this.lastSize&&this.lastSize.width==w&&this.lastSize.height==h){return this;}
+this.lastSize={width:w,height:h};var adj=this.adjustSize(w,h),aw=adj.width,ah=adj.height,rz;if(aw!==undefined||ah!==undefined){rz=this.getResizeEl();if(!this.deferHeight&&aw!==undefined&&ah!==undefined){rz.setSize(aw,ah);}else if(!this.deferHeight&&ah!==undefined){rz.setHeight(ah);}else if(aw!==undefined){rz.setWidth(aw);}
+this.onResize(aw,ah,w,h);this.fireEvent('resize',this,aw,ah,w,h);}
+return this;},setWidth:function(width){return this.setSize(width);},setHeight:function(height){return this.setSize(undefined,height);},getSize:function(){return this.getResizeEl().getSize();},getWidth:function(){return this.getResizeEl().getWidth();},getHeight:function(){return this.getResizeEl().getHeight();},getOuterSize:function(){var el=this.getResizeEl();return{width:el.getWidth()+el.getMargins('lr'),height:el.getHeight()+el.getMargins('tb')};},getPosition:function(local){var el=this.getPositionEl();if(local===true){return[el.getLeft(true),el.getTop(true)];}
+return this.xy||el.getXY();},getBox:function(local){var pos=this.getPosition(local);var s=this.getSize();s.x=pos[0];s.y=pos[1];return s;},updateBox:function(box){this.setSize(box.width,box.height);this.setPagePosition(box.x,box.y);return this;},getResizeEl:function(){return this.resizeEl||this.el;},setAutoScroll:function(scroll){if(this.rendered){this.getContentTarget().setOverflow(scroll?'auto':'');}
+this.autoScroll=scroll;return this;},setPosition:function(x,y){if(x&&typeof x[1]=='number'){y=x[1];x=x[0];}
+this.x=x;this.y=y;if(!this.boxReady){return this;}
+var adj=this.adjustPosition(x,y);var ax=adj.x,ay=adj.y;var el=this.getPositionEl();if(ax!==undefined||ay!==undefined){if(ax!==undefined&&ay!==undefined){el.setLeftTop(ax,ay);}else if(ax!==undefined){el.setLeft(ax);}else if(ay!==undefined){el.setTop(ay);}
+this.onPosition(ax,ay);this.fireEvent('move',this,ax,ay);}
+return this;},setPagePosition:function(x,y){if(x&&typeof x[1]=='number'){y=x[1];x=x[0];}
+this.pageX=x;this.pageY=y;if(!this.boxReady){return;}
+if(x===undefined||y===undefined){return;}
+var p=this.getPositionEl().translatePoints(x,y);this.setPosition(p.left,p.top);return this;},afterRender:function(){Ext.BoxComponent.superclass.afterRender.call(this);if(this.resizeEl){this.resizeEl=Ext.get(this.resizeEl);}
+if(this.positionEl){this.positionEl=Ext.get(this.positionEl);}
+this.boxReady=true;Ext.isDefined(this.autoScroll)&&this.setAutoScroll(this.autoScroll);this.setSize(this.width,this.height);if(this.x||this.y){this.setPosition(this.x,this.y);}else if(this.pageX||this.pageY){this.setPagePosition(this.pageX,this.pageY);}},syncSize:function(){delete this.lastSize;this.setSize(this.autoWidth?undefined:this.getResizeEl().getWidth(),this.autoHeight?undefined:this.getResizeEl().getHeight());return this;},onResize:function(adjWidth,adjHeight,rawWidth,rawHeight){},onPosition:function(x,y){},adjustSize:function(w,h){if(this.autoWidth){w='auto';}
+if(this.autoHeight){h='auto';}
+return{width:w,height:h};},adjustPosition:function(x,y){return{x:x,y:y};}});Ext.reg('box',Ext.BoxComponent);Ext.Spacer=Ext.extend(Ext.BoxComponent,{autoEl:'div'});Ext.reg('spacer',Ext.Spacer);Ext.SplitBar=function(dragElement,resizingElement,orientation,placement,existingProxy){this.el=Ext.get(dragElement,true);this.el.dom.unselectable="on";this.resizingEl=Ext.get(resizingElement,true);this.orientation=orientation||Ext.SplitBar.HORIZONTAL;this.minSize=0;this.maxSize=2000;this.animate=false;this.useShim=false;this.shim=null;if(!existingProxy){this.proxy=Ext.SplitBar.createProxy(this.orientation);}else{this.proxy=Ext.get(existingProxy).dom;}
+this.dd=new Ext.dd.DDProxy(this.el.dom.id,"XSplitBars",{dragElId:this.proxy.id});this.dd.b4StartDrag=this.onStartProxyDrag.createDelegate(this);this.dd.endDrag=this.onEndProxyDrag.createDelegate(this);this.dragSpecs={};this.adapter=new Ext.SplitBar.BasicLayoutAdapter();this.adapter.init(this);if(this.orientation==Ext.SplitBar.HORIZONTAL){this.placement=placement||(this.el.getX()>this.resizingEl.getX()?Ext.SplitBar.LEFT:Ext.SplitBar.RIGHT);this.el.addClass("x-splitbar-h");}else{this.placement=placement||(this.el.getY()>this.resizingEl.getY()?Ext.SplitBar.TOP:Ext.SplitBar.BOTTOM);this.el.addClass("x-splitbar-v");}
+this.addEvents("resize","moved","beforeresize","beforeapply");Ext.SplitBar.superclass.constructor.call(this);};Ext.extend(Ext.SplitBar,Ext.util.Observable,{onStartProxyDrag:function(x,y){this.fireEvent("beforeresize",this);this.overlay=Ext.DomHelper.append(document.body,{cls:"x-drag-overlay",html:"&#160;"},true);this.overlay.unselectable();this.overlay.setSize(Ext.lib.Dom.getViewWidth(true),Ext.lib.Dom.getViewHeight(true));this.overlay.show();Ext.get(this.proxy).setDisplayed("block");var size=this.adapter.getElementSize(this);this.activeMinSize=this.getMinimumSize();this.activeMaxSize=this.getMaximumSize();var c1=size-this.activeMinSize;var c2=Math.max(this.activeMaxSize-size,0);if(this.orientation==Ext.SplitBar.HORIZONTAL){this.dd.resetConstraints();this.dd.setXConstraint(this.placement==Ext.SplitBar.LEFT?c1:c2,this.placement==Ext.SplitBar.LEFT?c2:c1,this.tickSize);this.dd.setYConstraint(0,0);}else{this.dd.resetConstraints();this.dd.setXConstraint(0,0);this.dd.setYConstraint(this.placement==Ext.SplitBar.TOP?c1:c2,this.placement==Ext.SplitBar.TOP?c2:c1,this.tickSize);}
+this.dragSpecs.startSize=size;this.dragSpecs.startPoint=[x,y];Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd,x,y);},onEndProxyDrag:function(e){Ext.get(this.proxy).setDisplayed(false);var endPoint=Ext.lib.Event.getXY(e);if(this.overlay){Ext.destroy(this.overlay);delete this.overlay;}
+var newSize;if(this.orientation==Ext.SplitBar.HORIZONTAL){newSize=this.dragSpecs.startSize+
+(this.placement==Ext.SplitBar.LEFT?endPoint[0]-this.dragSpecs.startPoint[0]:this.dragSpecs.startPoint[0]-endPoint[0]);}else{newSize=this.dragSpecs.startSize+
+(this.placement==Ext.SplitBar.TOP?endPoint[1]-this.dragSpecs.startPoint[1]:this.dragSpecs.startPoint[1]-endPoint[1]);}
+newSize=Math.min(Math.max(newSize,this.activeMinSize),this.activeMaxSize);if(newSize!=this.dragSpecs.startSize){if(this.fireEvent('beforeapply',this,newSize)!==false){this.adapter.setElementSize(this,newSize);this.fireEvent("moved",this,newSize);this.fireEvent("resize",this,newSize);}}},getAdapter:function(){return this.adapter;},setAdapter:function(adapter){this.adapter=adapter;this.adapter.init(this);},getMinimumSize:function(){return this.minSize;},setMinimumSize:function(minSize){this.minSize=minSize;},getMaximumSize:function(){return this.maxSize;},setMaximumSize:function(maxSize){this.maxSize=maxSize;},setCurrentSize:function(size){var oldAnimate=this.animate;this.animate=false;this.adapter.setElementSize(this,size);this.animate=oldAnimate;},destroy:function(removeEl){Ext.destroy(this.shim,Ext.get(this.proxy));this.dd.unreg();if(removeEl){this.el.remove();}
+this.purgeListeners();}});Ext.SplitBar.createProxy=function(dir){var proxy=new Ext.Element(document.createElement("div"));document.body.appendChild(proxy.dom);proxy.unselectable();var cls='x-splitbar-proxy';proxy.addClass(cls+' '+(dir==Ext.SplitBar.HORIZONTAL?cls+'-h':cls+'-v'));return proxy.dom;};Ext.SplitBar.BasicLayoutAdapter=function(){};Ext.SplitBar.BasicLayoutAdapter.prototype={init:function(s){},getElementSize:function(s){if(s.orientation==Ext.SplitBar.HORIZONTAL){return s.resizingEl.getWidth();}else{return s.resizingEl.getHeight();}},setElementSize:function(s,newSize,onComplete){if(s.orientation==Ext.SplitBar.HORIZONTAL){if(!s.animate){s.resizingEl.setWidth(newSize);if(onComplete){onComplete(s,newSize);}}else{s.resizingEl.setWidth(newSize,true,.1,onComplete,'easeOut');}}else{if(!s.animate){s.resizingEl.setHeight(newSize);if(onComplete){onComplete(s,newSize);}}else{s.resizingEl.setHeight(newSize,true,.1,onComplete,'easeOut');}}}};Ext.SplitBar.AbsoluteLayoutAdapter=function(container){this.basic=new Ext.SplitBar.BasicLayoutAdapter();this.container=Ext.get(container);};Ext.SplitBar.AbsoluteLayoutAdapter.prototype={init:function(s){this.basic.init(s);},getElementSize:function(s){return this.basic.getElementSize(s);},setElementSize:function(s,newSize,onComplete){this.basic.setElementSize(s,newSize,this.moveSplitter.createDelegate(this,[s]));},moveSplitter:function(s){var yes=Ext.SplitBar;switch(s.placement){case yes.LEFT:s.el.setX(s.resizingEl.getRight());break;case yes.RIGHT:s.el.setStyle("right",(this.container.getWidth()-s.resizingEl.getLeft())+"px");break;case yes.TOP:s.el.setY(s.resizingEl.getBottom());break;case yes.BOTTOM:s.el.setY(s.resizingEl.getTop()-s.el.getHeight());break;}}};Ext.SplitBar.VERTICAL=1;Ext.SplitBar.HORIZONTAL=2;Ext.SplitBar.LEFT=1;Ext.SplitBar.RIGHT=2;Ext.SplitBar.TOP=3;Ext.SplitBar.BOTTOM=4;Ext.Container=Ext.extend(Ext.BoxComponent,{bufferResize:50,autoDestroy:true,forceLayout:false,defaultType:'panel',resizeEvent:'resize',bubbleEvents:['add','remove'],initComponent:function(){Ext.Container.superclass.initComponent.call(this);this.addEvents('afterlayout','beforeadd','beforeremove','add','remove');var items=this.items;if(items){delete this.items;this.add(items);}},initItems:function(){if(!this.items){this.items=new Ext.util.MixedCollection(false,this.getComponentId);this.getLayout();}},setLayout:function(layout){if(this.layout&&this.layout!=layout){this.layout.setContainer(null);}
+this.layout=layout;this.initItems();layout.setContainer(this);},afterRender:function(){Ext.Container.superclass.afterRender.call(this);if(!this.layout){this.layout='auto';}
+if(Ext.isObject(this.layout)&&!this.layout.layout){this.layoutConfig=this.layout;this.layout=this.layoutConfig.type;}
+if(Ext.isString(this.layout)){this.layout=new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);}
+this.setLayout(this.layout);if(this.activeItem!==undefined&&this.layout.setActiveItem){var item=this.activeItem;delete this.activeItem;this.layout.setActiveItem(item);}
+if(!this.ownerCt){this.doLayout(false,true);}
+if(this.monitorResize===true){Ext.EventManager.onWindowResize(this.doLayout,this,[false]);}},getLayoutTarget:function(){return this.el;},getComponentId:function(comp){return comp.getItemId();},add:function(comp){this.initItems();var args=arguments.length>1;if(args||Ext.isArray(comp)){var result=[];Ext.each(args?arguments:comp,function(c){result.push(this.add(c));},this);return result;}
+var c=this.lookupComponent(this.applyDefaults(comp));var index=this.items.length;if(this.fireEvent('beforeadd',this,c,index)!==false&&this.onBeforeAdd(c)!==false){this.items.add(c);c.onAdded(this,index);this.onAdd(c);this.fireEvent('add',this,c,index);}
+return c;},onAdd:function(c){},onAdded:function(container,pos){this.ownerCt=container;this.initRef();this.cascade(function(c){c.initRef();});this.fireEvent('added',this,container,pos);},insert:function(index,comp){var args=arguments,length=args.length,result=[],i,c;this.initItems();if(length>2){for(i=length-1;i>=1;--i){result.push(this.insert(index,args[i]));}
+return result;}
+c=this.lookupComponent(this.applyDefaults(comp));index=Math.min(index,this.items.length);if(this.fireEvent('beforeadd',this,c,index)!==false&&this.onBeforeAdd(c)!==false){if(c.ownerCt==this){this.items.remove(c);}
+this.items.insert(index,c);c.onAdded(this,index);this.onAdd(c);this.fireEvent('add',this,c,index);}
+return c;},applyDefaults:function(c){var d=this.defaults;if(d){if(Ext.isFunction(d)){d=d.call(this,c);}
+if(Ext.isString(c)){c=Ext.ComponentMgr.get(c);Ext.apply(c,d);}else if(!c.events){Ext.applyIf(c.isAction?c.initialConfig:c,d);}else{Ext.apply(c,d);}}
+return c;},onBeforeAdd:function(item){if(item.ownerCt){item.ownerCt.remove(item,false);}
+if(this.hideBorders===true){item.border=(item.border===true);}},remove:function(comp,autoDestroy){this.initItems();var c=this.getComponent(comp);if(c&&this.fireEvent('beforeremove',this,c)!==false){this.doRemove(c,autoDestroy);this.fireEvent('remove',this,c);}
+return c;},onRemove:function(c){},doRemove:function(c,autoDestroy){var l=this.layout,hasLayout=l&&this.rendered;if(hasLayout){l.onRemove(c);}
+this.items.remove(c);c.onRemoved();this.onRemove(c);if(autoDestroy===true||(autoDestroy!==false&&this.autoDestroy)){c.destroy();}
+if(hasLayout){l.afterRemove(c);}},removeAll:function(autoDestroy){this.initItems();var item,rem=[],items=[];this.items.each(function(i){rem.push(i);});for(var i=0,len=rem.length;i<len;++i){item=rem[i];this.remove(item,autoDestroy);if(item.ownerCt!==this){items.push(item);}}
+return items;},getComponent:function(comp){if(Ext.isObject(comp)){comp=comp.getItemId();}
+return this.items.get(comp);},lookupComponent:function(comp){if(Ext.isString(comp)){return Ext.ComponentMgr.get(comp);}else if(!comp.events){return this.createComponent(comp);}
+return comp;},createComponent:function(config,defaultType){if(config.render){return config;}
+var c=Ext.create(Ext.apply({ownerCt:this},config),defaultType||this.defaultType);delete c.initialConfig.ownerCt;delete c.ownerCt;return c;},canLayout:function(){var el=this.getVisibilityEl();return el&&el.dom&&!el.isStyle("display","none");},doLayout:function(shallow,force){var rendered=this.rendered,forceLayout=force||this.forceLayout;if(this.collapsed||!this.canLayout()){this.deferLayout=this.deferLayout||!shallow;if(!forceLayout){return;}
+shallow=shallow&&!this.deferLayout;}else{delete this.deferLayout;}
+if(rendered&&this.layout){this.layout.layout();}
+if(shallow!==true&&this.items){var cs=this.items.items;for(var i=0,len=cs.length;i<len;i++){var c=cs[i];if(c.doLayout){c.doLayout(false,forceLayout);}}}
+if(rendered){this.onLayout(shallow,forceLayout);}
+this.hasLayout=true;delete this.forceLayout;},onLayout:Ext.emptyFn,shouldBufferLayout:function(){var hl=this.hasLayout;if(this.ownerCt){return hl?!this.hasLayoutPending():false;}
+return hl;},hasLayoutPending:function(){var pending=false;this.ownerCt.bubble(function(c){if(c.layoutPending){pending=true;return false;}});return pending;},onShow:function(){Ext.Container.superclass.onShow.call(this);if(Ext.isDefined(this.deferLayout)){delete this.deferLayout;this.doLayout(true);}},getLayout:function(){if(!this.layout){var layout=new Ext.layout.AutoLayout(this.layoutConfig);this.setLayout(layout);}
+return this.layout;},beforeDestroy:function(){var c;if(this.items){while(c=this.items.first()){this.doRemove(c,true);}}
+if(this.monitorResize){Ext.EventManager.removeResizeListener(this.doLayout,this);}
+Ext.destroy(this.layout);Ext.Container.superclass.beforeDestroy.call(this);},cascade:function(fn,scope,args){if(fn.apply(scope||this,args||[this])!==false){if(this.items){var cs=this.items.items;for(var i=0,len=cs.length;i<len;i++){if(cs[i].cascade){cs[i].cascade(fn,scope,args);}else{fn.apply(scope||cs[i],args||[cs[i]]);}}}}
+return this;},findById:function(id){var m=null,ct=this;this.cascade(function(c){if(ct!=c&&c.id===id){m=c;return false;}});return m;},findByType:function(xtype,shallow){return this.findBy(function(c){return c.isXType(xtype,shallow);});},find:function(prop,value){return this.findBy(function(c){return c[prop]===value;});},findBy:function(fn,scope){var m=[],ct=this;this.cascade(function(c){if(ct!=c&&fn.call(scope||c,c,ct)===true){m.push(c);}});return m;},get:function(key){return this.getComponent(key);}});Ext.Container.LAYOUTS={};Ext.reg('container',Ext.Container);Ext.layout.ContainerLayout=Ext.extend(Object,{monitorResize:false,activeItem:null,constructor:function(config){this.id=Ext.id(null,'ext-layout-');Ext.apply(this,config);},type:'container',IEMeasureHack:function(target,viewFlag){var tChildren=target.dom.childNodes,tLen=tChildren.length,c,d=[],e,i,ret;for(i=0;i<tLen;i++){c=tChildren[i];e=Ext.get(c);if(e){d[i]=e.getStyle('display');e.setStyle({display:'none'});}}
+ret=target?target.getViewSize(viewFlag):{};for(i=0;i<tLen;i++){c=tChildren[i];e=Ext.get(c);if(e){e.setStyle({display:d[i]});}}
+return ret;},getLayoutTargetSize:Ext.EmptyFn,layout:function(){var ct=this.container,target=ct.getLayoutTarget();if(!(this.hasLayout||Ext.isEmpty(this.targetCls))){target.addClass(this.targetCls);}
+this.onLayout(ct,target);ct.fireEvent('afterlayout',ct,this);},onLayout:function(ct,target){this.renderAll(ct,target);},isValidParent:function(c,target){return target&&c.getPositionEl().dom.parentNode==(target.dom||target);},renderAll:function(ct,target){var items=ct.items.items,i,c,len=items.length;for(i=0;i<len;i++){c=items[i];if(c&&(!c.rendered||!this.isValidParent(c,target))){this.renderItem(c,i,target);}}},renderItem:function(c,position,target){if(c){if(!c.rendered){c.render(target,position);this.configureItem(c);}else if(!this.isValidParent(c,target)){if(Ext.isNumber(position)){position=target.dom.childNodes[position];}
+target.dom.insertBefore(c.getPositionEl().dom,position||null);c.container=target;this.configureItem(c);}}},getRenderedItems:function(ct){var t=ct.getLayoutTarget(),cti=ct.items.items,len=cti.length,i,c,items=[];for(i=0;i<len;i++){if((c=cti[i]).rendered&&this.isValidParent(c,t)&&c.shouldLayout!==false){items.push(c);}};return items;},configureItem:function(c){if(this.extraCls){var t=c.getPositionEl?c.getPositionEl():c;t.addClass(this.extraCls);}
+if(c.doLayout&&this.forceLayout){c.doLayout();}
+if(this.renderHidden&&c!=this.activeItem){c.hide();}},onRemove:function(c){if(this.activeItem==c){delete this.activeItem;}
+if(c.rendered&&this.extraCls){var t=c.getPositionEl?c.getPositionEl():c;t.removeClass(this.extraCls);}},afterRemove:function(c){if(c.removeRestore){c.removeMode='container';delete c.removeRestore;}},onResize:function(){var ct=this.container,b;if(ct.collapsed){return;}
+if(b=ct.bufferResize&&ct.shouldBufferLayout()){if(!this.resizeTask){this.resizeTask=new Ext.util.DelayedTask(this.runLayout,this);this.resizeBuffer=Ext.isNumber(b)?b:50;}
+ct.layoutPending=true;this.resizeTask.delay(this.resizeBuffer);}else{this.runLayout();}},runLayout:function(){var ct=this.container;this.layout();ct.onLayout();delete ct.layoutPending;},setContainer:function(ct){if(this.monitorResize&&ct!=this.container){var old=this.container;if(old){old.un(old.resizeEvent,this.onResize,this);}
+if(ct){ct.on(ct.resizeEvent,this.onResize,this);}}
+this.container=ct;},parseMargins:function(v){if(Ext.isNumber(v)){v=v.toString();}
+var ms=v.split(' '),len=ms.length;if(len==1){ms[1]=ms[2]=ms[3]=ms[0];}else if(len==2){ms[2]=ms[0];ms[3]=ms[1];}else if(len==3){ms[3]=ms[1];}
+return{top:parseInt(ms[0],10)||0,right:parseInt(ms[1],10)||0,bottom:parseInt(ms[2],10)||0,left:parseInt(ms[3],10)||0};},fieldTpl:(function(){var t=new Ext.Template('<div class="x-form-item {itemCls}" tabIndex="-1">','<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>','<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">','</div><div class="{clearCls}"></div>','</div>');t.disableFormats=true;return t.compile();})(),destroy:function(){if(this.resizeTask&&this.resizeTask.cancel){this.resizeTask.cancel();}
+if(this.container){this.container.un(this.container.resizeEvent,this.onResize,this);}
+if(!Ext.isEmpty(this.targetCls)){var target=this.container.getLayoutTarget();if(target){target.removeClass(this.targetCls);}}}});Ext.layout.AutoLayout=Ext.extend(Ext.layout.ContainerLayout,{type:'auto',monitorResize:true,onLayout:function(ct,target){Ext.layout.AutoLayout.superclass.onLayout.call(this,ct,target);var cs=this.getRenderedItems(ct),len=cs.length,i,c;for(i=0;i<len;i++){c=cs[i];if(c.doLayout){c.doLayout(true);}}}});Ext.Container.LAYOUTS['auto']=Ext.layout.AutoLayout;Ext.layout.FitLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,type:'fit',getLayoutTargetSize:function(){var target=this.container.getLayoutTarget();if(!target){return{};}
+return target.getStyleSize();},onLayout:function(ct,target){Ext.layout.FitLayout.superclass.onLayout.call(this,ct,target);if(!ct.collapsed){this.setItemSize(this.activeItem||ct.items.itemAt(0),this.getLayoutTargetSize());}},setItemSize:function(item,size){if(item&&size.height>0){item.setSize(size);}}});Ext.Container.LAYOUTS['fit']=Ext.layout.FitLayout;Ext.layout.CardLayout=Ext.extend(Ext.layout.FitLayout,{deferredRender:false,layoutOnCardChange:false,renderHidden:true,type:'card',setActiveItem:function(item){var ai=this.activeItem,ct=this.container;item=ct.getComponent(item);if(item&&ai!=item){if(ai){ai.hide();if(ai.hidden!==true){return false;}
+ai.fireEvent('deactivate',ai);}
+var layout=item.doLayout&&(this.layoutOnCardChange||!item.rendered);this.activeItem=item;delete item.deferLayout;item.show();this.layout();if(layout){item.doLayout();}
+item.fireEvent('activate',item);}},renderAll:function(ct,target){if(this.deferredRender){this.renderItem(this.activeItem,undefined,target);}else{Ext.layout.CardLayout.superclass.renderAll.call(this,ct,target);}}});Ext.Container.LAYOUTS['card']=Ext.layout.CardLayout;Ext.layout.AnchorLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,type:'anchor',defaultAnchor:'100%',parseAnchorRE:/^(r|right|b|bottom)$/i,getLayoutTargetSize:function(){var target=this.container.getLayoutTarget(),ret={};if(target){ret=target.getViewSize();if(Ext.isIE&&Ext.isStrict&&ret.width==0){ret=target.getStyleSize();}
+ret.width-=target.getPadding('lr');ret.height-=target.getPadding('tb');}
+return ret;},onLayout:function(container,target){Ext.layout.AnchorLayout.superclass.onLayout.call(this,container,target);var size=this.getLayoutTargetSize(),containerWidth=size.width,containerHeight=size.height,overflow=target.getStyle('overflow'),components=this.getRenderedItems(container),len=components.length,boxes=[],box,anchorWidth,anchorHeight,component,anchorSpec,calcWidth,calcHeight,anchorsArray,totalHeight=0,i,el;if(containerWidth<20&&containerHeight<20){return;}
+if(container.anchorSize){if(typeof container.anchorSize=='number'){anchorWidth=container.anchorSize;}else{anchorWidth=container.anchorSize.width;anchorHeight=container.anchorSize.height;}}else{anchorWidth=container.initialConfig.width;anchorHeight=container.initialConfig.height;}
+for(i=0;i<len;i++){component=components[i];el=component.getPositionEl();if(!component.anchor&&component.items&&!Ext.isNumber(component.width)&&!(Ext.isIE6&&Ext.isStrict)){component.anchor=this.defaultAnchor;}
+if(component.anchor){anchorSpec=component.anchorSpec;if(!anchorSpec){anchorsArray=component.anchor.split(' ');component.anchorSpec=anchorSpec={right:this.parseAnchor(anchorsArray[0],component.initialConfig.width,anchorWidth),bottom:this.parseAnchor(anchorsArray[1],component.initialConfig.height,anchorHeight)};}
+calcWidth=anchorSpec.right?this.adjustWidthAnchor(anchorSpec.right(containerWidth)-el.getMargins('lr'),component):undefined;calcHeight=anchorSpec.bottom?this.adjustHeightAnchor(anchorSpec.bottom(containerHeight)-el.getMargins('tb'),component):undefined;if(calcWidth||calcHeight){boxes.push({component:component,width:calcWidth||undefined,height:calcHeight||undefined});}}}
+for(i=0,len=boxes.length;i<len;i++){box=boxes[i];box.component.setSize(box.width,box.height);}
+if(overflow&&overflow!='hidden'&&!this.adjustmentPass){var newTargetSize=this.getLayoutTargetSize();if(newTargetSize.width!=size.width||newTargetSize.height!=size.height){this.adjustmentPass=true;this.onLayout(container,target);}}
+delete this.adjustmentPass;},parseAnchor:function(a,start,cstart){if(a&&a!='none'){var last;if(this.parseAnchorRE.test(a)){var diff=cstart-start;return function(v){if(v!==last){last=v;return v-diff;}};}else if(a.indexOf('%')!=-1){var ratio=parseFloat(a.replace('%',''))*.01;return function(v){if(v!==last){last=v;return Math.floor(v*ratio);}};}else{a=parseInt(a,10);if(!isNaN(a)){return function(v){if(v!==last){last=v;return v+a;}};}}}
+return false;},adjustWidthAnchor:function(value,comp){return value;},adjustHeightAnchor:function(value,comp){return value;}});Ext.Container.LAYOUTS['anchor']=Ext.layout.AnchorLayout;Ext.layout.ColumnLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,type:'column',extraCls:'x-column',scrollOffset:0,targetCls:'x-column-layout-ct',isValidParent:function(c,target){return this.innerCt&&c.getPositionEl().dom.parentNode==this.innerCt.dom;},getLayoutTargetSize:function(){var target=this.container.getLayoutTarget(),ret;if(target){ret=target.getViewSize();if(Ext.isIE&&Ext.isStrict&&ret.width==0){ret=target.getStyleSize();}
+ret.width-=target.getPadding('lr');ret.height-=target.getPadding('tb');}
+return ret;},renderAll:function(ct,target){if(!this.innerCt){this.innerCt=target.createChild({cls:'x-column-inner'});this.innerCt.createChild({cls:'x-clear'});}
+Ext.layout.ColumnLayout.superclass.renderAll.call(this,ct,this.innerCt);},onLayout:function(ct,target){var cs=ct.items.items,len=cs.length,c,i,m,margins=[];this.renderAll(ct,target);var size=this.getLayoutTargetSize();if(size.width<1&&size.height<1){return;}
+var w=size.width-this.scrollOffset,h=size.height,pw=w;this.innerCt.setWidth(w);for(i=0;i<len;i++){c=cs[i];m=c.getPositionEl().getMargins('lr');margins[i]=m;if(!c.columnWidth){pw-=(c.getWidth()+m);}}
+pw=pw<0?0:pw;for(i=0;i<len;i++){c=cs[i];m=margins[i];if(c.columnWidth){c.setSize(Math.floor(c.columnWidth*pw)-m);}}
+if(Ext.isIE){if(i=target.getStyle('overflow')&&i!='hidden'&&!this.adjustmentPass){var ts=this.getLayoutTargetSize();if(ts.width!=size.width){this.adjustmentPass=true;this.onLayout(ct,target);}}}
+delete this.adjustmentPass;}});Ext.Container.LAYOUTS['column']=Ext.layout.ColumnLayout;Ext.layout.BorderLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,rendered:false,type:'border',targetCls:'x-border-layout-ct',getLayoutTargetSize:function(){var target=this.container.getLayoutTarget();return target?target.getViewSize():{};},onLayout:function(ct,target){var collapsed,i,c,pos,items=ct.items.items,len=items.length;if(!this.rendered){collapsed=[];for(i=0;i<len;i++){c=items[i];pos=c.region;if(c.collapsed){collapsed.push(c);}
+c.collapsed=false;if(!c.rendered){c.render(target,i);c.getPositionEl().addClass('x-border-panel');}
+this[pos]=pos!='center'&&c.split?new Ext.layout.BorderLayout.SplitRegion(this,c.initialConfig,pos):new Ext.layout.BorderLayout.Region(this,c.initialConfig,pos);this[pos].render(target,c);}
+this.rendered=true;}
+var size=this.getLayoutTargetSize();if(size.width<20||size.height<20){if(collapsed){this.restoreCollapsed=collapsed;}
+return;}else if(this.restoreCollapsed){collapsed=this.restoreCollapsed;delete this.restoreCollapsed;}
+var w=size.width,h=size.height,centerW=w,centerH=h,centerY=0,centerX=0,n=this.north,s=this.south,west=this.west,e=this.east,c=this.center,b,m,totalWidth,totalHeight;if(!c&&Ext.layout.BorderLayout.WARN!==false){throw'No center region defined in BorderLayout '+ct.id;}
+if(n&&n.isVisible()){b=n.getSize();m=n.getMargins();b.width=w-(m.left+m.right);b.x=m.left;b.y=m.top;centerY=b.height+b.y+m.bottom;centerH-=centerY;n.applyLayout(b);}
+if(s&&s.isVisible()){b=s.getSize();m=s.getMargins();b.width=w-(m.left+m.right);b.x=m.left;totalHeight=(b.height+m.top+m.bottom);b.y=h-totalHeight+m.top;centerH-=totalHeight;s.applyLayout(b);}
+if(west&&west.isVisible()){b=west.getSize();m=west.getMargins();b.height=centerH-(m.top+m.bottom);b.x=m.left;b.y=centerY+m.top;totalWidth=(b.width+m.left+m.right);centerX+=totalWidth;centerW-=totalWidth;west.applyLayout(b);}
+if(e&&e.isVisible()){b=e.getSize();m=e.getMargins();b.height=centerH-(m.top+m.bottom);totalWidth=(b.width+m.left+m.right);b.x=w-totalWidth+m.left;b.y=centerY+m.top;centerW-=totalWidth;e.applyLayout(b);}
+if(c){m=c.getMargins();var centerBox={x:centerX+m.left,y:centerY+m.top,width:centerW-(m.left+m.right),height:centerH-(m.top+m.bottom)};c.applyLayout(centerBox);}
+if(collapsed){for(i=0,len=collapsed.length;i<len;i++){collapsed[i].collapse(false);}}
+if(Ext.isIE&&Ext.isStrict){target.repaint();}
+if(i=target.getStyle('overflow')&&i!='hidden'&&!this.adjustmentPass){var ts=this.getLayoutTargetSize();if(ts.width!=size.width||ts.height!=size.height){this.adjustmentPass=true;this.onLayout(ct,target);}}
+delete this.adjustmentPass;},destroy:function(){var r=['north','south','east','west'],i,region;for(i=0;i<r.length;i++){region=this[r[i]];if(region){if(region.destroy){region.destroy();}else if(region.split){region.split.destroy(true);}}}
+Ext.layout.BorderLayout.superclass.destroy.call(this);}});Ext.layout.BorderLayout.Region=function(layout,config,pos){Ext.apply(this,config);this.layout=layout;this.position=pos;this.state={};if(typeof this.margins=='string'){this.margins=this.layout.parseMargins(this.margins);}
+this.margins=Ext.applyIf(this.margins||{},this.defaultMargins);if(this.collapsible){if(typeof this.cmargins=='string'){this.cmargins=this.layout.parseMargins(this.cmargins);}
+if(this.collapseMode=='mini'&&!this.cmargins){this.cmargins={left:0,top:0,right:0,bottom:0};}else{this.cmargins=Ext.applyIf(this.cmargins||{},pos=='north'||pos=='south'?this.defaultNSCMargins:this.defaultEWCMargins);}}};Ext.layout.BorderLayout.Region.prototype={collapsible:false,split:false,floatable:true,minWidth:50,minHeight:50,defaultMargins:{left:0,top:0,right:0,bottom:0},defaultNSCMargins:{left:5,top:5,right:5,bottom:5},defaultEWCMargins:{left:5,top:0,right:5,bottom:0},floatingZIndex:100,isCollapsed:false,render:function(ct,p){this.panel=p;p.el.enableDisplayMode();this.targetEl=ct;this.el=p.el;var gs=p.getState,ps=this.position;p.getState=function(){return Ext.apply(gs.call(p)||{},this.state);}.createDelegate(this);if(ps!='center'){p.allowQueuedExpand=false;p.on({beforecollapse:this.beforeCollapse,collapse:this.onCollapse,beforeexpand:this.beforeExpand,expand:this.onExpand,hide:this.onHide,show:this.onShow,scope:this});if(this.collapsible||this.floatable){p.collapseEl='el';p.slideAnchor=this.getSlideAnchor();}
+if(p.tools&&p.tools.toggle){p.tools.toggle.addClass('x-tool-collapse-'+ps);p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');}}},getCollapsedEl:function(){if(!this.collapsedEl){if(!this.toolTemplate){var tt=new Ext.Template('<div class="x-tool x-tool-{id}">&#160;</div>');tt.disableFormats=true;tt.compile();Ext.layout.BorderLayout.Region.prototype.toolTemplate=tt;}
+this.collapsedEl=this.targetEl.createChild({cls:"x-layout-collapsed x-layout-collapsed-"+this.position,id:this.panel.id+'-xcollapsed'});this.collapsedEl.enableDisplayMode('block');if(this.collapseMode=='mini'){this.collapsedEl.addClass('x-layout-cmini-'+this.position);this.miniCollapsedEl=this.collapsedEl.createChild({cls:"x-layout-mini x-layout-mini-"+this.position,html:"&#160;"});this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');this.collapsedEl.addClassOnOver("x-layout-collapsed-over");this.collapsedEl.on('click',this.onExpandClick,this,{stopEvent:true});}else{if(this.collapsible!==false&&!this.hideCollapseTool){var t=this.expandToolEl=this.toolTemplate.append(this.collapsedEl.dom,{id:'expand-'+this.position},true);t.addClassOnOver('x-tool-expand-'+this.position+'-over');t.on('click',this.onExpandClick,this,{stopEvent:true});}
+if(this.floatable!==false||this.titleCollapse){this.collapsedEl.addClassOnOver("x-layout-collapsed-over");this.collapsedEl.on("click",this[this.floatable?'collapseClick':'onExpandClick'],this);}}}
+return this.collapsedEl;},onExpandClick:function(e){if(this.isSlid){this.panel.expand(false);}else{this.panel.expand();}},onCollapseClick:function(e){this.panel.collapse();},beforeCollapse:function(p,animate){this.lastAnim=animate;if(this.splitEl){this.splitEl.hide();}
+this.getCollapsedEl().show();var el=this.panel.getEl();this.originalZIndex=el.getStyle('z-index');el.setStyle('z-index',100);this.isCollapsed=true;this.layout.layout();},onCollapse:function(animate){this.panel.el.setStyle('z-index',1);if(this.lastAnim===false||this.panel.animCollapse===false){this.getCollapsedEl().dom.style.visibility='visible';}else{this.getCollapsedEl().slideIn(this.panel.slideAnchor,{duration:.2});}
+this.state.collapsed=true;this.panel.saveState();},beforeExpand:function(animate){if(this.isSlid){this.afterSlideIn();}
+var c=this.getCollapsedEl();this.el.show();if(this.position=='east'||this.position=='west'){this.panel.setSize(undefined,c.getHeight());}else{this.panel.setSize(c.getWidth(),undefined);}
+c.hide();c.dom.style.visibility='hidden';this.panel.el.setStyle('z-index',this.floatingZIndex);},onExpand:function(){this.isCollapsed=false;if(this.splitEl){this.splitEl.show();}
+this.layout.layout();this.panel.el.setStyle('z-index',this.originalZIndex);this.state.collapsed=false;this.panel.saveState();},collapseClick:function(e){if(this.isSlid){e.stopPropagation();this.slideIn();}else{e.stopPropagation();this.slideOut();}},onHide:function(){if(this.isCollapsed){this.getCollapsedEl().hide();}else if(this.splitEl){this.splitEl.hide();}},onShow:function(){if(this.isCollapsed){this.getCollapsedEl().show();}else if(this.splitEl){this.splitEl.show();}},isVisible:function(){return!this.panel.hidden;},getMargins:function(){return this.isCollapsed&&this.cmargins?this.cmargins:this.margins;},getSize:function(){return this.isCollapsed?this.getCollapsedEl().getSize():this.panel.getSize();},setPanel:function(panel){this.panel=panel;},getMinWidth:function(){return this.minWidth;},getMinHeight:function(){return this.minHeight;},applyLayoutCollapsed:function(box){var ce=this.getCollapsedEl();ce.setLeftTop(box.x,box.y);ce.setSize(box.width,box.height);},applyLayout:function(box){if(this.isCollapsed){this.applyLayoutCollapsed(box);}else{this.panel.setPosition(box.x,box.y);this.panel.setSize(box.width,box.height);}},beforeSlide:function(){this.panel.beforeEffect();},afterSlide:function(){this.panel.afterEffect();},initAutoHide:function(){if(this.autoHide!==false){if(!this.autoHideHd){this.autoHideSlideTask=new Ext.util.DelayedTask(this.slideIn,this);this.autoHideHd={"mouseout":function(e){if(!e.within(this.el,true)){this.autoHideSlideTask.delay(500);}},"mouseover":function(e){this.autoHideSlideTask.cancel();},scope:this};}
+this.el.on(this.autoHideHd);this.collapsedEl.on(this.autoHideHd);}},clearAutoHide:function(){if(this.autoHide!==false){this.el.un("mouseout",this.autoHideHd.mouseout);this.el.un("mouseover",this.autoHideHd.mouseover);this.collapsedEl.un("mouseout",this.autoHideHd.mouseout);this.collapsedEl.un("mouseover",this.autoHideHd.mouseover);}},clearMonitor:function(){Ext.getDoc().un("click",this.slideInIf,this);},slideOut:function(){if(this.isSlid||this.el.hasActiveFx()){return;}
+this.isSlid=true;var ts=this.panel.tools,dh,pc;if(ts&&ts.toggle){ts.toggle.hide();}
+this.el.show();pc=this.panel.collapsed;this.panel.collapsed=false;if(this.position=='east'||this.position=='west'){dh=this.panel.deferHeight;this.panel.deferHeight=false;this.panel.setSize(undefined,this.collapsedEl.getHeight());this.panel.deferHeight=dh;}else{this.panel.setSize(this.collapsedEl.getWidth(),undefined);}
+this.panel.collapsed=pc;this.restoreLT=[this.el.dom.style.left,this.el.dom.style.top];this.el.alignTo(this.collapsedEl,this.getCollapseAnchor());this.el.setStyle("z-index",this.floatingZIndex+2);this.panel.el.replaceClass('x-panel-collapsed','x-panel-floating');if(this.animFloat!==false){this.beforeSlide();this.el.slideIn(this.getSlideAnchor(),{callback:function(){this.afterSlide();this.initAutoHide();Ext.getDoc().on("click",this.slideInIf,this);},scope:this,block:true});}else{this.initAutoHide();Ext.getDoc().on("click",this.slideInIf,this);}},afterSlideIn:function(){this.clearAutoHide();this.isSlid=false;this.clearMonitor();this.el.setStyle("z-index","");this.panel.el.replaceClass('x-panel-floating','x-panel-collapsed');this.el.dom.style.left=this.restoreLT[0];this.el.dom.style.top=this.restoreLT[1];var ts=this.panel.tools;if(ts&&ts.toggle){ts.toggle.show();}},slideIn:function(cb){if(!this.isSlid||this.el.hasActiveFx()){Ext.callback(cb);return;}
+this.isSlid=false;if(this.animFloat!==false){this.beforeSlide();this.el.slideOut(this.getSlideAnchor(),{callback:function(){this.el.hide();this.afterSlide();this.afterSlideIn();Ext.callback(cb);},scope:this,block:true});}else{this.el.hide();this.afterSlideIn();}},slideInIf:function(e){if(!e.within(this.el)){this.slideIn();}},anchors:{"west":"left","east":"right","north":"top","south":"bottom"},sanchors:{"west":"l","east":"r","north":"t","south":"b"},canchors:{"west":"tl-tr","east":"tr-tl","north":"tl-bl","south":"bl-tl"},getAnchor:function(){return this.anchors[this.position];},getCollapseAnchor:function(){return this.canchors[this.position];},getSlideAnchor:function(){return this.sanchors[this.position];},getAlignAdj:function(){var cm=this.cmargins;switch(this.position){case"west":return[0,0];break;case"east":return[0,0];break;case"north":return[0,0];break;case"south":return[0,0];break;}},getExpandAdj:function(){var c=this.collapsedEl,cm=this.cmargins;switch(this.position){case"west":return[-(cm.right+c.getWidth()+cm.left),0];break;case"east":return[cm.right+c.getWidth()+cm.left,0];break;case"north":return[0,-(cm.top+cm.bottom+c.getHeight())];break;case"south":return[0,cm.top+cm.bottom+c.getHeight()];break;}},destroy:function(){if(this.autoHideSlideTask&&this.autoHideSlideTask.cancel){this.autoHideSlideTask.cancel();}
+Ext.destroyMembers(this,'miniCollapsedEl','collapsedEl','expandToolEl');}};Ext.layout.BorderLayout.SplitRegion=function(layout,config,pos){Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this,layout,config,pos);this.applyLayout=this.applyFns[pos];};Ext.extend(Ext.layout.BorderLayout.SplitRegion,Ext.layout.BorderLayout.Region,{splitTip:"Drag to resize.",collapsibleSplitTip:"Drag to resize. Double click to hide.",useSplitTips:false,splitSettings:{north:{orientation:Ext.SplitBar.VERTICAL,placement:Ext.SplitBar.TOP,maxFn:'getVMaxSize',minProp:'minHeight',maxProp:'maxHeight'},south:{orientation:Ext.SplitBar.VERTICAL,placement:Ext.SplitBar.BOTTOM,maxFn:'getVMaxSize',minProp:'minHeight',maxProp:'maxHeight'},east:{orientation:Ext.SplitBar.HORIZONTAL,placement:Ext.SplitBar.RIGHT,maxFn:'getHMaxSize',minProp:'minWidth',maxProp:'maxWidth'},west:{orientation:Ext.SplitBar.HORIZONTAL,placement:Ext.SplitBar.LEFT,maxFn:'getHMaxSize',minProp:'minWidth',maxProp:'maxWidth'}},applyFns:{west:function(box){if(this.isCollapsed){return this.applyLayoutCollapsed(box);}
+var sd=this.splitEl.dom,s=sd.style;this.panel.setPosition(box.x,box.y);var sw=sd.offsetWidth;s.left=(box.x+box.width-sw)+'px';s.top=(box.y)+'px';s.height=Math.max(0,box.height)+'px';this.panel.setSize(box.width-sw,box.height);},east:function(box){if(this.isCollapsed){return this.applyLayoutCollapsed(box);}
+var sd=this.splitEl.dom,s=sd.style;var sw=sd.offsetWidth;this.panel.setPosition(box.x+sw,box.y);s.left=(box.x)+'px';s.top=(box.y)+'px';s.height=Math.max(0,box.height)+'px';this.panel.setSize(box.width-sw,box.height);},north:function(box){if(this.isCollapsed){return this.applyLayoutCollapsed(box);}
+var sd=this.splitEl.dom,s=sd.style;var sh=sd.offsetHeight;this.panel.setPosition(box.x,box.y);s.left=(box.x)+'px';s.top=(box.y+box.height-sh)+'px';s.width=Math.max(0,box.width)+'px';this.panel.setSize(box.width,box.height-sh);},south:function(box){if(this.isCollapsed){return this.applyLayoutCollapsed(box);}
+var sd=this.splitEl.dom,s=sd.style;var sh=sd.offsetHeight;this.panel.setPosition(box.x,box.y+sh);s.left=(box.x)+'px';s.top=(box.y)+'px';s.width=Math.max(0,box.width)+'px';this.panel.setSize(box.width,box.height-sh);}},render:function(ct,p){Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this,ct,p);var ps=this.position;this.splitEl=ct.createChild({cls:"x-layout-split x-layout-split-"+ps,html:"&#160;",id:this.panel.id+'-xsplit'});if(this.collapseMode=='mini'){this.miniSplitEl=this.splitEl.createChild({cls:"x-layout-mini x-layout-mini-"+ps,html:"&#160;"});this.miniSplitEl.addClassOnOver('x-layout-mini-over');this.miniSplitEl.on('click',this.onCollapseClick,this,{stopEvent:true});}
+var s=this.splitSettings[ps];this.split=new Ext.SplitBar(this.splitEl.dom,p.el,s.orientation);this.split.tickSize=this.tickSize;this.split.placement=s.placement;this.split.getMaximumSize=this[s.maxFn].createDelegate(this);this.split.minSize=this.minSize||this[s.minProp];this.split.on("beforeapply",this.onSplitMove,this);this.split.useShim=this.useShim===true;this.maxSize=this.maxSize||this[s.maxProp];if(p.hidden){this.splitEl.hide();}
+if(this.useSplitTips){this.splitEl.dom.title=this.collapsible?this.collapsibleSplitTip:this.splitTip;}
+if(this.collapsible){this.splitEl.on("dblclick",this.onCollapseClick,this);}},getSize:function(){if(this.isCollapsed){return this.collapsedEl.getSize();}
+var s=this.panel.getSize();if(this.position=='north'||this.position=='south'){s.height+=this.splitEl.dom.offsetHeight;}else{s.width+=this.splitEl.dom.offsetWidth;}
+return s;},getHMaxSize:function(){var cmax=this.maxSize||10000;var center=this.layout.center;return Math.min(cmax,(this.el.getWidth()+center.el.getWidth())-center.getMinWidth());},getVMaxSize:function(){var cmax=this.maxSize||10000;var center=this.layout.center;return Math.min(cmax,(this.el.getHeight()+center.el.getHeight())-center.getMinHeight());},onSplitMove:function(split,newSize){var s=this.panel.getSize();this.lastSplitSize=newSize;if(this.position=='north'||this.position=='south'){this.panel.setSize(s.width,newSize);this.state.height=newSize;}else{this.panel.setSize(newSize,s.height);this.state.width=newSize;}
+this.layout.layout();this.panel.saveState();return false;},getSplitBar:function(){return this.split;},destroy:function(){Ext.destroy(this.miniSplitEl,this.split,this.splitEl);Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);}});Ext.Container.LAYOUTS['border']=Ext.layout.BorderLayout;Ext.layout.FormLayout=Ext.extend(Ext.layout.AnchorLayout,{labelSeparator:':',trackLabels:true,type:'form',onRemove:function(c){Ext.layout.FormLayout.superclass.onRemove.call(this,c);if(this.trackLabels){c.un('show',this.onFieldShow,this);c.un('hide',this.onFieldHide,this);}
+var el=c.getPositionEl(),ct=c.getItemCt&&c.getItemCt();if(c.rendered&&ct){if(el&&el.dom){el.insertAfter(ct);}
+Ext.destroy(ct);Ext.destroyMembers(c,'label','itemCt');if(c.customItemCt){Ext.destroyMembers(c,'getItemCt','customItemCt');}}},setContainer:function(ct){Ext.layout.FormLayout.superclass.setContainer.call(this,ct);if(ct.labelAlign){ct.addClass('x-form-label-'+ct.labelAlign);}
+if(ct.hideLabels){Ext.apply(this,{labelStyle:'display:none',elementStyle:'padding-left:0;',labelAdjust:0});}else{this.labelSeparator=Ext.isDefined(ct.labelSeparator)?ct.labelSeparator:this.labelSeparator;ct.labelWidth=ct.labelWidth||100;if(Ext.isNumber(ct.labelWidth)){var pad=Ext.isNumber(ct.labelPad)?ct.labelPad:5;Ext.apply(this,{labelAdjust:ct.labelWidth+pad,labelStyle:'width:'+ct.labelWidth+'px;',elementStyle:'padding-left:'+(ct.labelWidth+pad)+'px'});}
+if(ct.labelAlign=='top'){Ext.apply(this,{labelStyle:'width:auto;',labelAdjust:0,elementStyle:'padding-left:0;'});}}},isHide:function(c){return c.hideLabel||this.container.hideLabels;},onFieldShow:function(c){c.getItemCt().removeClass('x-hide-'+c.hideMode);if(c.isComposite){c.doLayout();}},onFieldHide:function(c){c.getItemCt().addClass('x-hide-'+c.hideMode);},getLabelStyle:function(s){var ls='',items=[this.labelStyle,s];for(var i=0,len=items.length;i<len;++i){if(items[i]){ls+=items[i];if(ls.substr(-1,1)!=';'){ls+=';';}}}
+return ls;},renderItem:function(c,position,target){if(c&&(c.isFormField||c.fieldLabel)&&c.inputType!='hidden'){var args=this.getTemplateArgs(c);if(Ext.isNumber(position)){position=target.dom.childNodes[position]||null;}
+if(position){c.itemCt=this.fieldTpl.insertBefore(position,args,true);}else{c.itemCt=this.fieldTpl.append(target,args,true);}
+if(!c.getItemCt){Ext.apply(c,{getItemCt:function(){return c.itemCt;},customItemCt:true});}
+c.label=c.getItemCt().child('label.x-form-item-label');if(!c.rendered){c.render('x-form-el-'+c.id);}else if(!this.isValidParent(c,target)){Ext.fly('x-form-el-'+c.id).appendChild(c.getPositionEl());}
+if(this.trackLabels){if(c.hidden){this.onFieldHide(c);}
+c.on({scope:this,show:this.onFieldShow,hide:this.onFieldHide});}
+this.configureItem(c);}else{Ext.layout.FormLayout.superclass.renderItem.apply(this,arguments);}},getTemplateArgs:function(field){var noLabelSep=!field.fieldLabel||field.hideLabel;return{id:field.id,label:field.fieldLabel,itemCls:(field.itemCls||this.container.itemCls||'')+(field.hideLabel?' x-hide-label':''),clearCls:field.clearCls||'x-form-clear-left',labelStyle:this.getLabelStyle(field.labelStyle),elementStyle:this.elementStyle||'',labelSeparator:noLabelSep?'':(Ext.isDefined(field.labelSeparator)?field.labelSeparator:this.labelSeparator)};},adjustWidthAnchor:function(value,c){if(c.label&&!this.isHide(c)&&(this.container.labelAlign!='top')){var adjust=Ext.isIE6||(Ext.isIE&&!Ext.isStrict);return value-this.labelAdjust+(adjust?-3:0);}
+return value;},adjustHeightAnchor:function(value,c){if(c.label&&!this.isHide(c)&&(this.container.labelAlign=='top')){return value-c.label.getHeight();}
+return value;},isValidParent:function(c,target){return target&&this.container.getEl().contains(c.getPositionEl());}});Ext.Container.LAYOUTS['form']=Ext.layout.FormLayout;Ext.layout.AccordionLayout=Ext.extend(Ext.layout.FitLayout,{fill:true,autoWidth:true,titleCollapse:true,hideCollapseTool:false,collapseFirst:false,animate:false,sequence:false,activeOnTop:false,type:'accordion',renderItem:function(c){if(this.animate===false){c.animCollapse=false;}
+c.collapsible=true;if(this.autoWidth){c.autoWidth=true;}
+if(this.titleCollapse){c.titleCollapse=true;}
+if(this.hideCollapseTool){c.hideCollapseTool=true;}
+if(this.collapseFirst!==undefined){c.collapseFirst=this.collapseFirst;}
+if(!this.activeItem&&!c.collapsed){this.setActiveItem(c,true);}else if(this.activeItem&&this.activeItem!=c){c.collapsed=true;}
+Ext.layout.AccordionLayout.superclass.renderItem.apply(this,arguments);c.header.addClass('x-accordion-hd');c.on('beforeexpand',this.beforeExpand,this);},onRemove:function(c){Ext.layout.AccordionLayout.superclass.onRemove.call(this,c);if(c.rendered){c.header.removeClass('x-accordion-hd');}
+c.un('beforeexpand',this.beforeExpand,this);},beforeExpand:function(p,anim){var ai=this.activeItem;if(ai){if(this.sequence){delete this.activeItem;if(!ai.collapsed){ai.collapse({callback:function(){p.expand(anim||true);},scope:this});return false;}}else{ai.collapse(this.animate);}}
+this.setActive(p);if(this.activeOnTop){p.el.dom.parentNode.insertBefore(p.el.dom,p.el.dom.parentNode.firstChild);}
+this.layout();},setItemSize:function(item,size){if(this.fill&&item){var hh=0,i,ct=this.getRenderedItems(this.container),len=ct.length,p;for(i=0;i<len;i++){if((p=ct[i])!=item&&!p.hidden){hh+=p.header.getHeight();}};size.height-=hh;item.setSize(size);}},setActiveItem:function(item){this.setActive(item,true);},setActive:function(item,expand){var ai=this.activeItem;item=this.container.getComponent(item);if(ai!=item){if(item.rendered&&item.collapsed&&expand){item.expand();}else{if(ai){ai.fireEvent('deactivate',ai);}
+this.activeItem=item;item.fireEvent('activate',item);}}}});Ext.Container.LAYOUTS.accordion=Ext.layout.AccordionLayout;Ext.layout.Accordion=Ext.layout.AccordionLayout;Ext.layout.TableLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:false,type:'table',targetCls:'x-table-layout-ct',tableAttrs:null,setContainer:function(ct){Ext.layout.TableLayout.superclass.setContainer.call(this,ct);this.currentRow=0;this.currentColumn=0;this.cells=[];},onLayout:function(ct,target){var cs=ct.items.items,len=cs.length,c,i;if(!this.table){target.addClass('x-table-layout-ct');this.table=target.createChild(Ext.apply({tag:'table',cls:'x-table-layout',cellspacing:0,cn:{tag:'tbody'}},this.tableAttrs),null,true);}
+this.renderAll(ct,target);},getRow:function(index){var row=this.table.tBodies[0].childNodes[index];if(!row){row=document.createElement('tr');this.table.tBodies[0].appendChild(row);}
+return row;},getNextCell:function(c){var cell=this.getNextNonSpan(this.currentColumn,this.currentRow);var curCol=this.currentColumn=cell[0],curRow=this.currentRow=cell[1];for(var rowIndex=curRow;rowIndex<curRow+(c.rowspan||1);rowIndex++){if(!this.cells[rowIndex]){this.cells[rowIndex]=[];}
+for(var colIndex=curCol;colIndex<curCol+(c.colspan||1);colIndex++){this.cells[rowIndex][colIndex]=true;}}
+var td=document.createElement('td');if(c.cellId){td.id=c.cellId;}
+var cls='x-table-layout-cell';if(c.cellCls){cls+=' '+c.cellCls;}
+td.className=cls;if(c.colspan){td.colSpan=c.colspan;}
+if(c.rowspan){td.rowSpan=c.rowspan;}
+this.getRow(curRow).appendChild(td);return td;},getNextNonSpan:function(colIndex,rowIndex){var cols=this.columns;while((cols&&colIndex>=cols)||(this.cells[rowIndex]&&this.cells[rowIndex][colIndex])){if(cols&&colIndex>=cols){rowIndex++;colIndex=0;}else{colIndex++;}}
+return[colIndex,rowIndex];},renderItem:function(c,position,target){if(!this.table){this.table=target.createChild(Ext.apply({tag:'table',cls:'x-table-layout',cellspacing:0,cn:{tag:'tbody'}},this.tableAttrs),null,true);}
+if(c&&!c.rendered){c.render(this.getNextCell(c));this.configureItem(c);}else if(c&&!this.isValidParent(c,target)){var container=this.getNextCell(c);container.insertBefore(c.getPositionEl().dom,null);c.container=Ext.get(container);this.configureItem(c);}},isValidParent:function(c,target){return c.getPositionEl().up('table',5).dom.parentNode===(target.dom||target);},destroy:function(){delete this.table;Ext.layout.TableLayout.superclass.destroy.call(this);}});Ext.Container.LAYOUTS['table']=Ext.layout.TableLayout;Ext.layout.AbsoluteLayout=Ext.extend(Ext.layout.AnchorLayout,{extraCls:'x-abs-layout-item',type:'absolute',onLayout:function(ct,target){target.position();this.paddingLeft=target.getPadding('l');this.paddingTop=target.getPadding('t');Ext.layout.AbsoluteLayout.superclass.onLayout.call(this,ct,target);},adjustWidthAnchor:function(value,comp){return value?value-comp.getPosition(true)[0]+this.paddingLeft:value;},adjustHeightAnchor:function(value,comp){return value?value-comp.getPosition(true)[1]+this.paddingTop:value;}});Ext.Container.LAYOUTS['absolute']=Ext.layout.AbsoluteLayout;Ext.layout.BoxLayout=Ext.extend(Ext.layout.ContainerLayout,{defaultMargins:{left:0,top:0,right:0,bottom:0},padding:'0',pack:'start',monitorResize:true,type:'box',scrollOffset:0,extraCls:'x-box-item',targetCls:'x-box-layout-ct',innerCls:'x-box-inner',constructor:function(config){Ext.layout.BoxLayout.superclass.constructor.call(this,config);if(Ext.isString(this.defaultMargins)){this.defaultMargins=this.parseMargins(this.defaultMargins);}
+var handler=this.overflowHandler;if(typeof handler=='string'){handler={type:handler};}
+var handlerType='none';if(handler&&handler.type!=undefined){handlerType=handler.type;}
+var constructor=Ext.layout.boxOverflow[handlerType];if(constructor[this.type]){constructor=constructor[this.type];}
+this.overflowHandler=new constructor(this,handler);},onLayout:function(container,target){Ext.layout.BoxLayout.superclass.onLayout.call(this,container,target);var tSize=this.getLayoutTargetSize(),items=this.getVisibleItems(container),calcs=this.calculateChildBoxes(items,tSize),boxes=calcs.boxes,meta=calcs.meta;if(tSize.width>0){var handler=this.overflowHandler,method=meta.tooNarrow?'handleOverflow':'clearOverflow';var results=handler[method](calcs,tSize);if(results){if(results.targetSize){tSize=results.targetSize;}
+if(results.recalculate){items=this.getVisibleItems(container);calcs=this.calculateChildBoxes(items,tSize);boxes=calcs.boxes;}}}
+this.layoutTargetLastSize=tSize;this.childBoxCache=calcs;this.updateInnerCtSize(tSize,calcs);this.updateChildBoxes(boxes);this.handleTargetOverflow(tSize,container,target);},updateChildBoxes:function(boxes){for(var i=0,length=boxes.length;i<length;i++){var box=boxes[i],comp=box.component;if(box.dirtySize){comp.setSize(box.width,box.height);}
+if(isNaN(box.left)||isNaN(box.top)){continue;}
+comp.setPosition(box.left,box.top);}},updateInnerCtSize:function(tSize,calcs){var align=this.align,padding=this.padding,width=tSize.width,height=tSize.height;if(this.type=='hbox'){var innerCtWidth=width,innerCtHeight=calcs.meta.maxHeight+padding.top+padding.bottom;if(align=='stretch'){innerCtHeight=height;}else if(align=='middle'){innerCtHeight=Math.max(height,innerCtHeight);}}else{var innerCtHeight=height,innerCtWidth=calcs.meta.maxWidth+padding.left+padding.right;if(align=='stretch'){innerCtWidth=width;}else if(align=='center'){innerCtWidth=Math.max(width,innerCtWidth);}}
+this.innerCt.setSize(innerCtWidth||undefined,innerCtHeight||undefined);},handleTargetOverflow:function(previousTargetSize,container,target){var overflow=target.getStyle('overflow');if(overflow&&overflow!='hidden'&&!this.adjustmentPass){var newTargetSize=this.getLayoutTargetSize();if(newTargetSize.width!=previousTargetSize.width||newTargetSize.height!=previousTargetSize.height){this.adjustmentPass=true;this.onLayout(container,target);}}
+delete this.adjustmentPass;},isValidParent:function(c,target){return this.innerCt&&c.getPositionEl().dom.parentNode==this.innerCt.dom;},getVisibleItems:function(ct){var ct=ct||this.container,t=ct.getLayoutTarget(),cti=ct.items.items,len=cti.length,i,c,items=[];for(i=0;i<len;i++){if((c=cti[i]).rendered&&this.isValidParent(c,t)&&c.hidden!==true&&c.collapsed!==true&&c.shouldLayout!==false){items.push(c);}}
+return items;},renderAll:function(ct,target){if(!this.innerCt){this.innerCt=target.createChild({cls:this.innerCls});this.padding=this.parseMargins(this.padding);}
+Ext.layout.BoxLayout.superclass.renderAll.call(this,ct,this.innerCt);},getLayoutTargetSize:function(){var target=this.container.getLayoutTarget(),ret;if(target){ret=target.getViewSize();if(Ext.isIE&&Ext.isStrict&&ret.width==0){ret=target.getStyleSize();}
+ret.width-=target.getPadding('lr');ret.height-=target.getPadding('tb');}
+return ret;},renderItem:function(c){if(Ext.isString(c.margins)){c.margins=this.parseMargins(c.margins);}else if(!c.margins){c.margins=this.defaultMargins;}
+Ext.layout.BoxLayout.superclass.renderItem.apply(this,arguments);},destroy:function(){Ext.destroy(this.overflowHandler);Ext.layout.BoxLayout.superclass.destroy.apply(this,arguments);}});Ext.ns('Ext.layout.boxOverflow');Ext.layout.boxOverflow.None=Ext.extend(Object,{constructor:function(layout,config){this.layout=layout;Ext.apply(this,config||{});},handleOverflow:Ext.emptyFn,clearOverflow:Ext.emptyFn});Ext.layout.boxOverflow.none=Ext.layout.boxOverflow.None;Ext.layout.boxOverflow.Menu=Ext.extend(Ext.layout.boxOverflow.None,{afterCls:'x-strip-right',noItemsMenuText:'<div class="x-toolbar-no-items">(None)</div>',constructor:function(layout){Ext.layout.boxOverflow.Menu.superclass.constructor.apply(this,arguments);this.menuItems=[];},createInnerElements:function(){if(!this.afterCt){this.afterCt=this.layout.innerCt.insertSibling({cls:this.afterCls},'before');}},clearOverflow:function(calculations,targetSize){var newWidth=targetSize.width+(this.afterCt?this.afterCt.getWidth():0),items=this.menuItems;this.hideTrigger();for(var index=0,length=items.length;index<length;index++){items.pop().component.show();}
+return{targetSize:{height:targetSize.height,width:newWidth}};},showTrigger:function(){this.createMenu();this.menuTrigger.show();},hideTrigger:function(){if(this.menuTrigger!=undefined){this.menuTrigger.hide();}},beforeMenuShow:function(menu){var items=this.menuItems,len=items.length,item,prev;var needsSep=function(group,item){return group.isXType('buttongroup')&&!(item instanceof Ext.Toolbar.Separator);};this.clearMenu();menu.removeAll();for(var i=0;i<len;i++){item=items[i].component;if(prev&&(needsSep(item,prev)||needsSep(prev,item))){menu.add('-');}
+this.addComponentToMenu(menu,item);prev=item;}
+if(menu.items.length<1){menu.add(this.noItemsMenuText);}},createMenuConfig:function(component,hideOnClick){var config=Ext.apply({},component.initialConfig),group=component.toggleGroup;Ext.copyTo(config,component,['iconCls','icon','itemId','disabled','handler','scope','menu']);Ext.apply(config,{text:component.overflowText||component.text,hideOnClick:hideOnClick});if(group||component.enableToggle){Ext.apply(config,{group:group,checked:component.pressed,listeners:{checkchange:function(item,checked){component.toggle(checked);}}});}
+delete config.ownerCt;delete config.xtype;delete config.id;return config;},addComponentToMenu:function(menu,component){if(component instanceof Ext.Toolbar.Separator){menu.add('-');}else if(Ext.isFunction(component.isXType)){if(component.isXType('splitbutton')){menu.add(this.createMenuConfig(component,true));}else if(component.isXType('button')){menu.add(this.createMenuConfig(component,!component.menu));}else if(component.isXType('buttongroup')){component.items.each(function(item){this.addComponentToMenu(menu,item);},this);}}},clearMenu:function(){var menu=this.moreMenu;if(menu&&menu.items){menu.items.each(function(item){delete item.menu;});}},createMenu:function(){if(!this.menuTrigger){this.createInnerElements();this.menu=new Ext.menu.Menu({ownerCt:this.layout.container,listeners:{scope:this,beforeshow:this.beforeMenuShow}});this.menuTrigger=new Ext.Button({iconCls:'x-toolbar-more-icon',cls:'x-toolbar-more',menu:this.menu,renderTo:this.afterCt});}},destroy:function(){Ext.destroy(this.menu,this.menuTrigger);}});Ext.layout.boxOverflow.menu=Ext.layout.boxOverflow.Menu;Ext.layout.boxOverflow.HorizontalMenu=Ext.extend(Ext.layout.boxOverflow.Menu,{constructor:function(){Ext.layout.boxOverflow.HorizontalMenu.superclass.constructor.apply(this,arguments);var me=this,layout=me.layout,origFunction=layout.calculateChildBoxes;layout.calculateChildBoxes=function(visibleItems,targetSize){var calcs=origFunction.apply(layout,arguments),meta=calcs.meta,items=me.menuItems;var hiddenWidth=0;for(var index=0,length=items.length;index<length;index++){hiddenWidth+=items[index].width;}
+meta.minimumWidth+=hiddenWidth;meta.tooNarrow=meta.minimumWidth>targetSize.width;return calcs;};},handleOverflow:function(calculations,targetSize){this.showTrigger();var newWidth=targetSize.width-this.afterCt.getWidth(),boxes=calculations.boxes,usedWidth=0,recalculate=false;for(var index=0,length=boxes.length;index<length;index++){usedWidth+=boxes[index].width;}
+var spareWidth=newWidth-usedWidth,showCount=0;for(var index=0,length=this.menuItems.length;index<length;index++){var hidden=this.menuItems[index],comp=hidden.component,width=hidden.width;if(width<spareWidth){comp.show();spareWidth-=width;showCount++;recalculate=true;}else{break;}}
+if(recalculate){this.menuItems=this.menuItems.slice(showCount);}else{for(var i=boxes.length-1;i>=0;i--){var item=boxes[i].component,right=boxes[i].left+boxes[i].width;if(right>=newWidth){this.menuItems.unshift({component:item,width:boxes[i].width});item.hide();}else{break;}}}
+if(this.menuItems.length==0){this.hideTrigger();}
+return{targetSize:{height:targetSize.height,width:newWidth},recalculate:recalculate};}});Ext.layout.boxOverflow.menu.hbox=Ext.layout.boxOverflow.HorizontalMenu;Ext.layout.boxOverflow.Scroller=Ext.extend(Ext.layout.boxOverflow.None,{animateScroll:true,scrollIncrement:100,wheelIncrement:3,scrollRepeatInterval:400,scrollDuration:0.4,beforeCls:'x-strip-left',afterCls:'x-strip-right',scrollerCls:'x-strip-scroller',beforeScrollerCls:'x-strip-scroller-left',afterScrollerCls:'x-strip-scroller-right',createWheelListener:function(){this.layout.innerCt.on({scope:this,mousewheel:function(e){e.stopEvent();this.scrollBy(e.getWheelDelta()*this.wheelIncrement*-1,false);}});},handleOverflow:function(calculations,targetSize){this.createInnerElements();this.showScrollers();},clearOverflow:function(){this.hideScrollers();},showScrollers:function(){this.createScrollers();this.beforeScroller.show();this.afterScroller.show();this.updateScrollButtons();},hideScrollers:function(){if(this.beforeScroller!=undefined){this.beforeScroller.hide();this.afterScroller.hide();}},createScrollers:function(){if(!this.beforeScroller&&!this.afterScroller){var before=this.beforeCt.createChild({cls:String.format("{0} {1} ",this.scrollerCls,this.beforeScrollerCls)});var after=this.afterCt.createChild({cls:String.format("{0} {1}",this.scrollerCls,this.afterScrollerCls)});before.addClassOnOver(this.beforeScrollerCls+'-hover');after.addClassOnOver(this.afterScrollerCls+'-hover');before.setVisibilityMode(Ext.Element.DISPLAY);after.setVisibilityMode(Ext.Element.DISPLAY);this.beforeRepeater=new Ext.util.ClickRepeater(before,{interval:this.scrollRepeatInterval,handler:this.scrollLeft,scope:this});this.afterRepeater=new Ext.util.ClickRepeater(after,{interval:this.scrollRepeatInterval,handler:this.scrollRight,scope:this});this.beforeScroller=before;this.afterScroller=after;}},destroy:function(){Ext.destroy(this.beforeScroller,this.afterScroller,this.beforeRepeater,this.afterRepeater,this.beforeCt,this.afterCt);},scrollBy:function(delta,animate){this.scrollTo(this.getScrollPosition()+delta,animate);},getItem:function(item){if(Ext.isString(item)){item=Ext.getCmp(item);}else if(Ext.isNumber(item)){item=this.items[item];}
+return item;},getScrollAnim:function(){return{duration:this.scrollDuration,callback:this.updateScrollButtons,scope:this};},updateScrollButtons:function(){if(this.beforeScroller==undefined||this.afterScroller==undefined){return;}
+var beforeMeth=this.atExtremeBefore()?'addClass':'removeClass',afterMeth=this.atExtremeAfter()?'addClass':'removeClass',beforeCls=this.beforeScrollerCls+'-disabled',afterCls=this.afterScrollerCls+'-disabled';this.beforeScroller[beforeMeth](beforeCls);this.afterScroller[afterMeth](afterCls);this.scrolling=false;},atExtremeBefore:function(){return this.getScrollPosition()===0;},scrollLeft:function(animate){this.scrollBy(-this.scrollIncrement,animate);},scrollRight:function(animate){this.scrollBy(this.scrollIncrement,animate);},scrollToItem:function(item,animate){item=this.getItem(item);if(item!=undefined){var visibility=this.getItemVisibility(item);if(!visibility.fullyVisible){var box=item.getBox(true,true),newX=box.x;if(visibility.hiddenRight){newX-=(this.layout.innerCt.getWidth()-box.width);}
+this.scrollTo(newX,animate);}}},getItemVisibility:function(item){var box=this.getItem(item).getBox(true,true),itemLeft=box.x,itemRight=box.x+box.width,scrollLeft=this.getScrollPosition(),scrollRight=this.layout.innerCt.getWidth()+scrollLeft;return{hiddenLeft:itemLeft<scrollLeft,hiddenRight:itemRight>scrollRight,fullyVisible:itemLeft>scrollLeft&&itemRight<scrollRight};}});Ext.layout.boxOverflow.scroller=Ext.layout.boxOverflow.Scroller;Ext.layout.boxOverflow.VerticalScroller=Ext.extend(Ext.layout.boxOverflow.Scroller,{scrollIncrement:75,wheelIncrement:2,handleOverflow:function(calculations,targetSize){Ext.layout.boxOverflow.VerticalScroller.superclass.handleOverflow.apply(this,arguments);return{targetSize:{height:targetSize.height-(this.beforeCt.getHeight()+this.afterCt.getHeight()),width:targetSize.width}};},createInnerElements:function(){var target=this.layout.innerCt;if(!this.beforeCt){this.beforeCt=target.insertSibling({cls:this.beforeCls},'before');this.afterCt=target.insertSibling({cls:this.afterCls},'after');this.createWheelListener();}},scrollTo:function(position,animate){var oldPosition=this.getScrollPosition(),newPosition=position.constrain(0,this.getMaxScrollBottom());if(newPosition!=oldPosition&&!this.scrolling){if(animate==undefined){animate=this.animateScroll;}
+this.layout.innerCt.scrollTo('top',newPosition,animate?this.getScrollAnim():false);if(animate){this.scrolling=true;}else{this.scrolling=false;this.updateScrollButtons();}}},getScrollPosition:function(){return parseInt(this.layout.innerCt.dom.scrollTop,10)||0;},getMaxScrollBottom:function(){return this.layout.innerCt.dom.scrollHeight-this.layout.innerCt.getHeight();},atExtremeAfter:function(){return this.getScrollPosition()>=this.getMaxScrollBottom();}});Ext.layout.boxOverflow.scroller.vbox=Ext.layout.boxOverflow.VerticalScroller;Ext.layout.boxOverflow.HorizontalScroller=Ext.extend(Ext.layout.boxOverflow.Scroller,{handleOverflow:function(calculations,targetSize){Ext.layout.boxOverflow.HorizontalScroller.superclass.handleOverflow.apply(this,arguments);return{targetSize:{height:targetSize.height,width:targetSize.width-(this.beforeCt.getWidth()+this.afterCt.getWidth())}};},createInnerElements:function(){var target=this.layout.innerCt;if(!this.beforeCt){this.afterCt=target.insertSibling({cls:this.afterCls},'before');this.beforeCt=target.insertSibling({cls:this.beforeCls},'before');this.createWheelListener();}},scrollTo:function(position,animate){var oldPosition=this.getScrollPosition(),newPosition=position.constrain(0,this.getMaxScrollRight());if(newPosition!=oldPosition&&!this.scrolling){if(animate==undefined){animate=this.animateScroll;}
+this.layout.innerCt.scrollTo('left',newPosition,animate?this.getScrollAnim():false);if(animate){this.scrolling=true;}else{this.scrolling=false;this.updateScrollButtons();}}},getScrollPosition:function(){return parseInt(this.layout.innerCt.dom.scrollLeft,10)||0;},getMaxScrollRight:function(){return this.layout.innerCt.dom.scrollWidth-this.layout.innerCt.getWidth();},atExtremeAfter:function(){return this.getScrollPosition()>=this.getMaxScrollRight();}});Ext.layout.boxOverflow.scroller.hbox=Ext.layout.boxOverflow.HorizontalScroller;Ext.layout.HBoxLayout=Ext.extend(Ext.layout.BoxLayout,{align:'top',type:'hbox',calculateChildBoxes:function(visibleItems,targetSize){var visibleCount=visibleItems.length,padding=this.padding,topOffset=padding.top,leftOffset=padding.left,paddingVert=topOffset+padding.bottom,paddingHoriz=leftOffset+padding.right,width=targetSize.width-this.scrollOffset,height=targetSize.height,availHeight=Math.max(0,height-paddingVert),isStart=this.pack=='start',isCenter=this.pack=='center',isEnd=this.pack=='end',nonFlexWidth=0,maxHeight=0,totalFlex=0,desiredWidth=0,minimumWidth=0,boxes=[],child,childWidth,childHeight,childSize,childMargins,canLayout,i,calcs,flexedWidth,horizMargins,vertMargins,stretchHeight;for(i=0;i<visibleCount;i++){child=visibleItems[i];childHeight=child.height;childWidth=child.width;canLayout=!child.hasLayout&&typeof child.doLayout=='function';if(typeof childWidth!='number'){if(child.flex&&!childWidth){totalFlex+=child.flex;}else{if(!childWidth&&canLayout){child.doLayout();}
+childSize=child.getSize();childWidth=childSize.width;childHeight=childSize.height;}}
+childMargins=child.margins;horizMargins=childMargins.left+childMargins.right;nonFlexWidth+=horizMargins+(childWidth||0);desiredWidth+=horizMargins+(child.flex?child.minWidth||0:childWidth);minimumWidth+=horizMargins+(child.minWidth||childWidth||0);if(typeof childHeight!='number'){if(canLayout){child.doLayout();}
+childHeight=child.getHeight();}
+maxHeight=Math.max(maxHeight,childHeight+childMargins.top+childMargins.bottom);boxes.push({component:child,height:childHeight||undefined,width:childWidth||undefined});}
+var shortfall=desiredWidth-width,tooNarrow=minimumWidth>width;var availableWidth=Math.max(0,width-nonFlexWidth-paddingHoriz);if(tooNarrow){for(i=0;i<visibleCount;i++){boxes[i].width=visibleItems[i].minWidth||visibleItems[i].width||boxes[i].width;}}else{if(shortfall>0){var minWidths=[];for(var index=0,length=visibleCount;index<length;index++){var item=visibleItems[index],minWidth=item.minWidth||0;if(item.flex){boxes[index].width=minWidth;}else{minWidths.push({minWidth:minWidth,available:boxes[index].width-minWidth,index:index});}}
+minWidths.sort(function(a,b){return a.available>b.available?1:-1;});for(var i=0,length=minWidths.length;i<length;i++){var itemIndex=minWidths[i].index;if(itemIndex==undefined){continue;}
+var item=visibleItems[itemIndex],box=boxes[itemIndex],oldWidth=box.width,minWidth=item.minWidth,newWidth=Math.max(minWidth,oldWidth-Math.ceil(shortfall/(length-i))),reduction=oldWidth-newWidth;boxes[itemIndex].width=newWidth;shortfall-=reduction;}}else{var remainingWidth=availableWidth,remainingFlex=totalFlex;for(i=0;i<visibleCount;i++){child=visibleItems[i];calcs=boxes[i];childMargins=child.margins;vertMargins=childMargins.top+childMargins.bottom;if(isStart&&child.flex&&!child.width){flexedWidth=Math.ceil((child.flex/remainingFlex)*remainingWidth);remainingWidth-=flexedWidth;remainingFlex-=child.flex;calcs.width=flexedWidth;calcs.dirtySize=true;}}}}
+if(isCenter){leftOffset+=availableWidth/2;}else if(isEnd){leftOffset+=availableWidth;}
+for(i=0;i<visibleCount;i++){child=visibleItems[i];calcs=boxes[i];childMargins=child.margins;leftOffset+=childMargins.left;vertMargins=childMargins.top+childMargins.bottom;calcs.left=leftOffset;calcs.top=topOffset+childMargins.top;switch(this.align){case'stretch':stretchHeight=availHeight-vertMargins;calcs.height=stretchHeight.constrain(child.minHeight||0,child.maxHeight||1000000);calcs.dirtySize=true;break;case'stretchmax':stretchHeight=maxHeight-vertMargins;calcs.height=stretchHeight.constrain(child.minHeight||0,child.maxHeight||1000000);calcs.dirtySize=true;break;case'middle':var diff=availHeight-calcs.height-vertMargins;if(diff>0){calcs.top=topOffset+vertMargins+(diff/2);}}
+leftOffset+=calcs.width+childMargins.right;}
+return{boxes:boxes,meta:{maxHeight:maxHeight,nonFlexWidth:nonFlexWidth,desiredWidth:desiredWidth,minimumWidth:minimumWidth,shortfall:desiredWidth-width,tooNarrow:tooNarrow}};}});Ext.Container.LAYOUTS.hbox=Ext.layout.HBoxLayout;Ext.layout.VBoxLayout=Ext.extend(Ext.layout.BoxLayout,{align:'left',type:'vbox',calculateChildBoxes:function(visibleItems,targetSize){var visibleCount=visibleItems.length,padding=this.padding,topOffset=padding.top,leftOffset=padding.left,paddingVert=topOffset+padding.bottom,paddingHoriz=leftOffset+padding.right,width=targetSize.width-this.scrollOffset,height=targetSize.height,availWidth=Math.max(0,width-paddingHoriz),isStart=this.pack=='start',isCenter=this.pack=='center',isEnd=this.pack=='end',nonFlexHeight=0,maxWidth=0,totalFlex=0,desiredHeight=0,minimumHeight=0,boxes=[],child,childWidth,childHeight,childSize,childMargins,canLayout,i,calcs,flexedWidth,horizMargins,vertMargins,stretchWidth;for(i=0;i<visibleCount;i++){child=visibleItems[i];childHeight=child.height;childWidth=child.width;canLayout=!child.hasLayout&&typeof child.doLayout=='function';if(typeof childHeight!='number'){if(child.flex&&!childHeight){totalFlex+=child.flex;}else{if(!childHeight&&canLayout){child.doLayout();}
+childSize=child.getSize();childWidth=childSize.width;childHeight=childSize.height;}}
+childMargins=child.margins;vertMargins=childMargins.top+childMargins.bottom;nonFlexHeight+=vertMargins+(childHeight||0);desiredHeight+=vertMargins+(child.flex?child.minHeight||0:childHeight);minimumHeight+=vertMargins+(child.minHeight||childHeight||0);if(typeof childWidth!='number'){if(canLayout){child.doLayout();}
+childWidth=child.getWidth();}
+maxWidth=Math.max(maxWidth,childWidth+childMargins.left+childMargins.right);boxes.push({component:child,height:childHeight||undefined,width:childWidth||undefined});}
+var shortfall=desiredHeight-height,tooNarrow=minimumHeight>height;var availableHeight=Math.max(0,(height-nonFlexHeight-paddingVert));if(tooNarrow){for(i=0,length=visibleCount;i<length;i++){boxes[i].height=visibleItems[i].minHeight||visibleItems[i].height||boxes[i].height;}}else{if(shortfall>0){var minHeights=[];for(var index=0,length=visibleCount;index<length;index++){var item=visibleItems[index],minHeight=item.minHeight||0;if(item.flex){boxes[index].height=minHeight;}else{minHeights.push({minHeight:minHeight,available:boxes[index].height-minHeight,index:index});}}
+minHeights.sort(function(a,b){return a.available>b.available?1:-1;});for(var i=0,length=minHeights.length;i<length;i++){var itemIndex=minHeights[i].index;if(itemIndex==undefined){continue;}
+var item=visibleItems[itemIndex],box=boxes[itemIndex],oldHeight=box.height,minHeight=item.minHeight,newHeight=Math.max(minHeight,oldHeight-Math.ceil(shortfall/(length-i))),reduction=oldHeight-newHeight;boxes[itemIndex].height=newHeight;shortfall-=reduction;}}else{var remainingHeight=availableHeight,remainingFlex=totalFlex;for(i=0;i<visibleCount;i++){child=visibleItems[i];calcs=boxes[i];childMargins=child.margins;horizMargins=childMargins.left+childMargins.right;if(isStart&&child.flex&&!child.height){flexedHeight=Math.ceil((child.flex/remainingFlex)*remainingHeight);remainingHeight-=flexedHeight;remainingFlex-=child.flex;calcs.height=flexedHeight;calcs.dirtySize=true;}}}}
+if(isCenter){topOffset+=availableHeight/2;}else if(isEnd){topOffset+=availableHeight;}
+for(i=0;i<visibleCount;i++){child=visibleItems[i];calcs=boxes[i];childMargins=child.margins;topOffset+=childMargins.top;horizMargins=childMargins.left+childMargins.right;calcs.left=leftOffset+childMargins.left;calcs.top=topOffset;switch(this.align){case'stretch':stretchWidth=availWidth-horizMargins;calcs.width=stretchWidth.constrain(child.minWidth||0,child.maxWidth||1000000);calcs.dirtySize=true;break;case'stretchmax':stretchWidth=maxWidth-horizMargins;calcs.width=stretchWidth.constrain(child.minWidth||0,child.maxWidth||1000000);calcs.dirtySize=true;break;case'center':var diff=availWidth-calcs.width-horizMargins;if(diff>0){calcs.left=leftOffset+horizMargins+(diff/2);}}
+topOffset+=calcs.height+childMargins.bottom;}
+return{boxes:boxes,meta:{maxWidth:maxWidth,nonFlexHeight:nonFlexHeight,desiredHeight:desiredHeight,minimumHeight:minimumHeight,shortfall:desiredHeight-height,tooNarrow:tooNarrow}};}});Ext.Container.LAYOUTS.vbox=Ext.layout.VBoxLayout;Ext.layout.ToolbarLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,type:'toolbar',triggerWidth:18,noItemsMenuText:'<div class="x-toolbar-no-items">(None)</div>',lastOverflow:false,tableHTML:['<table cellspacing="0" class="x-toolbar-ct">','<tbody>','<tr>','<td class="x-toolbar-left" align="{0}">','<table cellspacing="0">','<tbody>','<tr class="x-toolbar-left-row"></tr>','</tbody>','</table>','</td>','<td class="x-toolbar-right" align="right">','<table cellspacing="0" class="x-toolbar-right-ct">','<tbody>','<tr>','<td>','<table cellspacing="0">','<tbody>','<tr class="x-toolbar-right-row"></tr>','</tbody>','</table>','</td>','<td>','<table cellspacing="0">','<tbody>','<tr class="x-toolbar-extras-row"></tr>','</tbody>','</table>','</td>','</tr>','</tbody>','</table>','</td>','</tr>','</tbody>','</table>'].join(""),onLayout:function(ct,target){if(!this.leftTr){var align=ct.buttonAlign=='center'?'center':'left';target.addClass('x-toolbar-layout-ct');target.insertHtml('beforeEnd',String.format(this.tableHTML,align));this.leftTr=target.child('tr.x-toolbar-left-row',true);this.rightTr=target.child('tr.x-toolbar-right-row',true);this.extrasTr=target.child('tr.x-toolbar-extras-row',true);if(this.hiddenItem==undefined){this.hiddenItems=[];}}
+var side=ct.buttonAlign=='right'?this.rightTr:this.leftTr,items=ct.items.items,position=0;for(var i=0,len=items.length,c;i<len;i++,position++){c=items[i];if(c.isFill){side=this.rightTr;position=-1;}else if(!c.rendered){c.render(this.insertCell(c,side,position));this.configureItem(c);}else{if(!c.xtbHidden&&!this.isValidParent(c,side.childNodes[position])){var td=this.insertCell(c,side,position);td.appendChild(c.getPositionEl().dom);c.container=Ext.get(td);}}}
+this.cleanup(this.leftTr);this.cleanup(this.rightTr);this.cleanup(this.extrasTr);this.fitToSize(target);},cleanup:function(el){var cn=el.childNodes,i,c;for(i=cn.length-1;i>=0&&(c=cn[i]);i--){if(!c.firstChild){el.removeChild(c);}}},insertCell:function(c,target,position){var td=document.createElement('td');td.className='x-toolbar-cell';target.insertBefore(td,target.childNodes[position]||null);return td;},hideItem:function(item){this.hiddenItems.push(item);item.xtbHidden=true;item.xtbWidth=item.getPositionEl().dom.parentNode.offsetWidth;item.hide();},unhideItem:function(item){item.show();item.xtbHidden=false;this.hiddenItems.remove(item);},getItemWidth:function(c){return c.hidden?(c.xtbWidth||0):c.getPositionEl().dom.parentNode.offsetWidth;},fitToSize:function(target){if(this.container.enableOverflow===false){return;}
+var width=target.dom.clientWidth,tableWidth=target.dom.firstChild.offsetWidth,clipWidth=width-this.triggerWidth,lastWidth=this.lastWidth||0,hiddenItems=this.hiddenItems,hasHiddens=hiddenItems.length!=0,isLarger=width>=lastWidth;this.lastWidth=width;if(tableWidth>width||(hasHiddens&&isLarger)){var items=this.container.items.items,len=items.length,loopWidth=0,item;for(var i=0;i<len;i++){item=items[i];if(!item.isFill){loopWidth+=this.getItemWidth(item);if(loopWidth>clipWidth){if(!(item.hidden||item.xtbHidden)){this.hideItem(item);}}else if(item.xtbHidden){this.unhideItem(item);}}}}
+hasHiddens=hiddenItems.length!=0;if(hasHiddens){this.initMore();if(!this.lastOverflow){this.container.fireEvent('overflowchange',this.container,true);this.lastOverflow=true;}}else if(this.more){this.clearMenu();this.more.destroy();delete this.more;if(this.lastOverflow){this.container.fireEvent('overflowchange',this.container,false);this.lastOverflow=false;}}},createMenuConfig:function(component,hideOnClick){var config=Ext.apply({},component.initialConfig),group=component.toggleGroup;Ext.copyTo(config,component,['iconCls','icon','itemId','disabled','handler','scope','menu']);Ext.apply(config,{text:component.overflowText||component.text,hideOnClick:hideOnClick});if(group||component.enableToggle){Ext.apply(config,{group:group,checked:component.pressed,listeners:{checkchange:function(item,checked){component.toggle(checked);}}});}
+delete config.ownerCt;delete config.xtype;delete config.id;return config;},addComponentToMenu:function(menu,component){if(component instanceof Ext.Toolbar.Separator){menu.add('-');}else if(Ext.isFunction(component.isXType)){if(component.isXType('splitbutton')){menu.add(this.createMenuConfig(component,true));}else if(component.isXType('button')){menu.add(this.createMenuConfig(component,!component.menu));}else if(component.isXType('buttongroup')){component.items.each(function(item){this.addComponentToMenu(menu,item);},this);}}},clearMenu:function(){var menu=this.moreMenu;if(menu&&menu.items){menu.items.each(function(item){delete item.menu;});}},beforeMoreShow:function(menu){var items=this.container.items.items,len=items.length,item,prev;var needsSep=function(group,item){return group.isXType('buttongroup')&&!(item instanceof Ext.Toolbar.Separator);};this.clearMenu();menu.removeAll();for(var i=0;i<len;i++){item=items[i];if(item.xtbHidden){if(prev&&(needsSep(item,prev)||needsSep(prev,item))){menu.add('-');}
+this.addComponentToMenu(menu,item);prev=item;}}
+if(menu.items.length<1){menu.add(this.noItemsMenuText);}},initMore:function(){if(!this.more){this.moreMenu=new Ext.menu.Menu({ownerCt:this.container,listeners:{beforeshow:this.beforeMoreShow,scope:this}});this.more=new Ext.Button({iconCls:'x-toolbar-more-icon',cls:'x-toolbar-more',menu:this.moreMenu,ownerCt:this.container});var td=this.insertCell(this.more,this.extrasTr,100);this.more.render(td);}},destroy:function(){Ext.destroy(this.more,this.moreMenu);delete this.leftTr;delete this.rightTr;delete this.extrasTr;Ext.layout.ToolbarLayout.superclass.destroy.call(this);}});Ext.Container.LAYOUTS.toolbar=Ext.layout.ToolbarLayout;Ext.layout.MenuLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,type:'menu',setContainer:function(ct){this.monitorResize=!ct.floating;ct.on('autosize',this.doAutoSize,this);Ext.layout.MenuLayout.superclass.setContainer.call(this,ct);},renderItem:function(c,position,target){if(!this.itemTpl){this.itemTpl=Ext.layout.MenuLayout.prototype.itemTpl=new Ext.XTemplate('<li id="{itemId}" class="{itemCls}">','<tpl if="needsIcon">','<img alt="{altText}" src="{icon}" class="{iconCls}"/>','</tpl>','</li>');}
+if(c&&!c.rendered){if(Ext.isNumber(position)){position=target.dom.childNodes[position];}
+var a=this.getItemArgs(c);c.render(c.positionEl=position?this.itemTpl.insertBefore(position,a,true):this.itemTpl.append(target,a,true));c.positionEl.menuItemId=c.getItemId();if(!a.isMenuItem&&a.needsIcon){c.positionEl.addClass('x-menu-list-item-indent');}
+this.configureItem(c);}else if(c&&!this.isValidParent(c,target)){if(Ext.isNumber(position)){position=target.dom.childNodes[position];}
+target.dom.insertBefore(c.getActionEl().dom,position||null);}},getItemArgs:function(c){var isMenuItem=c instanceof Ext.menu.Item,canHaveIcon=!(isMenuItem||c instanceof Ext.menu.Separator);return{isMenuItem:isMenuItem,needsIcon:canHaveIcon&&(c.icon||c.iconCls),icon:c.icon||Ext.BLANK_IMAGE_URL,iconCls:'x-menu-item-icon '+(c.iconCls||''),itemId:'x-menu-el-'+c.id,itemCls:'x-menu-list-item ',altText:c.altText||''};},isValidParent:function(c,target){return c.el.up('li.x-menu-list-item',5).dom.parentNode===(target.dom||target);},onLayout:function(ct,target){Ext.layout.MenuLayout.superclass.onLayout.call(this,ct,target);this.doAutoSize();},doAutoSize:function(){var ct=this.container,w=ct.width;if(ct.floating){if(w){ct.setWidth(w);}else if(Ext.isIE){ct.setWidth(Ext.isStrict&&(Ext.isIE7||Ext.isIE8)?'auto':ct.minWidth);var el=ct.getEl(),t=el.dom.offsetWidth;ct.setWidth(ct.getLayoutTarget().getWidth()+el.getFrameWidth('lr'));}}}});Ext.Container.LAYOUTS['menu']=Ext.layout.MenuLayout;Ext.Viewport=Ext.extend(Ext.Container,{initComponent:function(){Ext.Viewport.superclass.initComponent.call(this);document.getElementsByTagName('html')[0].className+=' x-viewport';this.el=Ext.getBody();this.el.setHeight=Ext.emptyFn;this.el.setWidth=Ext.emptyFn;this.el.setSize=Ext.emptyFn;this.el.dom.scroll='no';this.allowDomMove=false;this.autoWidth=true;this.autoHeight=true;Ext.EventManager.onWindowResize(this.fireResize,this);this.renderTo=this.el;},fireResize:function(w,h){this.fireEvent('resize',this,w,h,w,h);}});Ext.reg('viewport',Ext.Viewport);Ext.Panel=Ext.extend(Ext.Container,{baseCls:'x-panel',collapsedCls:'x-panel-collapsed',maskDisabled:true,animCollapse:Ext.enableFx,headerAsText:true,buttonAlign:'right',collapsed:false,collapseFirst:true,minButtonWidth:75,elements:'body',preventBodyReset:false,padding:undefined,resizeEvent:'bodyresize',toolTarget:'header',collapseEl:'bwrap',slideAnchor:'t',disabledClass:'',deferHeight:true,expandDefaults:{duration:0.25},collapseDefaults:{duration:0.25},initComponent:function(){Ext.Panel.superclass.initComponent.call(this);this.addEvents('bodyresize','titlechange','iconchange','collapse','expand','beforecollapse','beforeexpand','beforeclose','close','activate','deactivate');if(this.unstyled){this.baseCls='x-plain';}
+this.toolbars=[];if(this.tbar){this.elements+=',tbar';this.topToolbar=this.createToolbar(this.tbar);this.tbar=null;}
+if(this.bbar){this.elements+=',bbar';this.bottomToolbar=this.createToolbar(this.bbar);this.bbar=null;}
+if(this.header===true){this.elements+=',header';this.header=null;}else if(this.headerCfg||(this.title&&this.header!==false)){this.elements+=',header';}
+if(this.footerCfg||this.footer===true){this.elements+=',footer';this.footer=null;}
+if(this.buttons){this.fbar=this.buttons;this.buttons=null;}
+if(this.fbar){this.createFbar(this.fbar);}
+if(this.autoLoad){this.on('render',this.doAutoLoad,this,{delay:10});}},createFbar:function(fbar){var min=this.minButtonWidth;this.elements+=',footer';this.fbar=this.createToolbar(fbar,{buttonAlign:this.buttonAlign,toolbarCls:'x-panel-fbar',enableOverflow:false,defaults:function(c){return{minWidth:c.minWidth||min};}});this.fbar.items.each(function(c){c.minWidth=c.minWidth||this.minButtonWidth;},this);this.buttons=this.fbar.items.items;},createToolbar:function(tb,options){var result;if(Ext.isArray(tb)){tb={items:tb};}
+result=tb.events?Ext.apply(tb,options):this.createComponent(Ext.apply({},tb,options),'toolbar');this.toolbars.push(result);return result;},createElement:function(name,pnode){if(this[name]){pnode.appendChild(this[name].dom);return;}
+if(name==='bwrap'||this.elements.indexOf(name)!=-1){if(this[name+'Cfg']){this[name]=Ext.fly(pnode).createChild(this[name+'Cfg']);}else{var el=document.createElement('div');el.className=this[name+'Cls'];this[name]=Ext.get(pnode.appendChild(el));}
+if(this[name+'CssClass']){this[name].addClass(this[name+'CssClass']);}
+if(this[name+'Style']){this[name].applyStyles(this[name+'Style']);}}},onRender:function(ct,position){Ext.Panel.superclass.onRender.call(this,ct,position);this.createClasses();var el=this.el,d=el.dom,bw,ts;if(this.collapsible&&!this.hideCollapseTool){this.tools=this.tools?this.tools.slice(0):[];this.tools[this.collapseFirst?'unshift':'push']({id:'toggle',handler:this.toggleCollapse,scope:this});}
+if(this.tools){ts=this.tools;this.elements+=(this.header!==false)?',header':'';}
+this.tools={};el.addClass(this.baseCls);if(d.firstChild){this.header=el.down('.'+this.headerCls);this.bwrap=el.down('.'+this.bwrapCls);var cp=this.bwrap?this.bwrap:el;this.tbar=cp.down('.'+this.tbarCls);this.body=cp.down('.'+this.bodyCls);this.bbar=cp.down('.'+this.bbarCls);this.footer=cp.down('.'+this.footerCls);this.fromMarkup=true;}
+if(this.preventBodyReset===true){el.addClass('x-panel-reset');}
+if(this.cls){el.addClass(this.cls);}
+if(this.buttons){this.elements+=',footer';}
+if(this.frame){el.insertHtml('afterBegin',String.format(Ext.Element.boxMarkup,this.baseCls));this.createElement('header',d.firstChild.firstChild.firstChild);this.createElement('bwrap',d);bw=this.bwrap.dom;var ml=d.childNodes[1],bl=d.childNodes[2];bw.appendChild(ml);bw.appendChild(bl);var mc=bw.firstChild.firstChild.firstChild;this.createElement('tbar',mc);this.createElement('body',mc);this.createElement('bbar',mc);this.createElement('footer',bw.lastChild.firstChild.firstChild);if(!this.footer){this.bwrap.dom.lastChild.className+=' x-panel-nofooter';}
+this.ft=Ext.get(this.bwrap.dom.lastChild);this.mc=Ext.get(mc);}else{this.createElement('header',d);this.createElement('bwrap',d);bw=this.bwrap.dom;this.createElement('tbar',bw);this.createElement('body',bw);this.createElement('bbar',bw);this.createElement('footer',bw);if(!this.header){this.body.addClass(this.bodyCls+'-noheader');if(this.tbar){this.tbar.addClass(this.tbarCls+'-noheader');}}}
+if(Ext.isDefined(this.padding)){this.body.setStyle('padding',this.body.addUnits(this.padding));}
+if(this.border===false){this.el.addClass(this.baseCls+'-noborder');this.body.addClass(this.bodyCls+'-noborder');if(this.header){this.header.addClass(this.headerCls+'-noborder');}
+if(this.footer){this.footer.addClass(this.footerCls+'-noborder');}
+if(this.tbar){this.tbar.addClass(this.tbarCls+'-noborder');}
+if(this.bbar){this.bbar.addClass(this.bbarCls+'-noborder');}}
+if(this.bodyBorder===false){this.body.addClass(this.bodyCls+'-noborder');}
+this.bwrap.enableDisplayMode('block');if(this.header){this.header.unselectable();if(this.headerAsText){this.header.dom.innerHTML='<span class="'+this.headerTextCls+'">'+this.header.dom.innerHTML+'</span>';if(this.iconCls){this.setIconClass(this.iconCls);}}}
+if(this.floating){this.makeFloating(this.floating);}
+if(this.collapsible&&this.titleCollapse&&this.header){this.mon(this.header,'click',this.toggleCollapse,this);this.header.setStyle('cursor','pointer');}
+if(ts){this.addTool.apply(this,ts);}
+if(this.fbar){this.footer.addClass('x-panel-btns');this.fbar.ownerCt=this;this.fbar.render(this.footer);this.footer.createChild({cls:'x-clear'});}
+if(this.tbar&&this.topToolbar){this.topToolbar.ownerCt=this;this.topToolbar.render(this.tbar);}
+if(this.bbar&&this.bottomToolbar){this.bottomToolbar.ownerCt=this;this.bottomToolbar.render(this.bbar);}},setIconClass:function(cls){var old=this.iconCls;this.iconCls=cls;if(this.rendered&&this.header){if(this.frame){this.header.addClass('x-panel-icon');this.header.replaceClass(old,this.iconCls);}else{var hd=this.header,img=hd.child('img.x-panel-inline-icon');if(img){Ext.fly(img).replaceClass(old,this.iconCls);}else{var hdspan=hd.child('span.'+this.headerTextCls);if(hdspan){Ext.DomHelper.insertBefore(hdspan.dom,{tag:'img',alt:'',src:Ext.BLANK_IMAGE_URL,cls:'x-panel-inline-icon '+this.iconCls});}}}}
+this.fireEvent('iconchange',this,cls,old);},makeFloating:function(cfg){this.floating=true;this.el=new Ext.Layer(Ext.apply({},cfg,{shadow:Ext.isDefined(this.shadow)?this.shadow:'sides',shadowOffset:this.shadowOffset,constrain:false,shim:this.shim===false?false:undefined}),this.el);},getTopToolbar:function(){return this.topToolbar;},getBottomToolbar:function(){return this.bottomToolbar;},getFooterToolbar:function(){return this.fbar;},addButton:function(config,handler,scope){if(!this.fbar){this.createFbar([]);}
+if(handler){if(Ext.isString(config)){config={text:config};}
+config=Ext.apply({handler:handler,scope:scope},config);}
+return this.fbar.add(config);},addTool:function(){if(!this.rendered){if(!this.tools){this.tools=[];}
+Ext.each(arguments,function(arg){this.tools.push(arg);},this);return;}
+if(!this[this.toolTarget]){return;}
+if(!this.toolTemplate){var tt=new Ext.Template('<div class="x-tool x-tool-{id}">&#160;</div>');tt.disableFormats=true;tt.compile();Ext.Panel.prototype.toolTemplate=tt;}
+for(var i=0,a=arguments,len=a.length;i<len;i++){var tc=a[i];if(!this.tools[tc.id]){var overCls='x-tool-'+tc.id+'-over';var t=this.toolTemplate.insertFirst(this[this.toolTarget],tc,true);this.tools[tc.id]=t;t.enableDisplayMode('block');this.mon(t,'click',this.createToolHandler(t,tc,overCls,this));if(tc.on){this.mon(t,tc.on);}
+if(tc.hidden){t.hide();}
+if(tc.qtip){if(Ext.isObject(tc.qtip)){Ext.QuickTips.register(Ext.apply({target:t.id},tc.qtip));}else{t.dom.qtip=tc.qtip;}}
+t.addClassOnOver(overCls);}}},onLayout:function(shallow,force){Ext.Panel.superclass.onLayout.apply(this,arguments);if(this.hasLayout&&this.toolbars.length>0){Ext.each(this.toolbars,function(tb){tb.doLayout(undefined,force);});this.syncHeight();}},syncHeight:function(){var h=this.toolbarHeight,bd=this.body,lsh=this.lastSize.height,sz;if(this.autoHeight||!Ext.isDefined(lsh)||lsh=='auto'){return;}
+if(h!=this.getToolbarHeight()){h=Math.max(0,lsh-this.getFrameHeight());bd.setHeight(h);sz=bd.getSize();this.toolbarHeight=this.getToolbarHeight();this.onBodyResize(sz.width,sz.height);}},onShow:function(){if(this.floating){return this.el.show();}
+Ext.Panel.superclass.onShow.call(this);},onHide:function(){if(this.floating){return this.el.hide();}
+Ext.Panel.superclass.onHide.call(this);},createToolHandler:function(t,tc,overCls,panel){return function(e){t.removeClass(overCls);if(tc.stopEvent!==false){e.stopEvent();}
+if(tc.handler){tc.handler.call(tc.scope||t,e,t,panel,tc);}};},afterRender:function(){if(this.floating&&!this.hidden){this.el.show();}
+if(this.title){this.setTitle(this.title);}
+Ext.Panel.superclass.afterRender.call(this);if(this.collapsed){this.collapsed=false;this.collapse(false);}
+this.initEvents();},getKeyMap:function(){if(!this.keyMap){this.keyMap=new Ext.KeyMap(this.el,this.keys);}
+return this.keyMap;},initEvents:function(){if(this.keys){this.getKeyMap();}
+if(this.draggable){this.initDraggable();}
+if(this.toolbars.length>0){Ext.each(this.toolbars,function(tb){tb.doLayout();tb.on({scope:this,afterlayout:this.syncHeight,remove:this.syncHeight});},this);this.syncHeight();}},initDraggable:function(){this.dd=new Ext.Panel.DD(this,Ext.isBoolean(this.draggable)?null:this.draggable);},beforeEffect:function(anim){if(this.floating){this.el.beforeAction();}
+if(anim!==false){this.el.addClass('x-panel-animated');}},afterEffect:function(anim){this.syncShadow();this.el.removeClass('x-panel-animated');},createEffect:function(a,cb,scope){var o={scope:scope,block:true};if(a===true){o.callback=cb;return o;}else if(!a.callback){o.callback=cb;}else{o.callback=function(){cb.call(scope);Ext.callback(a.callback,a.scope);};}
+return Ext.applyIf(o,a);},collapse:function(animate){if(this.collapsed||this.el.hasFxBlock()||this.fireEvent('beforecollapse',this,animate)===false){return;}
+var doAnim=animate===true||(animate!==false&&this.animCollapse);this.beforeEffect(doAnim);this.onCollapse(doAnim,animate);return this;},onCollapse:function(doAnim,animArg){if(doAnim){this[this.collapseEl].slideOut(this.slideAnchor,Ext.apply(this.createEffect(animArg||true,this.afterCollapse,this),this.collapseDefaults));}else{this[this.collapseEl].hide(this.hideMode);this.afterCollapse(false);}},afterCollapse:function(anim){this.collapsed=true;this.el.addClass(this.collapsedCls);if(anim!==false){this[this.collapseEl].hide(this.hideMode);}
+this.afterEffect(anim);this.cascade(function(c){if(c.lastSize){c.lastSize={width:undefined,height:undefined};}});this.fireEvent('collapse',this);},expand:function(animate){if(!this.collapsed||this.el.hasFxBlock()||this.fireEvent('beforeexpand',this,animate)===false){return;}
+var doAnim=animate===true||(animate!==false&&this.animCollapse);this.el.removeClass(this.collapsedCls);this.beforeEffect(doAnim);this.onExpand(doAnim,animate);return this;},onExpand:function(doAnim,animArg){if(doAnim){this[this.collapseEl].slideIn(this.slideAnchor,Ext.apply(this.createEffect(animArg||true,this.afterExpand,this),this.expandDefaults));}else{this[this.collapseEl].show(this.hideMode);this.afterExpand(false);}},afterExpand:function(anim){this.collapsed=false;if(anim!==false){this[this.collapseEl].show(this.hideMode);}
+this.afterEffect(anim);if(this.deferLayout){delete this.deferLayout;this.doLayout(true);}
+this.fireEvent('expand',this);},toggleCollapse:function(animate){this[this.collapsed?'expand':'collapse'](animate);return this;},onDisable:function(){if(this.rendered&&this.maskDisabled){this.el.mask();}
+Ext.Panel.superclass.onDisable.call(this);},onEnable:function(){if(this.rendered&&this.maskDisabled){this.el.unmask();}
+Ext.Panel.superclass.onEnable.call(this);},onResize:function(adjWidth,adjHeight,rawWidth,rawHeight){var w=adjWidth,h=adjHeight;if(Ext.isDefined(w)||Ext.isDefined(h)){if(!this.collapsed){if(Ext.isNumber(w)){this.body.setWidth(w=this.adjustBodyWidth(w-this.getFrameWidth()));}else if(w=='auto'){w=this.body.setWidth('auto').dom.offsetWidth;}else{w=this.body.dom.offsetWidth;}
+if(this.tbar){this.tbar.setWidth(w);if(this.topToolbar){this.topToolbar.setSize(w);}}
+if(this.bbar){this.bbar.setWidth(w);if(this.bottomToolbar){this.bottomToolbar.setSize(w);if(Ext.isIE){this.bbar.setStyle('position','static');this.bbar.setStyle('position','');}}}
+if(this.footer){this.footer.setWidth(w);if(this.fbar){this.fbar.setSize(Ext.isIE?(w-this.footer.getFrameWidth('lr')):'auto');}}
+if(Ext.isNumber(h)){h=Math.max(0,h-this.getFrameHeight());this.body.setHeight(h);}else if(h=='auto'){this.body.setHeight(h);}
+if(this.disabled&&this.el._mask){this.el._mask.setSize(this.el.dom.clientWidth,this.el.getHeight());}}else{this.queuedBodySize={width:w,height:h};if(!this.queuedExpand&&this.allowQueuedExpand!==false){this.queuedExpand=true;this.on('expand',function(){delete this.queuedExpand;this.onResize(this.queuedBodySize.width,this.queuedBodySize.height);},this,{single:true});}}
+this.onBodyResize(w,h);}
+this.syncShadow();Ext.Panel.superclass.onResize.call(this,adjWidth,adjHeight,rawWidth,rawHeight);},onBodyResize:function(w,h){this.fireEvent('bodyresize',this,w,h);},getToolbarHeight:function(){var h=0;if(this.rendered){Ext.each(this.toolbars,function(tb){h+=tb.getHeight();},this);}
+return h;},adjustBodyHeight:function(h){return h;},adjustBodyWidth:function(w){return w;},onPosition:function(){this.syncShadow();},getFrameWidth:function(){var w=this.el.getFrameWidth('lr')+this.bwrap.getFrameWidth('lr');if(this.frame){var l=this.bwrap.dom.firstChild;w+=(Ext.fly(l).getFrameWidth('l')+Ext.fly(l.firstChild).getFrameWidth('r'));w+=this.mc.getFrameWidth('lr');}
+return w;},getFrameHeight:function(){var h=this.el.getFrameWidth('tb')+this.bwrap.getFrameWidth('tb');h+=(this.tbar?this.tbar.getHeight():0)+
+(this.bbar?this.bbar.getHeight():0);if(this.frame){h+=this.el.dom.firstChild.offsetHeight+this.ft.dom.offsetHeight+this.mc.getFrameWidth('tb');}else{h+=(this.header?this.header.getHeight():0)+
+(this.footer?this.footer.getHeight():0);}
+return h;},getInnerWidth:function(){return this.getSize().width-this.getFrameWidth();},getInnerHeight:function(){return this.body.getHeight();},syncShadow:function(){if(this.floating){this.el.sync(true);}},getLayoutTarget:function(){return this.body;},getContentTarget:function(){return this.body;},setTitle:function(title,iconCls){this.title=title;if(this.header&&this.headerAsText){this.header.child('span').update(title);}
+if(iconCls){this.setIconClass(iconCls);}
+this.fireEvent('titlechange',this,title);return this;},getUpdater:function(){return this.body.getUpdater();},load:function(){var um=this.body.getUpdater();um.update.apply(um,arguments);return this;},beforeDestroy:function(){Ext.Panel.superclass.beforeDestroy.call(this);if(this.header){this.header.removeAllListeners();}
+if(this.tools){for(var k in this.tools){Ext.destroy(this.tools[k]);}}
+if(this.toolbars.length>0){Ext.each(this.toolbars,function(tb){tb.un('afterlayout',this.syncHeight,this);tb.un('remove',this.syncHeight,this);},this);}
+if(Ext.isArray(this.buttons)){while(this.buttons.length){Ext.destroy(this.buttons[0]);}}
+if(this.rendered){Ext.destroy(this.ft,this.header,this.footer,this.tbar,this.bbar,this.body,this.mc,this.bwrap,this.dd);if(this.fbar){Ext.destroy(this.fbar,this.fbar.el);}}
+Ext.destroy(this.toolbars);},createClasses:function(){this.headerCls=this.baseCls+'-header';this.headerTextCls=this.baseCls+'-header-text';this.bwrapCls=this.baseCls+'-bwrap';this.tbarCls=this.baseCls+'-tbar';this.bodyCls=this.baseCls+'-body';this.bbarCls=this.baseCls+'-bbar';this.footerCls=this.baseCls+'-footer';},createGhost:function(cls,useShim,appendTo){var el=document.createElement('div');el.className='x-panel-ghost '+(cls?cls:'');if(this.header){el.appendChild(this.el.dom.firstChild.cloneNode(true));}
+Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());el.style.width=this.el.dom.offsetWidth+'px';;if(!appendTo){this.container.dom.appendChild(el);}else{Ext.getDom(appendTo).appendChild(el);}
+if(useShim!==false&&this.el.useShim!==false){var layer=new Ext.Layer({shadow:false,useDisplay:true,constrain:false},el);layer.show();return layer;}else{return new Ext.Element(el);}},doAutoLoad:function(){var u=this.body.getUpdater();if(this.renderer){u.setRenderer(this.renderer);}
+u.update(Ext.isObject(this.autoLoad)?this.autoLoad:{url:this.autoLoad});},getTool:function(id){return this.tools[id];}});Ext.reg('panel',Ext.Panel);Ext.Editor=function(field,config){if(field.field){this.field=Ext.create(field.field,'textfield');config=Ext.apply({},field);delete config.field;}else{this.field=field;}
+Ext.Editor.superclass.constructor.call(this,config);};Ext.extend(Ext.Editor,Ext.Component,{allowBlur:true,value:"",alignment:"c-c?",offsets:[0,0],shadow:"frame",constrain:false,swallowKeys:true,completeOnEnter:true,cancelOnEsc:true,updateEl:false,initComponent:function(){Ext.Editor.superclass.initComponent.call(this);this.addEvents("beforestartedit","startedit","beforecomplete","complete","canceledit","specialkey");},onRender:function(ct,position){this.el=new Ext.Layer({shadow:this.shadow,cls:"x-editor",parentEl:ct,shim:this.shim,shadowOffset:this.shadowOffset||4,id:this.id,constrain:this.constrain});if(this.zIndex){this.el.setZIndex(this.zIndex);}
+this.el.setStyle("overflow",Ext.isGecko?"auto":"hidden");if(this.field.msgTarget!='title'){this.field.msgTarget='qtip';}
+this.field.inEditor=true;this.mon(this.field,{scope:this,blur:this.onBlur,specialkey:this.onSpecialKey});if(this.field.grow){this.mon(this.field,"autosize",this.el.sync,this.el,{delay:1});}
+this.field.render(this.el).show();this.field.getEl().dom.name='';if(this.swallowKeys){this.field.el.swallowEvent(['keypress','keydown']);}},onSpecialKey:function(field,e){var key=e.getKey(),complete=this.completeOnEnter&&key==e.ENTER,cancel=this.cancelOnEsc&&key==e.ESC;if(complete||cancel){e.stopEvent();if(complete){this.completeEdit();}else{this.cancelEdit();}
+if(field.triggerBlur){field.triggerBlur();}}
+this.fireEvent('specialkey',field,e);},startEdit:function(el,value){if(this.editing){this.completeEdit();}
+this.boundEl=Ext.get(el);var v=value!==undefined?value:this.boundEl.dom.innerHTML;if(!this.rendered){this.render(this.parentEl||document.body);}
+if(this.fireEvent("beforestartedit",this,this.boundEl,v)!==false){this.startValue=v;this.field.reset();this.field.setValue(v);this.realign(true);this.editing=true;this.show();}},doAutoSize:function(){if(this.autoSize){var sz=this.boundEl.getSize(),fs=this.field.getSize();switch(this.autoSize){case"width":this.setSize(sz.width,fs.height);break;case"height":this.setSize(fs.width,sz.height);break;case"none":this.setSize(fs.width,fs.height);break;default:this.setSize(sz.width,sz.height);}}},setSize:function(w,h){delete this.field.lastSize;this.field.setSize(w,h);if(this.el){if(Ext.isGecko2||Ext.isOpera||(Ext.isIE7&&Ext.isStrict)){this.el.setSize(w,h);}
+this.el.sync();}},realign:function(autoSize){if(autoSize===true){this.doAutoSize();}
+this.el.alignTo(this.boundEl,this.alignment,this.offsets);},completeEdit:function(remainVisible){if(!this.editing){return;}
+if(this.field.assertValue){this.field.assertValue();}
+var v=this.getValue();if(!this.field.isValid()){if(this.revertInvalid!==false){this.cancelEdit(remainVisible);}
+return;}
+if(String(v)===String(this.startValue)&&this.ignoreNoChange){this.hideEdit(remainVisible);return;}
+if(this.fireEvent("beforecomplete",this,v,this.startValue)!==false){v=this.getValue();if(this.updateEl&&this.boundEl){this.boundEl.update(v);}
+this.hideEdit(remainVisible);this.fireEvent("complete",this,v,this.startValue);}},onShow:function(){this.el.show();if(this.hideEl!==false){this.boundEl.hide();}
+this.field.show().focus(false,true);this.fireEvent("startedit",this.boundEl,this.startValue);},cancelEdit:function(remainVisible){if(this.editing){var v=this.getValue();this.setValue(this.startValue);this.hideEdit(remainVisible);this.fireEvent("canceledit",this,v,this.startValue);}},hideEdit:function(remainVisible){if(remainVisible!==true){this.editing=false;this.hide();}},onBlur:function(){if(this.allowBlur===true&&this.editing&&this.selectSameEditor!==true){this.completeEdit();}},onHide:function(){if(this.editing){this.completeEdit();return;}
+this.field.blur();if(this.field.collapse){this.field.collapse();}
+this.el.hide();if(this.hideEl!==false){this.boundEl.show();}},setValue:function(v){this.field.setValue(v);},getValue:function(){return this.field.getValue();},beforeDestroy:function(){Ext.destroyMembers(this,'field');delete this.parentEl;delete this.boundEl;}});Ext.reg('editor',Ext.Editor);Ext.ColorPalette=Ext.extend(Ext.Component,{itemCls:'x-color-palette',value:null,clickEvent:'click',ctype:'Ext.ColorPalette',allowReselect:false,colors:['000000','993300','333300','003300','003366','000080','333399','333333','800000','FF6600','808000','008000','008080','0000FF','666699','808080','FF0000','FF9900','99CC00','339966','33CCCC','3366FF','800080','969696','FF00FF','FFCC00','FFFF00','00FF00','00FFFF','00CCFF','993366','C0C0C0','FF99CC','FFCC99','FFFF99','CCFFCC','CCFFFF','99CCFF','CC99FF','FFFFFF'],initComponent:function(){Ext.ColorPalette.superclass.initComponent.call(this);this.addEvents('select');if(this.handler){this.on('select',this.handler,this.scope,true);}},onRender:function(container,position){this.autoEl={tag:'div',cls:this.itemCls};Ext.ColorPalette.superclass.onRender.call(this,container,position);var t=this.tpl||new Ext.XTemplate('<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>');t.overwrite(this.el,this.colors);this.mon(this.el,this.clickEvent,this.handleClick,this,{delegate:'a'});if(this.clickEvent!='click'){this.mon(this.el,'click',Ext.emptyFn,this,{delegate:'a',preventDefault:true});}},afterRender:function(){Ext.ColorPalette.superclass.afterRender.call(this);if(this.value){var s=this.value;this.value=null;this.select(s,true);}},handleClick:function(e,t){e.preventDefault();if(!this.disabled){var c=t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];this.select(c.toUpperCase());}},select:function(color,suppressEvent){color=color.replace('#','');if(color!=this.value||this.allowReselect){var el=this.el;if(this.value){el.child('a.color-'+this.value).removeClass('x-color-palette-sel');}
+el.child('a.color-'+color).addClass('x-color-palette-sel');this.value=color;if(suppressEvent!==true){this.fireEvent('select',this,color);}}}});Ext.reg('colorpalette',Ext.ColorPalette);Ext.DatePicker=Ext.extend(Ext.BoxComponent,{todayText:'Today',okText:'&#160;OK&#160;',cancelText:'Cancel',todayTip:'{0} (Spacebar)',minText:'This date is before the minimum date',maxText:'This date is after the maximum date',format:'m/d/y',disabledDaysText:'Disabled',disabledDatesText:'Disabled',monthNames:Date.monthNames,dayNames:Date.dayNames,nextText:'Next Month (Control+Right)',prevText:'Previous Month (Control+Left)',monthYearText:'Choose a month (Control+Up/Down to move years)',startDay:0,showToday:true,focusOnSelect:true,initHour:12,initComponent:function(){Ext.DatePicker.superclass.initComponent.call(this);this.value=this.value?this.value.clearTime(true):new Date().clearTime();this.addEvents('select');if(this.handler){this.on('select',this.handler,this.scope||this);}
+this.initDisabledDays();},initDisabledDays:function(){if(!this.disabledDatesRE&&this.disabledDates){var dd=this.disabledDates,len=dd.length-1,re='(?:';Ext.each(dd,function(d,i){re+=Ext.isDate(d)?'^'+Ext.escapeRe(d.dateFormat(this.format))+'$':dd[i];if(i!=len){re+='|';}},this);this.disabledDatesRE=new RegExp(re+')');}},setDisabledDates:function(dd){if(Ext.isArray(dd)){this.disabledDates=dd;this.disabledDatesRE=null;}else{this.disabledDatesRE=dd;}
+this.initDisabledDays();this.update(this.value,true);},setDisabledDays:function(dd){this.disabledDays=dd;this.update(this.value,true);},setMinDate:function(dt){this.minDate=dt;this.update(this.value,true);},setMaxDate:function(dt){this.maxDate=dt;this.update(this.value,true);},setValue:function(value){this.value=value.clearTime(true);this.update(this.value);},getValue:function(){return this.value;},focus:function(){this.update(this.activeDate);},onEnable:function(initial){Ext.DatePicker.superclass.onEnable.call(this);this.doDisabled(false);this.update(initial?this.value:this.activeDate);if(Ext.isIE){this.el.repaint();}},onDisable:function(){Ext.DatePicker.superclass.onDisable.call(this);this.doDisabled(true);if(Ext.isIE&&!Ext.isIE8){Ext.each([].concat(this.textNodes,this.el.query('th span')),function(el){Ext.fly(el).repaint();});}},doDisabled:function(disabled){this.keyNav.setDisabled(disabled);this.prevRepeater.setDisabled(disabled);this.nextRepeater.setDisabled(disabled);if(this.showToday){this.todayKeyListener.setDisabled(disabled);this.todayBtn.setDisabled(disabled);}},onRender:function(container,position){var m=['<table cellspacing="0">','<tr><td class="x-date-left"><a href="#" title="',this.prevText,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="',this.nextText,'">&#160;</a></td></tr>','<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],dn=this.dayNames,i;for(i=0;i<7;i++){var d=this.startDay+i;if(d>6){d=d-7;}
+m.push('<th><span>',dn[d].substr(0,1),'</span></th>');}
+m[m.length]='</tr></thead><tbody><tr>';for(i=0;i<42;i++){if(i%7===0&&i!==0){m[m.length]='</tr><tr>';}
+m[m.length]='<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';}
+m.push('</tr></tbody></table></td></tr>',this.showToday?'<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>':'','</table><div class="x-date-mp"></div>');var el=document.createElement('div');el.className='x-date-picker';el.innerHTML=m.join('');container.dom.insertBefore(el,position);this.el=Ext.get(el);this.eventEl=Ext.get(el.firstChild);this.prevRepeater=new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'),{handler:this.showPrevMonth,scope:this,preventDefault:true,stopDefault:true});this.nextRepeater=new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'),{handler:this.showNextMonth,scope:this,preventDefault:true,stopDefault:true});this.monthPicker=this.el.down('div.x-date-mp');this.monthPicker.enableDisplayMode('block');this.keyNav=new Ext.KeyNav(this.eventEl,{'left':function(e){if(e.ctrlKey){this.showPrevMonth();}else{this.update(this.activeDate.add('d',-1));}},'right':function(e){if(e.ctrlKey){this.showNextMonth();}else{this.update(this.activeDate.add('d',1));}},'up':function(e){if(e.ctrlKey){this.showNextYear();}else{this.update(this.activeDate.add('d',-7));}},'down':function(e){if(e.ctrlKey){this.showPrevYear();}else{this.update(this.activeDate.add('d',7));}},'pageUp':function(e){this.showNextMonth();},'pageDown':function(e){this.showPrevMonth();},'enter':function(e){e.stopPropagation();return true;},scope:this});this.el.unselectable();this.cells=this.el.select('table.x-date-inner tbody td');this.textNodes=this.el.query('table.x-date-inner tbody span');this.mbtn=new Ext.Button({text:'&#160;',tooltip:this.monthYearText,renderTo:this.el.child('td.x-date-middle',true)});this.mbtn.el.child('em').addClass('x-btn-arrow');if(this.showToday){this.todayKeyListener=this.eventEl.addKeyListener(Ext.EventObject.SPACE,this.selectToday,this);var today=(new Date()).dateFormat(this.format);this.todayBtn=new Ext.Button({renderTo:this.el.child('td.x-date-bottom',true),text:String.format(this.todayText,today),tooltip:String.format(this.todayTip,today),handler:this.selectToday,scope:this});}
+this.mon(this.eventEl,'mousewheel',this.handleMouseWheel,this);this.mon(this.eventEl,'click',this.handleDateClick,this,{delegate:'a.x-date-date'});this.mon(this.mbtn,'click',this.showMonthPicker,this);this.onEnable(true);},createMonthPicker:function(){if(!this.monthPicker.dom.firstChild){var buf=['<table border="0" cellspacing="0">'];for(var i=0;i<6;i++){buf.push('<tr><td class="x-date-mp-month"><a href="#">',Date.getShortMonthName(i),'</a></td>','<td class="x-date-mp-month x-date-mp-sep"><a href="#">',Date.getShortMonthName(i+6),'</a></td>',i===0?'<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>':'<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>');}
+buf.push('<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',this.okText,'</button><button type="button" class="x-date-mp-cancel">',this.cancelText,'</button></td></tr>','</table>');this.monthPicker.update(buf.join(''));this.mon(this.monthPicker,'click',this.onMonthClick,this);this.mon(this.monthPicker,'dblclick',this.onMonthDblClick,this);this.mpMonths=this.monthPicker.select('td.x-date-mp-month');this.mpYears=this.monthPicker.select('td.x-date-mp-year');this.mpMonths.each(function(m,a,i){i+=1;if((i%2)===0){m.dom.xmonth=5+Math.round(i*0.5);}else{m.dom.xmonth=Math.round((i-1)*0.5);}});}},showMonthPicker:function(){if(!this.disabled){this.createMonthPicker();var size=this.el.getSize();this.monthPicker.setSize(size);this.monthPicker.child('table').setSize(size);this.mpSelMonth=(this.activeDate||this.value).getMonth();this.updateMPMonth(this.mpSelMonth);this.mpSelYear=(this.activeDate||this.value).getFullYear();this.updateMPYear(this.mpSelYear);this.monthPicker.slideIn('t',{duration:0.2});}},updateMPYear:function(y){this.mpyear=y;var ys=this.mpYears.elements;for(var i=1;i<=10;i++){var td=ys[i-1],y2;if((i%2)===0){y2=y+Math.round(i*0.5);td.firstChild.innerHTML=y2;td.xyear=y2;}else{y2=y-(5-Math.round(i*0.5));td.firstChild.innerHTML=y2;td.xyear=y2;}
+this.mpYears.item(i-1)[y2==this.mpSelYear?'addClass':'removeClass']('x-date-mp-sel');}},updateMPMonth:function(sm){this.mpMonths.each(function(m,a,i){m[m.dom.xmonth==sm?'addClass':'removeClass']('x-date-mp-sel');});},selectMPMonth:function(m){},onMonthClick:function(e,t){e.stopEvent();var el=new Ext.Element(t),pn;if(el.is('button.x-date-mp-cancel')){this.hideMonthPicker();}
+else if(el.is('button.x-date-mp-ok')){var d=new Date(this.mpSelYear,this.mpSelMonth,(this.activeDate||this.value).getDate());if(d.getMonth()!=this.mpSelMonth){d=new Date(this.mpSelYear,this.mpSelMonth,1).getLastDateOfMonth();}
+this.update(d);this.hideMonthPicker();}
+else if((pn=el.up('td.x-date-mp-month',2))){this.mpMonths.removeClass('x-date-mp-sel');pn.addClass('x-date-mp-sel');this.mpSelMonth=pn.dom.xmonth;}
+else if((pn=el.up('td.x-date-mp-year',2))){this.mpYears.removeClass('x-date-mp-sel');pn.addClass('x-date-mp-sel');this.mpSelYear=pn.dom.xyear;}
+else if(el.is('a.x-date-mp-prev')){this.updateMPYear(this.mpyear-10);}
+else if(el.is('a.x-date-mp-next')){this.updateMPYear(this.mpyear+10);}},onMonthDblClick:function(e,t){e.stopEvent();var el=new Ext.Element(t),pn;if((pn=el.up('td.x-date-mp-month',2))){this.update(new Date(this.mpSelYear,pn.dom.xmonth,(this.activeDate||this.value).getDate()));this.hideMonthPicker();}
+else if((pn=el.up('td.x-date-mp-year',2))){this.update(new Date(pn.dom.xyear,this.mpSelMonth,(this.activeDate||this.value).getDate()));this.hideMonthPicker();}},hideMonthPicker:function(disableAnim){if(this.monthPicker){if(disableAnim===true){this.monthPicker.hide();}else{this.monthPicker.slideOut('t',{duration:0.2});}}},showPrevMonth:function(e){this.update(this.activeDate.add('mo',-1));},showNextMonth:function(e){this.update(this.activeDate.add('mo',1));},showPrevYear:function(){this.update(this.activeDate.add('y',-1));},showNextYear:function(){this.update(this.activeDate.add('y',1));},handleMouseWheel:function(e){e.stopEvent();if(!this.disabled){var delta=e.getWheelDelta();if(delta>0){this.showPrevMonth();}else if(delta<0){this.showNextMonth();}}},handleDateClick:function(e,t){e.stopEvent();if(!this.disabled&&t.dateValue&&!Ext.fly(t.parentNode).hasClass('x-date-disabled')){this.cancelFocus=this.focusOnSelect===false;this.setValue(new Date(t.dateValue));delete this.cancelFocus;this.fireEvent('select',this,this.value);}},selectToday:function(){if(this.todayBtn&&!this.todayBtn.disabled){this.setValue(new Date().clearTime());this.fireEvent('select',this,this.value);}},update:function(date,forceRefresh){if(this.rendered){var vd=this.activeDate,vis=this.isVisible();this.activeDate=date;if(!forceRefresh&&vd&&this.el){var t=date.getTime();if(vd.getMonth()==date.getMonth()&&vd.getFullYear()==date.getFullYear()){this.cells.removeClass('x-date-selected');this.cells.each(function(c){if(c.dom.firstChild.dateValue==t){c.addClass('x-date-selected');if(vis&&!this.cancelFocus){Ext.fly(c.dom.firstChild).focus(50);}
+return false;}},this);return;}}
+var days=date.getDaysInMonth(),firstOfMonth=date.getFirstDateOfMonth(),startingPos=firstOfMonth.getDay()-this.startDay;if(startingPos<0){startingPos+=7;}
+days+=startingPos;var pm=date.add('mo',-1),prevStart=pm.getDaysInMonth()-startingPos,cells=this.cells.elements,textEls=this.textNodes,d=(new Date(pm.getFullYear(),pm.getMonth(),prevStart,this.initHour)),today=new Date().clearTime().getTime(),sel=date.clearTime(true).getTime(),min=this.minDate?this.minDate.clearTime(true):Number.NEGATIVE_INFINITY,max=this.maxDate?this.maxDate.clearTime(true):Number.POSITIVE_INFINITY,ddMatch=this.disabledDatesRE,ddText=this.disabledDatesText,ddays=this.disabledDays?this.disabledDays.join(''):false,ddaysText=this.disabledDaysText,format=this.format;if(this.showToday){var td=new Date().clearTime(),disable=(td<min||td>max||(ddMatch&&format&&ddMatch.test(td.dateFormat(format)))||(ddays&&ddays.indexOf(td.getDay())!=-1));if(!this.disabled){this.todayBtn.setDisabled(disable);this.todayKeyListener[disable?'disable':'enable']();}}
+var setCellClass=function(cal,cell){cell.title='';var t=d.clearTime(true).getTime();cell.firstChild.dateValue=t;if(t==today){cell.className+=' x-date-today';cell.title=cal.todayText;}
+if(t==sel){cell.className+=' x-date-selected';if(vis){Ext.fly(cell.firstChild).focus(50);}}
+if(t<min){cell.className=' x-date-disabled';cell.title=cal.minText;return;}
+if(t>max){cell.className=' x-date-disabled';cell.title=cal.maxText;return;}
+if(ddays){if(ddays.indexOf(d.getDay())!=-1){cell.title=ddaysText;cell.className=' x-date-disabled';}}
+if(ddMatch&&format){var fvalue=d.dateFormat(format);if(ddMatch.test(fvalue)){cell.title=ddText.replace('%0',fvalue);cell.className=' x-date-disabled';}}};var i=0;for(;i<startingPos;i++){textEls[i].innerHTML=(++prevStart);d.setDate(d.getDate()+1);cells[i].className='x-date-prevday';setCellClass(this,cells[i]);}
+for(;i<days;i++){var intDay=i-startingPos+1;textEls[i].innerHTML=(intDay);d.setDate(d.getDate()+1);cells[i].className='x-date-active';setCellClass(this,cells[i]);}
+var extraDays=0;for(;i<42;i++){textEls[i].innerHTML=(++extraDays);d.setDate(d.getDate()+1);cells[i].className='x-date-nextday';setCellClass(this,cells[i]);}
+this.mbtn.setText(this.monthNames[date.getMonth()]+' '+date.getFullYear());if(!this.internalRender){var main=this.el.dom.firstChild,w=main.offsetWidth;this.el.setWidth(w+this.el.getBorderWidth('lr'));Ext.fly(main).setWidth(w);this.internalRender=true;if(Ext.isOpera&&!this.secondPass){main.rows[0].cells[1].style.width=(w-(main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth))+'px';this.secondPass=true;this.update.defer(10,this,[date]);}}}},beforeDestroy:function(){if(this.rendered){Ext.destroy(this.keyNav,this.monthPicker,this.eventEl,this.mbtn,this.nextRepeater,this.prevRepeater,this.cells.el,this.todayBtn);delete this.textNodes;delete this.cells.elements;}}});Ext.reg('datepicker',Ext.DatePicker);Ext.LoadMask=function(el,config){this.el=Ext.get(el);Ext.apply(this,config);if(this.store){this.store.on({scope:this,beforeload:this.onBeforeLoad,load:this.onLoad,exception:this.onLoad});this.removeMask=Ext.value(this.removeMask,false);}else{var um=this.el.getUpdater();um.showLoadIndicator=false;um.on({scope:this,beforeupdate:this.onBeforeLoad,update:this.onLoad,failure:this.onLoad});this.removeMask=Ext.value(this.removeMask,true);}};Ext.LoadMask.prototype={msg:'Loading...',msgCls:'x-mask-loading',disabled:false,disable:function(){this.disabled=true;},enable:function(){this.disabled=false;},onLoad:function(){this.el.unmask(this.removeMask);},onBeforeLoad:function(){if(!this.disabled){this.el.mask(this.msg,this.msgCls);}},show:function(){this.onBeforeLoad();},hide:function(){this.onLoad();},destroy:function(){if(this.store){this.store.un('beforeload',this.onBeforeLoad,this);this.store.un('load',this.onLoad,this);this.store.un('exception',this.onLoad,this);}else{var um=this.el.getUpdater();um.un('beforeupdate',this.onBeforeLoad,this);um.un('update',this.onLoad,this);um.un('failure',this.onLoad,this);}}};Ext.ns('Ext.slider');Ext.slider.Thumb=Ext.extend(Object,{dragging:false,constructor:function(config){Ext.apply(this,config||{},{cls:'x-slider-thumb',constrain:false});Ext.slider.Thumb.superclass.constructor.call(this,config);if(this.slider.vertical){Ext.apply(this,Ext.slider.Thumb.Vertical);}},render:function(){this.el=this.slider.innerEl.insertFirst({cls:this.cls});this.initEvents();},enable:function(){this.disabled=false;this.el.removeClass(this.slider.disabledClass);},disable:function(){this.disabled=true;this.el.addClass(this.slider.disabledClass);},initEvents:function(){var el=this.el;el.addClassOnOver('x-slider-thumb-over');this.tracker=new Ext.dd.DragTracker({onBeforeStart:this.onBeforeDragStart.createDelegate(this),onStart:this.onDragStart.createDelegate(this),onDrag:this.onDrag.createDelegate(this),onEnd:this.onDragEnd.createDelegate(this),tolerance:3,autoStart:300});this.tracker.initEl(el);},onBeforeDragStart:function(e){if(this.disabled){return false;}else{this.slider.promoteThumb(this);return true;}},onDragStart:function(e){this.el.addClass('x-slider-thumb-drag');this.dragging=true;this.dragStartValue=this.value;this.slider.fireEvent('dragstart',this.slider,e,this);},onDrag:function(e){var slider=this.slider,index=this.index,newValue=this.getNewValue();if(this.constrain){var above=slider.thumbs[index+1],below=slider.thumbs[index-1];if(below!=undefined&&newValue<=below.value)newValue=below.value;if(above!=undefined&&newValue>=above.value)newValue=above.value;}
+slider.setValue(index,newValue,false);slider.fireEvent('drag',slider,e,this);},getNewValue:function(){var slider=this.slider,pos=slider.innerEl.translatePoints(this.tracker.getXY());return Ext.util.Format.round(slider.reverseValue(pos.left),slider.decimalPrecision);},onDragEnd:function(e){var slider=this.slider,value=this.value;this.el.removeClass('x-slider-thumb-drag');this.dragging=false;slider.fireEvent('dragend',slider,e);if(this.dragStartValue!=value){slider.fireEvent('changecomplete',slider,value,this);}},destroy:function(){Ext.destroyMembers(this,'tracker','el');}});Ext.slider.MultiSlider=Ext.extend(Ext.BoxComponent,{vertical:false,minValue:0,maxValue:100,decimalPrecision:0,keyIncrement:1,increment:0,clickRange:[5,15],clickToChange:true,animate:true,constrainThumbs:true,topThumbZIndex:10000,initComponent:function(){if(!Ext.isDefined(this.value)){this.value=this.minValue;}
+this.thumbs=[];Ext.slider.MultiSlider.superclass.initComponent.call(this);this.keyIncrement=Math.max(this.increment,this.keyIncrement);this.addEvents('beforechange','change','changecomplete','dragstart','drag','dragend');if(this.values==undefined||Ext.isEmpty(this.values))this.values=[0];var values=this.values;for(var i=0;i<values.length;i++){this.addThumb(values[i]);}
+if(this.vertical){Ext.apply(this,Ext.slider.Vertical);}},addThumb:function(value){var thumb=new Ext.slider.Thumb({value:value,slider:this,index:this.thumbs.length,constrain:this.constrainThumbs});this.thumbs.push(thumb);if(this.rendered)thumb.render();},promoteThumb:function(topThumb){var thumbs=this.thumbs,zIndex,thumb;for(var i=0,j=thumbs.length;i<j;i++){thumb=thumbs[i];if(thumb==topThumb){zIndex=this.topThumbZIndex;}else{zIndex='';}
+thumb.el.setStyle('zIndex',zIndex);}},onRender:function(){this.autoEl={cls:'x-slider '+(this.vertical?'x-slider-vert':'x-slider-horz'),cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{tag:'a',cls:'x-slider-focus',href:"#",tabIndex:'-1',hidefocus:'on'}]}}};Ext.slider.MultiSlider.superclass.onRender.apply(this,arguments);this.endEl=this.el.first();this.innerEl=this.endEl.first();this.focusEl=this.innerEl.child('.x-slider-focus');for(var i=0;i<this.thumbs.length;i++){this.thumbs[i].render();}
+var thumb=this.innerEl.child('.x-slider-thumb');this.halfThumb=(this.vertical?thumb.getHeight():thumb.getWidth())/2;this.initEvents();},initEvents:function(){this.mon(this.el,{scope:this,mousedown:this.onMouseDown,keydown:this.onKeyDown});this.focusEl.swallowEvent("click",true);},onMouseDown:function(e){if(this.disabled){return;}
+var thumbClicked=false;for(var i=0;i<this.thumbs.length;i++){thumbClicked=thumbClicked||e.target==this.thumbs[i].el.dom;}
+if(this.clickToChange&&!thumbClicked){var local=this.innerEl.translatePoints(e.getXY());this.onClickChange(local);}
+this.focus();},onClickChange:function(local){if(local.top>this.clickRange[0]&&local.top<this.clickRange[1]){var thumb=this.getNearest(local,'left'),index=thumb.index;this.setValue(index,Ext.util.Format.round(this.reverseValue(local.left),this.decimalPrecision),undefined,true);}},getNearest:function(local,prop){var localValue=prop=='top'?this.innerEl.getHeight()-local[prop]:local[prop],clickValue=this.reverseValue(localValue),nearestDistance=(this.maxValue-this.minValue)+5,index=0,nearest=null;for(var i=0;i<this.thumbs.length;i++){var thumb=this.thumbs[i],value=thumb.value,dist=Math.abs(value-clickValue);if(Math.abs(dist<=nearestDistance)){nearest=thumb;index=i;nearestDistance=dist;}}
+return nearest;},onKeyDown:function(e){if(this.disabled||this.thumbs.length!==1){e.preventDefault();return;}
+var k=e.getKey(),val;switch(k){case e.UP:case e.RIGHT:e.stopEvent();val=e.ctrlKey?this.maxValue:this.getValue(0)+this.keyIncrement;this.setValue(0,val,undefined,true);break;case e.DOWN:case e.LEFT:e.stopEvent();val=e.ctrlKey?this.minValue:this.getValue(0)-this.keyIncrement;this.setValue(0,val,undefined,true);break;default:e.preventDefault();}},doSnap:function(value){if(!(this.increment&&value)){return value;}
+var newValue=value,inc=this.increment,m=value%inc;if(m!=0){newValue-=m;if(m*2>=inc){newValue+=inc;}else if(m*2<-inc){newValue-=inc;}}
+return newValue.constrain(this.minValue,this.maxValue);},afterRender:function(){Ext.slider.MultiSlider.superclass.afterRender.apply(this,arguments);for(var i=0;i<this.thumbs.length;i++){var thumb=this.thumbs[i];if(thumb.value!==undefined){var v=this.normalizeValue(thumb.value);if(v!==thumb.value){this.setValue(i,v,false);}else{this.moveThumb(i,this.translateValue(v),false);}}};},getRatio:function(){var w=this.innerEl.getWidth(),v=this.maxValue-this.minValue;return v==0?w:(w/v);},normalizeValue:function(v){v=this.doSnap(v);v=Ext.util.Format.round(v,this.decimalPrecision);v=v.constrain(this.minValue,this.maxValue);return v;},setMinValue:function(val){this.minValue=val;var i=0,thumbs=this.thumbs,len=thumbs.length,t;for(;i<len;++i){t=thumbs[i];t.value=t.value<val?val:t.value;}
+this.syncThumb();},setMaxValue:function(val){this.maxValue=val;var i=0,thumbs=this.thumbs,len=thumbs.length,t;for(;i<len;++i){t=thumbs[i];t.value=t.value>val?val:t.value;}
+this.syncThumb();},setValue:function(index,v,animate,changeComplete){var thumb=this.thumbs[index],el=thumb.el;v=this.normalizeValue(v);if(v!==thumb.value&&this.fireEvent('beforechange',this,v,thumb.value,thumb)!==false){thumb.value=v;if(this.rendered){this.moveThumb(index,this.translateValue(v),animate!==false);this.fireEvent('change',this,v,thumb);if(changeComplete){this.fireEvent('changecomplete',this,v,thumb);}}}},translateValue:function(v){var ratio=this.getRatio();return(v*ratio)-(this.minValue*ratio)-this.halfThumb;},reverseValue:function(pos){var ratio=this.getRatio();return(pos+(this.minValue*ratio))/ratio;},moveThumb:function(index,v,animate){var thumb=this.thumbs[index].el;if(!animate||this.animate===false){thumb.setLeft(v);}else{thumb.shift({left:v,stopFx:true,duration:.35});}},focus:function(){this.focusEl.focus(10);},onResize:function(w,h){var thumbs=this.thumbs,len=thumbs.length,i=0;for(;i<len;++i){thumbs[i].el.stopFx();}
+if(Ext.isNumber(w)){this.innerEl.setWidth(w-(this.el.getPadding('l')+this.endEl.getPadding('r')));}
+this.syncThumb();Ext.slider.MultiSlider.superclass.onResize.apply(this,arguments);},onDisable:function(){Ext.slider.MultiSlider.superclass.onDisable.call(this);for(var i=0;i<this.thumbs.length;i++){var thumb=this.thumbs[i],el=thumb.el;thumb.disable();if(Ext.isIE){var xy=el.getXY();el.hide();this.innerEl.addClass(this.disabledClass).dom.disabled=true;if(!this.thumbHolder){this.thumbHolder=this.endEl.createChild({cls:'x-slider-thumb '+this.disabledClass});}
+this.thumbHolder.show().setXY(xy);}}},onEnable:function(){Ext.slider.MultiSlider.superclass.onEnable.call(this);for(var i=0;i<this.thumbs.length;i++){var thumb=this.thumbs[i],el=thumb.el;thumb.enable();if(Ext.isIE){this.innerEl.removeClass(this.disabledClass).dom.disabled=false;if(this.thumbHolder)this.thumbHolder.hide();el.show();this.syncThumb();}}},syncThumb:function(){if(this.rendered){for(var i=0;i<this.thumbs.length;i++){this.moveThumb(i,this.translateValue(this.thumbs[i].value));}}},getValue:function(index){return this.thumbs[index].value;},getValues:function(){var values=[];for(var i=0;i<this.thumbs.length;i++){values.push(this.thumbs[i].value);}
+return values;},beforeDestroy:function(){var thumbs=this.thumbs;for(var i=0,len=thumbs.length;i<len;++i){thumbs[i].destroy();thumbs[i]=null;}
+Ext.destroyMembers(this,'endEl','innerEl','focusEl','thumbHolder');Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);}});Ext.reg('multislider',Ext.slider.MultiSlider);Ext.slider.SingleSlider=Ext.extend(Ext.slider.MultiSlider,{constructor:function(config){config=config||{};Ext.applyIf(config,{values:[config.value||0]});Ext.slider.SingleSlider.superclass.constructor.call(this,config);},getValue:function(){return Ext.slider.SingleSlider.superclass.getValue.call(this,0);},setValue:function(value,animate){var args=Ext.toArray(arguments),len=args.length;if(len==1||(len<=3&&typeof arguments[1]!='number')){args.unshift(0);}
+return Ext.slider.SingleSlider.superclass.setValue.apply(this,args);},syncThumb:function(){return Ext.slider.SingleSlider.superclass.syncThumb.apply(this,[0].concat(arguments));},getNearest:function(){return this.thumbs[0];}});Ext.Slider=Ext.slider.SingleSlider;Ext.reg('slider',Ext.slider.SingleSlider);Ext.slider.Vertical={onResize:function(w,h){this.innerEl.setHeight(h-(this.el.getPadding('t')+this.endEl.getPadding('b')));this.syncThumb();},getRatio:function(){var h=this.innerEl.getHeight(),v=this.maxValue-this.minValue;return h/v;},moveThumb:function(index,v,animate){var thumb=this.thumbs[index],el=thumb.el;if(!animate||this.animate===false){el.setBottom(v);}else{el.shift({bottom:v,stopFx:true,duration:.35});}},onClickChange:function(local){if(local.left>this.clickRange[0]&&local.left<this.clickRange[1]){var thumb=this.getNearest(local,'top'),index=thumb.index,value=this.minValue+this.reverseValue(this.innerEl.getHeight()-local.top);this.setValue(index,Ext.util.Format.round(value,this.decimalPrecision),undefined,true);}}};Ext.slider.Thumb.Vertical={getNewValue:function(){var slider=this.slider,innerEl=slider.innerEl,pos=innerEl.translatePoints(this.tracker.getXY()),bottom=innerEl.getHeight()-pos.top;return slider.minValue+Ext.util.Format.round(bottom/slider.getRatio(),slider.decimalPrecision);}};Ext.ProgressBar=Ext.extend(Ext.BoxComponent,{baseCls:'x-progress',animate:false,waitTimer:null,initComponent:function(){Ext.ProgressBar.superclass.initComponent.call(this);this.addEvents("update");},onRender:function(ct,position){var tpl=new Ext.Template('<div class="{cls}-wrap">','<div class="{cls}-inner">','<div class="{cls}-bar">','<div class="{cls}-text">','<div>&#160;</div>','</div>','</div>','<div class="{cls}-text {cls}-text-back">','<div>&#160;</div>','</div>','</div>','</div>');this.el=position?tpl.insertBefore(position,{cls:this.baseCls},true):tpl.append(ct,{cls:this.baseCls},true);if(this.id){this.el.dom.id=this.id;}
+var inner=this.el.dom.firstChild;this.progressBar=Ext.get(inner.firstChild);if(this.textEl){this.textEl=Ext.get(this.textEl);delete this.textTopEl;}else{this.textTopEl=Ext.get(this.progressBar.dom.firstChild);var textBackEl=Ext.get(inner.childNodes[1]);this.textTopEl.setStyle("z-index",99).addClass('x-hidden');this.textEl=new Ext.CompositeElement([this.textTopEl.dom.firstChild,textBackEl.dom.firstChild]);this.textEl.setWidth(inner.offsetWidth);}
+this.progressBar.setHeight(inner.offsetHeight);},afterRender:function(){Ext.ProgressBar.superclass.afterRender.call(this);if(this.value){this.updateProgress(this.value,this.text);}else{this.updateText(this.text);}},updateProgress:function(value,text,animate){this.value=value||0;if(text){this.updateText(text);}
+if(this.rendered&&!this.isDestroyed){var w=Math.floor(value*this.el.dom.firstChild.offsetWidth);this.progressBar.setWidth(w,animate===true||(animate!==false&&this.animate));if(this.textTopEl){this.textTopEl.removeClass('x-hidden').setWidth(w);}}
+this.fireEvent('update',this,value,text);return this;},wait:function(o){if(!this.waitTimer){var scope=this;o=o||{};this.updateText(o.text);this.waitTimer=Ext.TaskMgr.start({run:function(i){var inc=o.increment||10;i-=1;this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01,null,o.animate);},interval:o.interval||1000,duration:o.duration,onStop:function(){if(o.fn){o.fn.apply(o.scope||this);}
+this.reset();},scope:scope});}
+return this;},isWaiting:function(){return this.waitTimer!==null;},updateText:function(text){this.text=text||'&#160;';if(this.rendered){this.textEl.update(this.text);}
+return this;},syncProgressBar:function(){if(this.value){this.updateProgress(this.value,this.text);}
+return this;},setSize:function(w,h){Ext.ProgressBar.superclass.setSize.call(this,w,h);if(this.textTopEl){var inner=this.el.dom.firstChild;this.textEl.setSize(inner.offsetWidth,inner.offsetHeight);}
+this.syncProgressBar();return this;},reset:function(hide){this.updateProgress(0);if(this.textTopEl){this.textTopEl.addClass('x-hidden');}
+this.clearTimer();if(hide===true){this.hide();}
+return this;},clearTimer:function(){if(this.waitTimer){this.waitTimer.onStop=null;Ext.TaskMgr.stop(this.waitTimer);this.waitTimer=null;}},onDestroy:function(){this.clearTimer();if(this.rendered){if(this.textEl.isComposite){this.textEl.clear();}
+Ext.destroyMembers(this,'textEl','progressBar','textTopEl');}
+Ext.ProgressBar.superclass.onDestroy.call(this);}});Ext.reg('progress',Ext.ProgressBar);Ext.DataView=Ext.extend(Ext.BoxComponent,{selectedClass:"x-view-selected",emptyText:"",deferEmptyText:true,trackOver:false,blockRefresh:false,last:false,initComponent:function(){Ext.DataView.superclass.initComponent.call(this);if(Ext.isString(this.tpl)||Ext.isArray(this.tpl)){this.tpl=new Ext.XTemplate(this.tpl);}
+this.addEvents("beforeclick","click","mouseenter","mouseleave","containerclick","dblclick","contextmenu","containercontextmenu","selectionchange","beforeselect");this.store=Ext.StoreMgr.lookup(this.store);this.all=new Ext.CompositeElementLite();this.selected=new Ext.CompositeElementLite();},afterRender:function(){Ext.DataView.superclass.afterRender.call(this);this.mon(this.getTemplateTarget(),{"click":this.onClick,"dblclick":this.onDblClick,"contextmenu":this.onContextMenu,scope:this});if(this.overClass||this.trackOver){this.mon(this.getTemplateTarget(),{"mouseover":this.onMouseOver,"mouseout":this.onMouseOut,scope:this});}
+if(this.store){this.bindStore(this.store,true);}},refresh:function(){this.clearSelections(false,true);var el=this.getTemplateTarget(),records=this.store.getRange();el.update('');if(records.length<1){if(!this.deferEmptyText||this.hasSkippedEmptyText){el.update(this.emptyText);}
+this.all.clear();}else{this.tpl.overwrite(el,this.collectData(records,0));this.all.fill(Ext.query(this.itemSelector,el.dom));this.updateIndexes(0);}
+this.hasSkippedEmptyText=true;},getTemplateTarget:function(){return this.el;},prepareData:function(data){return data;},collectData:function(records,startIndex){var r=[],i=0,len=records.length;for(;i<len;i++){r[r.length]=this.prepareData(records[i].data,startIndex+i,records[i]);}
+return r;},bufferRender:function(records,index){var div=document.createElement('div');this.tpl.overwrite(div,this.collectData(records,index));return Ext.query(this.itemSelector,div);},onUpdate:function(ds,record){var index=this.store.indexOf(record);if(index>-1){var sel=this.isSelected(index),original=this.all.elements[index],node=this.bufferRender([record],index)[0];this.all.replaceElement(index,node,true);if(sel){this.selected.replaceElement(original,node);this.all.item(index).addClass(this.selectedClass);}
+this.updateIndexes(index,index);}},onAdd:function(ds,records,index){if(this.all.getCount()===0){this.refresh();return;}
+var nodes=this.bufferRender(records,index),n,a=this.all.elements;if(index<this.all.getCount()){n=this.all.item(index).insertSibling(nodes,'before',true);a.splice.apply(a,[index,0].concat(nodes));}else{n=this.all.last().insertSibling(nodes,'after',true);a.push.apply(a,nodes);}
+this.updateIndexes(index);},onRemove:function(ds,record,index){this.deselect(index);this.all.removeElement(index,true);this.updateIndexes(index);if(this.store.getCount()===0){this.refresh();}},refreshNode:function(index){this.onUpdate(this.store,this.store.getAt(index));},updateIndexes:function(startIndex,endIndex){var ns=this.all.elements;startIndex=startIndex||0;endIndex=endIndex||((endIndex===0)?0:(ns.length-1));for(var i=startIndex;i<=endIndex;i++){ns[i].viewIndex=i;}},getStore:function(){return this.store;},bindStore:function(store,initial){if(!initial&&this.store){if(store!==this.store&&this.store.autoDestroy){this.store.destroy();}else{this.store.un("beforeload",this.onBeforeLoad,this);this.store.un("datachanged",this.onDataChanged,this);this.store.un("add",this.onAdd,this);this.store.un("remove",this.onRemove,this);this.store.un("update",this.onUpdate,this);this.store.un("clear",this.refresh,this);}
+if(!store){this.store=null;}}
+if(store){store=Ext.StoreMgr.lookup(store);store.on({scope:this,beforeload:this.onBeforeLoad,datachanged:this.onDataChanged,add:this.onAdd,remove:this.onRemove,update:this.onUpdate,clear:this.refresh});}
+this.store=store;if(store){this.refresh();}},onDataChanged:function(){if(this.blockRefresh!==true){this.refresh.apply(this,arguments);}},findItemFromChild:function(node){return Ext.fly(node).findParent(this.itemSelector,this.getTemplateTarget());},onClick:function(e){var item=e.getTarget(this.itemSelector,this.getTemplateTarget()),index;if(item){index=this.indexOf(item);if(this.onItemClick(item,index,e)!==false){this.fireEvent("click",this,index,item,e);}}else{if(this.fireEvent("containerclick",this,e)!==false){this.onContainerClick(e);}}},onContainerClick:function(e){this.clearSelections();},onContextMenu:function(e){var item=e.getTarget(this.itemSelector,this.getTemplateTarget());if(item){this.fireEvent("contextmenu",this,this.indexOf(item),item,e);}else{this.fireEvent("containercontextmenu",this,e);}},onDblClick:function(e){var item=e.getTarget(this.itemSelector,this.getTemplateTarget());if(item){this.fireEvent("dblclick",this,this.indexOf(item),item,e);}},onMouseOver:function(e){var item=e.getTarget(this.itemSelector,this.getTemplateTarget());if(item&&item!==this.lastItem){this.lastItem=item;Ext.fly(item).addClass(this.overClass);this.fireEvent("mouseenter",this,this.indexOf(item),item,e);}},onMouseOut:function(e){if(this.lastItem){if(!e.within(this.lastItem,true,true)){Ext.fly(this.lastItem).removeClass(this.overClass);this.fireEvent("mouseleave",this,this.indexOf(this.lastItem),this.lastItem,e);delete this.lastItem;}}},onItemClick:function(item,index,e){if(this.fireEvent("beforeclick",this,index,item,e)===false){return false;}
+if(this.multiSelect){this.doMultiSelection(item,index,e);e.preventDefault();}else if(this.singleSelect){this.doSingleSelection(item,index,e);e.preventDefault();}
+return true;},doSingleSelection:function(item,index,e){if(e.ctrlKey&&this.isSelected(index)){this.deselect(index);}else{this.select(index,false);}},doMultiSelection:function(item,index,e){if(e.shiftKey&&this.last!==false){var last=this.last;this.selectRange(last,index,e.ctrlKey);this.last=last;}else{if((e.ctrlKey||this.simpleSelect)&&this.isSelected(index)){this.deselect(index);}else{this.select(index,e.ctrlKey||e.shiftKey||this.simpleSelect);}}},getSelectionCount:function(){return this.selected.getCount();},getSelectedNodes:function(){return this.selected.elements;},getSelectedIndexes:function(){var indexes=[],selected=this.selected.elements,i=0,len=selected.length;for(;i<len;i++){indexes.push(selected[i].viewIndex);}
+return indexes;},getSelectedRecords:function(){return this.getRecords(this.selected.elements);},getRecords:function(nodes){var records=[],i=0,len=nodes.length;for(;i<len;i++){records[records.length]=this.store.getAt(nodes[i].viewIndex);}
+return records;},getRecord:function(node){return this.store.getAt(node.viewIndex);},clearSelections:function(suppressEvent,skipUpdate){if((this.multiSelect||this.singleSelect)&&this.selected.getCount()>0){if(!skipUpdate){this.selected.removeClass(this.selectedClass);}
+this.selected.clear();this.last=false;if(!suppressEvent){this.fireEvent("selectionchange",this,this.selected.elements);}}},isSelected:function(node){return this.selected.contains(this.getNode(node));},deselect:function(node){if(this.isSelected(node)){node=this.getNode(node);this.selected.removeElement(node);if(this.last==node.viewIndex){this.last=false;}
+Ext.fly(node).removeClass(this.selectedClass);this.fireEvent("selectionchange",this,this.selected.elements);}},select:function(nodeInfo,keepExisting,suppressEvent){if(Ext.isArray(nodeInfo)){if(!keepExisting){this.clearSelections(true);}
+for(var i=0,len=nodeInfo.length;i<len;i++){this.select(nodeInfo[i],true,true);}
+if(!suppressEvent){this.fireEvent("selectionchange",this,this.selected.elements);}}else{var node=this.getNode(nodeInfo);if(!keepExisting){this.clearSelections(true);}
+if(node&&!this.isSelected(node)){if(this.fireEvent("beforeselect",this,node,this.selected.elements)!==false){Ext.fly(node).addClass(this.selectedClass);this.selected.add(node);this.last=node.viewIndex;if(!suppressEvent){this.fireEvent("selectionchange",this,this.selected.elements);}}}}},selectRange:function(start,end,keepExisting){if(!keepExisting){this.clearSelections(true);}
+this.select(this.getNodes(start,end),true);},getNode:function(nodeInfo){if(Ext.isString(nodeInfo)){return document.getElementById(nodeInfo);}else if(Ext.isNumber(nodeInfo)){return this.all.elements[nodeInfo];}else if(nodeInfo instanceof Ext.data.Record){var idx=this.store.indexOf(nodeInfo);return this.all.elements[idx];}
+return nodeInfo;},getNodes:function(start,end){var ns=this.all.elements,nodes=[],i;start=start||0;end=!Ext.isDefined(end)?Math.max(ns.length-1,0):end;if(start<=end){for(i=start;i<=end&&ns[i];i++){nodes.push(ns[i]);}}else{for(i=start;i>=end&&ns[i];i--){nodes.push(ns[i]);}}
+return nodes;},indexOf:function(node){node=this.getNode(node);if(Ext.isNumber(node.viewIndex)){return node.viewIndex;}
+return this.all.indexOf(node);},onBeforeLoad:function(){if(this.loadingText){this.clearSelections(false,true);this.getTemplateTarget().update('<div class="loading-indicator">'+this.loadingText+'</div>');this.all.clear();}},onDestroy:function(){this.all.clear();this.selected.clear();Ext.DataView.superclass.onDestroy.call(this);this.bindStore(null);}});Ext.DataView.prototype.setStore=Ext.DataView.prototype.bindStore;Ext.reg('dataview',Ext.DataView);Ext.list.ListView=Ext.extend(Ext.DataView,{itemSelector:'dl',selectedClass:'x-list-selected',overClass:'x-list-over',scrollOffset:undefined,columnResize:true,columnSort:true,maxColumnWidth:Ext.isIE?99:100,initComponent:function(){if(this.columnResize){this.colResizer=new Ext.list.ColumnResizer(this.colResizer);this.colResizer.init(this);}
+if(this.columnSort){this.colSorter=new Ext.list.Sorter(this.columnSort);this.colSorter.init(this);}
+if(!this.internalTpl){this.internalTpl=new Ext.XTemplate('<div class="x-list-header"><div class="x-list-header-inner">','<tpl for="columns">','<div style="width:{[values.width*100]}%;text-align:{align};"><em unselectable="on" id="',this.id,'-xlhd-{#}">','{header}','</em></div>','</tpl>','<div class="x-clear"></div>','</div></div>','<div class="x-list-body"><div class="x-list-body-inner">','</div></div>');}
+if(!this.tpl){this.tpl=new Ext.XTemplate('<tpl for="rows">','<dl>','<tpl for="parent.columns">','<dt style="width:{[values.width*100]}%;text-align:{align};">','<em unselectable="on"<tpl if="cls"> class="{cls}</tpl>">','{[values.tpl.apply(parent)]}','</em></dt>','</tpl>','<div class="x-clear"></div>','</dl>','</tpl>');};var cs=this.columns,allocatedWidth=0,colsWithWidth=0,len=cs.length,columns=[];for(var i=0;i<len;i++){var c=cs[i];if(!c.isColumn){c.xtype=c.xtype?(/^lv/.test(c.xtype)?c.xtype:'lv'+c.xtype):'lvcolumn';c=Ext.create(c);}
+if(c.width){allocatedWidth+=c.width*100;if(allocatedWidth>this.maxColumnWidth){c.width-=(allocatedWidth-this.maxColumnWidth)/100;}
+colsWithWidth++;}
+columns.push(c);}
+cs=this.columns=columns;if(colsWithWidth<len){var remaining=len-colsWithWidth;if(allocatedWidth<this.maxColumnWidth){var perCol=((this.maxColumnWidth-allocatedWidth)/remaining)/100;for(var j=0;j<len;j++){var c=cs[j];if(!c.width){c.width=perCol;}}}}
+Ext.list.ListView.superclass.initComponent.call(this);},onRender:function(){this.autoEl={cls:'x-list-wrap'};Ext.list.ListView.superclass.onRender.apply(this,arguments);this.internalTpl.overwrite(this.el,{columns:this.columns});this.innerBody=Ext.get(this.el.dom.childNodes[1].firstChild);this.innerHd=Ext.get(this.el.dom.firstChild.firstChild);if(this.hideHeaders){this.el.dom.firstChild.style.display='none';}},getTemplateTarget:function(){return this.innerBody;},collectData:function(){var rs=Ext.list.ListView.superclass.collectData.apply(this,arguments);return{columns:this.columns,rows:rs};},verifyInternalSize:function(){if(this.lastSize){this.onResize(this.lastSize.width,this.lastSize.height);}},onResize:function(w,h){var body=this.innerBody.dom,header=this.innerHd.dom,scrollWidth=w-Ext.num(this.scrollOffset,Ext.getScrollBarWidth())+'px',parentNode;if(!body){return;}
+parentNode=body.parentNode;if(Ext.isNumber(w)){if(this.reserveScrollOffset||((parentNode.offsetWidth-parentNode.clientWidth)>10)){body.style.width=scrollWidth;header.style.width=scrollWidth;}else{body.style.width=w+'px';header.style.width=w+'px';setTimeout(function(){if((parentNode.offsetWidth-parentNode.clientWidth)>10){body.style.width=scrollWidth;header.style.width=scrollWidth;}},10);}}
+if(Ext.isNumber(h)){parentNode.style.height=Math.max(0,h-header.parentNode.offsetHeight)+'px';}},updateIndexes:function(){Ext.list.ListView.superclass.updateIndexes.apply(this,arguments);this.verifyInternalSize();},findHeaderIndex:function(header){header=header.dom||header;var parentNode=header.parentNode,children=parentNode.parentNode.childNodes,i=0,c;for(;c=children[i];i++){if(c==parentNode){return i;}}
+return-1;},setHdWidths:function(){var els=this.innerHd.dom.getElementsByTagName('div'),i=0,columns=this.columns,len=columns.length;for(;i<len;i++){els[i].style.width=(columns[i].width*100)+'%';}}});Ext.reg('listview',Ext.list.ListView);Ext.ListView=Ext.list.ListView;Ext.list.Column=Ext.extend(Object,{isColumn:true,align:'left',header:'',width:null,cls:'',constructor:function(c){if(!c.tpl){c.tpl=new Ext.XTemplate('{'+c.dataIndex+'}');}
+else if(Ext.isString(c.tpl)){c.tpl=new Ext.XTemplate(c.tpl);}
+Ext.apply(this,c);}});Ext.reg('lvcolumn',Ext.list.Column);Ext.list.NumberColumn=Ext.extend(Ext.list.Column,{format:'0,000.00',constructor:function(c){c.tpl=c.tpl||new Ext.XTemplate('{'+c.dataIndex+':number("'+(c.format||this.format)+'")}');Ext.list.NumberColumn.superclass.constructor.call(this,c);}});Ext.reg('lvnumbercolumn',Ext.list.NumberColumn);Ext.list.DateColumn=Ext.extend(Ext.list.Column,{format:'m/d/Y',constructor:function(c){c.tpl=c.tpl||new Ext.XTemplate('{'+c.dataIndex+':date("'+(c.format||this.format)+'")}');Ext.list.DateColumn.superclass.constructor.call(this,c);}});Ext.reg('lvdatecolumn',Ext.list.DateColumn);Ext.list.BooleanColumn=Ext.extend(Ext.list.Column,{trueText:'true',falseText:'false',undefinedText:'&#160;',constructor:function(c){c.tpl=c.tpl||new Ext.XTemplate('{'+c.dataIndex+':this.format}');var t=this.trueText,f=this.falseText,u=this.undefinedText;c.tpl.format=function(v){if(v===undefined){return u;}
+if(!v||v==='false'){return f;}
+return t;};Ext.list.DateColumn.superclass.constructor.call(this,c);}});Ext.reg('lvbooleancolumn',Ext.list.BooleanColumn);Ext.list.ColumnResizer=Ext.extend(Ext.util.Observable,{minPct:.05,constructor:function(config){Ext.apply(this,config);Ext.list.ColumnResizer.superclass.constructor.call(this);},init:function(listView){this.view=listView;listView.on('render',this.initEvents,this);},initEvents:function(view){view.mon(view.innerHd,'mousemove',this.handleHdMove,this);this.tracker=new Ext.dd.DragTracker({onBeforeStart:this.onBeforeStart.createDelegate(this),onStart:this.onStart.createDelegate(this),onDrag:this.onDrag.createDelegate(this),onEnd:this.onEnd.createDelegate(this),tolerance:3,autoStart:300});this.tracker.initEl(view.innerHd);view.on('beforedestroy',this.tracker.destroy,this.tracker);},handleHdMove:function(e,t){var handleWidth=5,x=e.getPageX(),header=e.getTarget('em',3,true);if(header){var region=header.getRegion(),style=header.dom.style,parentNode=header.dom.parentNode;if(x-region.left<=handleWidth&&parentNode!=parentNode.parentNode.firstChild){this.activeHd=Ext.get(parentNode.previousSibling.firstChild);style.cursor=Ext.isWebKit?'e-resize':'col-resize';}else if(region.right-x<=handleWidth&&parentNode!=parentNode.parentNode.lastChild.previousSibling){this.activeHd=header;style.cursor=Ext.isWebKit?'w-resize':'col-resize';}else{delete this.activeHd;style.cursor='';}}},onBeforeStart:function(e){this.dragHd=this.activeHd;return!!this.dragHd;},onStart:function(e){var me=this,view=me.view,dragHeader=me.dragHd,x=me.tracker.getXY()[0];me.proxy=view.el.createChild({cls:'x-list-resizer'});me.dragX=dragHeader.getX();me.headerIndex=view.findHeaderIndex(dragHeader);me.headersDisabled=view.disableHeaders;view.disableHeaders=true;me.proxy.setHeight(view.el.getHeight());me.proxy.setX(me.dragX);me.proxy.setWidth(x-me.dragX);this.setBoundaries();},setBoundaries:function(relativeX){var view=this.view,headerIndex=this.headerIndex,width=view.innerHd.getWidth(),relativeX=view.innerHd.getX(),minWidth=Math.ceil(width*this.minPct),maxWidth=width-minWidth,numColumns=view.columns.length,headers=view.innerHd.select('em',true),minX=minWidth+relativeX,maxX=maxWidth+relativeX,header;if(numColumns==2){this.minX=minX;this.maxX=maxX;}else{header=headers.item(headerIndex+2);this.minX=headers.item(headerIndex).getX()+minWidth;this.maxX=header?header.getX()-minWidth:maxX;if(headerIndex==0){this.minX=minX;}else if(headerIndex==numColumns-2){this.maxX=maxX;}}},onDrag:function(e){var me=this,cursorX=me.tracker.getXY()[0].constrain(me.minX,me.maxX);me.proxy.setWidth(cursorX-this.dragX);},onEnd:function(e){var newWidth=this.proxy.getWidth(),index=this.headerIndex,view=this.view,columns=view.columns,width=view.innerHd.getWidth(),newPercent=Math.ceil(newWidth*view.maxColumnWidth/width)/100,disabled=this.headersDisabled,headerCol=columns[index],otherCol=columns[index+1],totalPercent=headerCol.width+otherCol.width;this.proxy.remove();headerCol.width=newPercent;otherCol.width=totalPercent-newPercent;delete this.dragHd;view.setHdWidths();view.refresh();setTimeout(function(){view.disableHeaders=disabled;},100);}});Ext.ListView.ColumnResizer=Ext.list.ColumnResizer;Ext.list.Sorter=Ext.extend(Ext.util.Observable,{sortClasses:["sort-asc","sort-desc"],constructor:function(config){Ext.apply(this,config);Ext.list.Sorter.superclass.constructor.call(this);},init:function(listView){this.view=listView;listView.on('render',this.initEvents,this);},initEvents:function(view){view.mon(view.innerHd,'click',this.onHdClick,this);view.innerHd.setStyle('cursor','pointer');view.mon(view.store,'datachanged',this.updateSortState,this);this.updateSortState.defer(10,this,[view.store]);},updateSortState:function(store){var state=store.getSortState();if(!state){return;}
+this.sortState=state;var cs=this.view.columns,sortColumn=-1;for(var i=0,len=cs.length;i<len;i++){if(cs[i].dataIndex==state.field){sortColumn=i;break;}}
+if(sortColumn!=-1){var sortDir=state.direction;this.updateSortIcon(sortColumn,sortDir);}},updateSortIcon:function(col,dir){var sc=this.sortClasses;var hds=this.view.innerHd.select('em').removeClass(sc);hds.item(col).addClass(sc[dir=="DESC"?1:0]);},onHdClick:function(e){var hd=e.getTarget('em',3);if(hd&&!this.view.disableHeaders){var index=this.view.findHeaderIndex(hd);this.view.store.sort(this.view.columns[index].dataIndex);}}});Ext.ListView.Sorter=Ext.list.Sorter;Ext.DataView.LabelEditor=Ext.extend(Ext.Editor,{alignment:"tl-tl",hideEl:false,cls:"x-small-editor",shim:false,completeOnEnter:true,cancelOnEsc:true,labelSelector:'span.x-editable',constructor:function(cfg,field){Ext.DataView.LabelEditor.superclass.constructor.call(this,field||new Ext.form.TextField({allowBlank:false,growMin:90,growMax:240,grow:true,selectOnFocus:true}),cfg);},init:function(view){this.view=view;view.on('render',this.initEditor,this);this.on('complete',this.onSave,this);},initEditor:function(){this.view.on({scope:this,containerclick:this.doBlur,click:this.doBlur});this.view.getEl().on('mousedown',this.onMouseDown,this,{delegate:this.labelSelector});},doBlur:function(){if(this.editing){this.field.blur();}},onMouseDown:function(e,target){if(!e.ctrlKey&&!e.shiftKey){var item=this.view.findItemFromChild(target);e.stopEvent();var record=this.view.store.getAt(this.view.indexOf(item));this.startEdit(target,record.data[this.dataIndex]);this.activeRecord=record;}else{e.preventDefault();}},onSave:function(ed,value){this.activeRecord.set(this.dataIndex,value);}});Ext.DataView.DragSelector=function(cfg){cfg=cfg||{};var view,proxy,tracker;var rs,bodyRegion,dragRegion=new Ext.lib.Region(0,0,0,0);var dragSafe=cfg.dragSafe===true;this.init=function(dataView){view=dataView;view.on('render',onRender);};function fillRegions(){rs=[];view.all.each(function(el){rs[rs.length]=el.getRegion();});bodyRegion=view.el.getRegion();}
+function cancelClick(){return false;}
+function onBeforeStart(e){return!dragSafe||e.target==view.el.dom;}
+function onStart(e){view.on('containerclick',cancelClick,view,{single:true});if(!proxy){proxy=view.el.createChild({cls:'x-view-selector'});}else{if(proxy.dom.parentNode!==view.el.dom){view.el.dom.appendChild(proxy.dom);}
+proxy.setDisplayed('block');}
+fillRegions();view.clearSelections();}
+function onDrag(e){var startXY=tracker.startXY;var xy=tracker.getXY();var x=Math.min(startXY[0],xy[0]);var y=Math.min(startXY[1],xy[1]);var w=Math.abs(startXY[0]-xy[0]);var h=Math.abs(startXY[1]-xy[1]);dragRegion.left=x;dragRegion.top=y;dragRegion.right=x+w;dragRegion.bottom=y+h;dragRegion.constrainTo(bodyRegion);proxy.setRegion(dragRegion);for(var i=0,len=rs.length;i<len;i++){var r=rs[i],sel=dragRegion.intersect(r);if(sel&&!r.selected){r.selected=true;view.select(i,true);}else if(!sel&&r.selected){r.selected=false;view.deselect(i);}}}
+function onEnd(e){if(!Ext.isIE){view.un('containerclick',cancelClick,view);}
+if(proxy){proxy.setDisplayed(false);}}
+function onRender(view){tracker=new Ext.dd.DragTracker({onBeforeStart:onBeforeStart,onStart:onStart,onDrag:onDrag,onEnd:onEnd});tracker.initEl(view.el);}};Ext.data.Api=(function(){var validActions={};return{actions:{create:'create',read:'read',update:'update',destroy:'destroy'},restActions:{create:'POST',read:'GET',update:'PUT',destroy:'DELETE'},isAction:function(action){return(Ext.data.Api.actions[action])?true:false;},getVerb:function(name){if(validActions[name]){return validActions[name];}
+for(var verb in this.actions){if(this.actions[verb]===name){validActions[name]=verb;break;}}
+return(validActions[name]!==undefined)?validActions[name]:null;},isValid:function(api){var invalid=[];var crud=this.actions;for(var action in api){if(!(action in crud)){invalid.push(action);}}
+return(!invalid.length)?true:invalid;},hasUniqueUrl:function(proxy,verb){var url=(proxy.api[verb])?proxy.api[verb].url:null;var unique=true;for(var action in proxy.api){if((unique=(action===verb)?true:(proxy.api[action].url!=url)?true:false)===false){break;}}
+return unique;},prepare:function(proxy){if(!proxy.api){proxy.api={};}
+for(var verb in this.actions){var action=this.actions[verb];proxy.api[action]=proxy.api[action]||proxy.url||proxy.directFn;if(typeof(proxy.api[action])=='string'){proxy.api[action]={url:proxy.api[action],method:(proxy.restful===true)?Ext.data.Api.restActions[action]:undefined};}}},restify:function(proxy){proxy.restful=true;for(var verb in this.restActions){proxy.api[this.actions[verb]].method||(proxy.api[this.actions[verb]].method=this.restActions[verb]);}
+proxy.onWrite=proxy.onWrite.createInterceptor(function(action,o,response,rs){var reader=o.reader;var res=new Ext.data.Response({action:action,raw:response});switch(response.status){case 200:return true;break;case 201:if(Ext.isEmpty(res.raw.responseText)){res.success=true;}else{return true;}
+break;case 204:res.success=true;res.data=null;break;default:return true;break;}
+if(res.success===true){this.fireEvent("write",this,action,res.data,res,rs,o.request.arg);}else{this.fireEvent('exception',this,'remote',action,o,res,rs);}
+o.request.callback.call(o.request.scope,res.data,res,res.success);return false;},proxy);}};})();Ext.data.Response=function(params,response){Ext.apply(this,params,{raw:response});};Ext.data.Response.prototype={message:null,success:false,status:null,root:null,raw:null,getMessage:function(){return this.message;},getSuccess:function(){return this.success;},getStatus:function(){return this.status;},getRoot:function(){return this.root;},getRawResponse:function(){return this.raw;}};Ext.data.Api.Error=Ext.extend(Ext.Error,{constructor:function(message,arg){this.arg=arg;Ext.Error.call(this,message);},name:'Ext.data.Api'});Ext.apply(Ext.data.Api.Error.prototype,{lang:{'action-url-undefined':'No fallback url defined for this action.  When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.','invalid':'received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions','invalid-url':'Invalid url.  Please review your proxy configuration.','execute':'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'}});Ext.data.SortTypes={none:function(s){return s;},stripTagsRE:/<\/?[^>]+>/gi,asText:function(s){return String(s).replace(this.stripTagsRE,"");},asUCText:function(s){return String(s).toUpperCase().replace(this.stripTagsRE,"");},asUCString:function(s){return String(s).toUpperCase();},asDate:function(s){if(!s){return 0;}
+if(Ext.isDate(s)){return s.getTime();}
+return Date.parse(String(s));},asFloat:function(s){var val=parseFloat(String(s).replace(/,/g,""));return isNaN(val)?0:val;},asInt:function(s){var val=parseInt(String(s).replace(/,/g,""),10);return isNaN(val)?0:val;}};Ext.data.Record=function(data,id){this.id=(id||id===0)?id:Ext.data.Record.id(this);this.data=data||{};};Ext.data.Record.create=function(o){var f=Ext.extend(Ext.data.Record,{});var p=f.prototype;p.fields=new Ext.util.MixedCollection(false,function(field){return field.name;});for(var i=0,len=o.length;i<len;i++){p.fields.add(new Ext.data.Field(o[i]));}
+f.getField=function(name){return p.fields.get(name);};return f;};Ext.data.Record.PREFIX='ext-record';Ext.data.Record.AUTO_ID=1;Ext.data.Record.EDIT='edit';Ext.data.Record.REJECT='reject';Ext.data.Record.COMMIT='commit';Ext.data.Record.id=function(rec){rec.phantom=true;return[Ext.data.Record.PREFIX,'-',Ext.data.Record.AUTO_ID++].join('');};Ext.data.Record.prototype={dirty:false,editing:false,error:null,modified:null,phantom:false,join:function(store){this.store=store;},set:function(name,value){var encode=Ext.isPrimitive(value)?String:Ext.encode;if(encode(this.data[name])==encode(value)){return;}
+this.dirty=true;if(!this.modified){this.modified={};}
+if(this.modified[name]===undefined){this.modified[name]=this.data[name];}
+this.data[name]=value;if(!this.editing){this.afterEdit();}},afterEdit:function(){if(this.store!=undefined&&typeof this.store.afterEdit=="function"){this.store.afterEdit(this);}},afterReject:function(){if(this.store){this.store.afterReject(this);}},afterCommit:function(){if(this.store){this.store.afterCommit(this);}},get:function(name){return this.data[name];},beginEdit:function(){this.editing=true;this.modified=this.modified||{};},cancelEdit:function(){this.editing=false;delete this.modified;},endEdit:function(){this.editing=false;if(this.dirty){this.afterEdit();}},reject:function(silent){var m=this.modified;for(var n in m){if(typeof m[n]!="function"){this.data[n]=m[n];}}
+this.dirty=false;delete this.modified;this.editing=false;if(silent!==true){this.afterReject();}},commit:function(silent){this.dirty=false;delete this.modified;this.editing=false;if(silent!==true){this.afterCommit();}},getChanges:function(){var m=this.modified,cs={};for(var n in m){if(m.hasOwnProperty(n)){cs[n]=this.data[n];}}
+return cs;},hasError:function(){return this.error!==null;},clearError:function(){this.error=null;},copy:function(newId){return new this.constructor(Ext.apply({},this.data),newId||this.id);},isModified:function(fieldName){return!!(this.modified&&this.modified.hasOwnProperty(fieldName));},isValid:function(){return this.fields.find(function(f){return(f.allowBlank===false&&Ext.isEmpty(this.data[f.name]))?true:false;},this)?false:true;},markDirty:function(){this.dirty=true;if(!this.modified){this.modified={};}
+this.fields.each(function(f){this.modified[f.name]=this.data[f.name];},this);}};Ext.StoreMgr=Ext.apply(new Ext.util.MixedCollection(),{register:function(){for(var i=0,s;(s=arguments[i]);i++){this.add(s);}},unregister:function(){for(var i=0,s;(s=arguments[i]);i++){this.remove(this.lookup(s));}},lookup:function(id){if(Ext.isArray(id)){var fields=['field1'],expand=!Ext.isArray(id[0]);if(!expand){for(var i=2,len=id[0].length;i<=len;++i){fields.push('field'+i);}}
+return new Ext.data.ArrayStore({fields:fields,data:id,expandData:expand,autoDestroy:true,autoCreated:true});}
+return Ext.isObject(id)?(id.events?id:Ext.create(id,'store')):this.get(id);},getKey:function(o){return o.storeId;}});Ext.data.Store=Ext.extend(Ext.util.Observable,{writer:undefined,remoteSort:false,autoDestroy:false,pruneModifiedRecords:false,lastOptions:null,autoSave:true,batch:true,restful:false,paramNames:undefined,defaultParamNames:{start:'start',limit:'limit',sort:'sort',dir:'dir'},isDestroyed:false,hasMultiSort:false,batchKey:'_ext_batch_',constructor:function(config){this.data=new Ext.util.MixedCollection(false);this.data.getKey=function(o){return o.id;};this.removed=[];if(config&&config.data){this.inlineData=config.data;delete config.data;}
+Ext.apply(this,config);this.baseParams=Ext.isObject(this.baseParams)?this.baseParams:{};this.paramNames=Ext.applyIf(this.paramNames||{},this.defaultParamNames);if((this.url||this.api)&&!this.proxy){this.proxy=new Ext.data.HttpProxy({url:this.url,api:this.api});}
+if(this.restful===true&&this.proxy){this.batch=false;Ext.data.Api.restify(this.proxy);}
+if(this.reader){if(!this.recordType){this.recordType=this.reader.recordType;}
+if(this.reader.onMetaChange){this.reader.onMetaChange=this.reader.onMetaChange.createSequence(this.onMetaChange,this);}
+if(this.writer){if(this.writer instanceof(Ext.data.DataWriter)===false){this.writer=this.buildWriter(this.writer);}
+this.writer.meta=this.reader.meta;this.pruneModifiedRecords=true;}}
+if(this.recordType){this.fields=this.recordType.prototype.fields;}
+this.modified=[];this.addEvents('datachanged','metachange','add','remove','update','clear','exception','beforeload','load','loadexception','beforewrite','write','beforesave','save');if(this.proxy){this.relayEvents(this.proxy,['loadexception','exception']);}
+if(this.writer){this.on({scope:this,add:this.createRecords,remove:this.destroyRecord,update:this.updateRecord,clear:this.onClear});}
+this.sortToggle={};if(this.sortField){this.setDefaultSort(this.sortField,this.sortDir);}else if(this.sortInfo){this.setDefaultSort(this.sortInfo.field,this.sortInfo.direction);}
+Ext.data.Store.superclass.constructor.call(this);if(this.id){this.storeId=this.id;delete this.id;}
+if(this.storeId){Ext.StoreMgr.register(this);}
+if(this.inlineData){this.loadData(this.inlineData);delete this.inlineData;}else if(this.autoLoad){this.load.defer(10,this,[typeof this.autoLoad=='object'?this.autoLoad:undefined]);}
+this.batchCounter=0;this.batches={};},buildWriter:function(config){var klass=undefined,type=(config.format||'json').toLowerCase();switch(type){case'json':klass=Ext.data.JsonWriter;break;case'xml':klass=Ext.data.XmlWriter;break;default:klass=Ext.data.JsonWriter;}
+return new klass(config);},destroy:function(){if(!this.isDestroyed){if(this.storeId){Ext.StoreMgr.unregister(this);}
+this.clearData();this.data=null;Ext.destroy(this.proxy);this.reader=this.writer=null;this.purgeListeners();this.isDestroyed=true;}},add:function(records){var i,len,record,index;records=[].concat(records);if(records.length<1){return;}
+for(i=0,len=records.length;i<len;i++){record=records[i];record.join(this);if(record.dirty||record.phantom){this.modified.push(record);}}
+index=this.data.length;this.data.addAll(records);if(this.snapshot){this.snapshot.addAll(records);}
+this.fireEvent('add',this,records,index);},addSorted:function(record){var index=this.findInsertIndex(record);this.insert(index,record);},doUpdate:function(rec){this.data.replace(rec.id,rec);if(this.snapshot){this.snapshot.replace(rec.id,rec);}
+this.fireEvent('update',this,rec,Ext.data.Record.COMMIT);},remove:function(record){if(Ext.isArray(record)){Ext.each(record,function(r){this.remove(r);},this);return;}
+var index=this.data.indexOf(record);if(index>-1){record.join(null);this.data.removeAt(index);}
+if(this.pruneModifiedRecords){this.modified.remove(record);}
+if(this.snapshot){this.snapshot.remove(record);}
+if(index>-1){this.fireEvent('remove',this,record,index);}},removeAt:function(index){this.remove(this.getAt(index));},removeAll:function(silent){var items=[];this.each(function(rec){items.push(rec);});this.clearData();if(this.snapshot){this.snapshot.clear();}
+if(this.pruneModifiedRecords){this.modified=[];}
+if(silent!==true){this.fireEvent('clear',this,items);}},onClear:function(store,records){Ext.each(records,function(rec,index){this.destroyRecord(this,rec,index);},this);},insert:function(index,records){var i,len,record;records=[].concat(records);for(i=0,len=records.length;i<len;i++){record=records[i];this.data.insert(index+i,record);record.join(this);if(record.dirty||record.phantom){this.modified.push(record);}}
+if(this.snapshot){this.snapshot.addAll(records);}
+this.fireEvent('add',this,records,index);},indexOf:function(record){return this.data.indexOf(record);},indexOfId:function(id){return this.data.indexOfKey(id);},getById:function(id){return(this.snapshot||this.data).key(id);},getAt:function(index){return this.data.itemAt(index);},getRange:function(start,end){return this.data.getRange(start,end);},storeOptions:function(o){o=Ext.apply({},o);delete o.callback;delete o.scope;this.lastOptions=o;},clearData:function(){this.data.each(function(rec){rec.join(null);});this.data.clear();},load:function(options){options=Ext.apply({},options);this.storeOptions(options);if(this.sortInfo&&this.remoteSort){var pn=this.paramNames;options.params=Ext.apply({},options.params);options.params[pn.sort]=this.sortInfo.field;options.params[pn.dir]=this.sortInfo.direction;}
+try{return this.execute('read',null,options);}catch(e){this.handleException(e);return false;}},updateRecord:function(store,record,action){if(action==Ext.data.Record.EDIT&&this.autoSave===true&&(!record.phantom||(record.phantom&&record.isValid()))){this.save();}},createRecords:function(store,records,index){var modified=this.modified,length=records.length,record,i;for(i=0;i<length;i++){record=records[i];if(record.phantom&&record.isValid()){record.markDirty();if(modified.indexOf(record)==-1){modified.push(record);}}}
+if(this.autoSave===true){this.save();}},destroyRecord:function(store,record,index){if(this.modified.indexOf(record)!=-1){this.modified.remove(record);}
+if(!record.phantom){this.removed.push(record);record.lastIndex=index;if(this.autoSave===true){this.save();}}},execute:function(action,rs,options,batch){if(!Ext.data.Api.isAction(action)){throw new Ext.data.Api.Error('execute',action);}
+options=Ext.applyIf(options||{},{params:{}});if(batch!==undefined){this.addToBatch(batch);}
+var doRequest=true;if(action==='read'){doRequest=this.fireEvent('beforeload',this,options);Ext.applyIf(options.params,this.baseParams);}
+else{if(this.writer.listful===true&&this.restful!==true){rs=(Ext.isArray(rs))?rs:[rs];}
+else if(Ext.isArray(rs)&&rs.length==1){rs=rs.shift();}
+if((doRequest=this.fireEvent('beforewrite',this,action,rs,options))!==false){this.writer.apply(options.params,this.baseParams,action,rs);}}
+if(doRequest!==false){if(this.writer&&this.proxy.url&&!this.proxy.restful&&!Ext.data.Api.hasUniqueUrl(this.proxy,action)){options.params.xaction=action;}
+this.proxy.request(Ext.data.Api.actions[action],rs,options.params,this.reader,this.createCallback(action,rs,batch),this,options);}
+return doRequest;},save:function(){if(!this.writer){throw new Ext.data.Store.Error('writer-undefined');}
+var queue=[],len,trans,batch,data={},i;if(this.removed.length){queue.push(['destroy',this.removed]);}
+var rs=[].concat(this.getModifiedRecords());if(rs.length){var phantoms=[];for(i=rs.length-1;i>=0;i--){if(rs[i].phantom===true){var rec=rs.splice(i,1).shift();if(rec.isValid()){phantoms.push(rec);}}else if(!rs[i].isValid()){rs.splice(i,1);}}
+if(phantoms.length){queue.push(['create',phantoms]);}
+if(rs.length){queue.push(['update',rs]);}}
+len=queue.length;if(len){batch=++this.batchCounter;for(i=0;i<len;++i){trans=queue[i];data[trans[0]]=trans[1];}
+if(this.fireEvent('beforesave',this,data)!==false){for(i=0;i<len;++i){trans=queue[i];this.doTransaction(trans[0],trans[1],batch);}
+return batch;}}
+return-1;},doTransaction:function(action,rs,batch){function transaction(records){try{this.execute(action,records,undefined,batch);}catch(e){this.handleException(e);}}
+if(this.batch===false){for(var i=0,len=rs.length;i<len;i++){transaction.call(this,rs[i]);}}else{transaction.call(this,rs);}},addToBatch:function(batch){var b=this.batches,key=this.batchKey+batch,o=b[key];if(!o){b[key]=o={id:batch,count:0,data:{}};}
+++o.count;},removeFromBatch:function(batch,action,data){var b=this.batches,key=this.batchKey+batch,o=b[key],arr;if(o){arr=o.data[action]||[];o.data[action]=arr.concat(data);if(o.count===1){data=o.data;delete b[key];this.fireEvent('save',this,batch,data);}else{--o.count;}}},createCallback:function(action,rs,batch){var actions=Ext.data.Api.actions;return(action=='read')?this.loadRecords:function(data,response,success){this['on'+Ext.util.Format.capitalize(action)+'Records'](success,rs,[].concat(data));if(success===true){this.fireEvent('write',this,action,data,response,rs);}
+this.removeFromBatch(batch,action,data);};},clearModified:function(rs){if(Ext.isArray(rs)){for(var n=rs.length-1;n>=0;n--){this.modified.splice(this.modified.indexOf(rs[n]),1);}}else{this.modified.splice(this.modified.indexOf(rs),1);}},reMap:function(record){if(Ext.isArray(record)){for(var i=0,len=record.length;i<len;i++){this.reMap(record[i]);}}else{delete this.data.map[record._phid];this.data.map[record.id]=record;var index=this.data.keys.indexOf(record._phid);this.data.keys.splice(index,1,record.id);delete record._phid;}},onCreateRecords:function(success,rs,data){if(success===true){try{this.reader.realize(rs,data);this.reMap(rs);}
+catch(e){this.handleException(e);if(Ext.isArray(rs)){this.onCreateRecords(success,rs,data);}}}},onUpdateRecords:function(success,rs,data){if(success===true){try{this.reader.update(rs,data);}catch(e){this.handleException(e);if(Ext.isArray(rs)){this.onUpdateRecords(success,rs,data);}}}},onDestroyRecords:function(success,rs,data){rs=(rs instanceof Ext.data.Record)?[rs]:[].concat(rs);for(var i=0,len=rs.length;i<len;i++){this.removed.splice(this.removed.indexOf(rs[i]),1);}
+if(success===false){for(i=rs.length-1;i>=0;i--){this.insert(rs[i].lastIndex,rs[i]);}}},handleException:function(e){Ext.handleError(e);},reload:function(options){this.load(Ext.applyIf(options||{},this.lastOptions));},loadRecords:function(o,options,success){var i,len;if(this.isDestroyed===true){return;}
+if(!o||success===false){if(success!==false){this.fireEvent('load',this,[],options);}
+if(options.callback){options.callback.call(options.scope||this,[],options,false,o);}
+return;}
+var r=o.records,t=o.totalRecords||r.length;if(!options||options.add!==true){if(this.pruneModifiedRecords){this.modified=[];}
+for(i=0,len=r.length;i<len;i++){r[i].join(this);}
+if(this.snapshot){this.data=this.snapshot;delete this.snapshot;}
+this.clearData();this.data.addAll(r);this.totalLength=t;this.applySort();this.fireEvent('datachanged',this);}else{var toAdd=[],rec,cnt=0;for(i=0,len=r.length;i<len;++i){rec=r[i];if(this.indexOfId(rec.id)>-1){this.doUpdate(rec);}else{toAdd.push(rec);++cnt;}}
+this.totalLength=Math.max(t,this.data.length+cnt);this.add(toAdd);}
+this.fireEvent('load',this,r,options);if(options.callback){options.callback.call(options.scope||this,r,options,true);}},loadData:function(o,append){var r=this.reader.readRecords(o);this.loadRecords(r,{add:append},true);},getCount:function(){return this.data.length||0;},getTotalCount:function(){return this.totalLength||0;},getSortState:function(){return this.sortInfo;},applySort:function(){if((this.sortInfo||this.multiSortInfo)&&!this.remoteSort){this.sortData();}},sortData:function(){var sortInfo=this.hasMultiSort?this.multiSortInfo:this.sortInfo,direction=sortInfo.direction||"ASC",sorters=sortInfo.sorters,sortFns=[];if(!this.hasMultiSort){sorters=[{direction:direction,field:sortInfo.field}];}
+for(var i=0,j=sorters.length;i<j;i++){sortFns.push(this.createSortFunction(sorters[i].field,sorters[i].direction));}
+if(sortFns.length==0){return;}
+var directionModifier=direction.toUpperCase()=="DESC"?-1:1;var fn=function(r1,r2){var result=sortFns[0].call(this,r1,r2);if(sortFns.length>1){for(var i=1,j=sortFns.length;i<j;i++){result=result||sortFns[i].call(this,r1,r2);}}
+return directionModifier*result;};this.data.sort(direction,fn);if(this.snapshot&&this.snapshot!=this.data){this.snapshot.sort(direction,fn);}},createSortFunction:function(field,direction){direction=direction||"ASC";var directionModifier=direction.toUpperCase()=="DESC"?-1:1;var sortType=this.fields.get(field).sortType;return function(r1,r2){var v1=sortType(r1.data[field]),v2=sortType(r2.data[field]);return directionModifier*(v1>v2?1:(v1<v2?-1:0));};},setDefaultSort:function(field,dir){dir=dir?dir.toUpperCase():'ASC';this.sortInfo={field:field,direction:dir};this.sortToggle[field]=dir;},sort:function(fieldName,dir){if(Ext.isArray(arguments[0])){return this.multiSort.call(this,fieldName,dir);}else{return this.singleSort(fieldName,dir);}},singleSort:function(fieldName,dir){var field=this.fields.get(fieldName);if(!field){return false;}
+var name=field.name,sortInfo=this.sortInfo||null,sortToggle=this.sortToggle?this.sortToggle[name]:null;if(!dir){if(sortInfo&&sortInfo.field==name){dir=(this.sortToggle[name]||'ASC').toggle('ASC','DESC');}else{dir=field.sortDir;}}
+this.sortToggle[name]=dir;this.sortInfo={field:name,direction:dir};this.hasMultiSort=false;if(this.remoteSort){if(!this.load(this.lastOptions)){if(sortToggle){this.sortToggle[name]=sortToggle;}
+if(sortInfo){this.sortInfo=sortInfo;}}}else{this.applySort();this.fireEvent('datachanged',this);}
+return true;},multiSort:function(sorters,direction){this.hasMultiSort=true;direction=direction||"ASC";if(this.multiSortInfo&&direction==this.multiSortInfo.direction){direction=direction.toggle("ASC","DESC");}
+this.multiSortInfo={sorters:sorters,direction:direction};if(this.remoteSort){this.singleSort(sorters[0].field,sorters[0].direction);}else{this.applySort();this.fireEvent('datachanged',this);}},each:function(fn,scope){this.data.each(fn,scope);},getModifiedRecords:function(){return this.modified;},sum:function(property,start,end){var rs=this.data.items,v=0;start=start||0;end=(end||end===0)?end:rs.length-1;for(var i=start;i<=end;i++){v+=(rs[i].data[property]||0);}
+return v;},createFilterFn:function(property,value,anyMatch,caseSensitive,exactMatch){if(Ext.isEmpty(value,false)){return false;}
+value=this.data.createValueMatcher(value,anyMatch,caseSensitive,exactMatch);return function(r){return value.test(r.data[property]);};},createMultipleFilterFn:function(filters){return function(record){var isMatch=true;for(var i=0,j=filters.length;i<j;i++){var filter=filters[i],fn=filter.fn,scope=filter.scope;isMatch=isMatch&&fn.call(scope,record);}
+return isMatch;};},filter:function(property,value,anyMatch,caseSensitive,exactMatch){var fn;if(Ext.isObject(property)){property=[property];}
+if(Ext.isArray(property)){var filters=[];for(var i=0,j=property.length;i<j;i++){var filter=property[i],func=filter.fn,scope=filter.scope||this;if(!Ext.isFunction(func)){func=this.createFilterFn(filter.property,filter.value,filter.anyMatch,filter.caseSensitive,filter.exactMatch);}
+filters.push({fn:func,scope:scope});}
+fn=this.createMultipleFilterFn(filters);}else{fn=this.createFilterFn(property,value,anyMatch,caseSensitive,exactMatch);}
+return fn?this.filterBy(fn):this.clearFilter();},filterBy:function(fn,scope){this.snapshot=this.snapshot||this.data;this.data=this.queryBy(fn,scope||this);this.fireEvent('datachanged',this);},clearFilter:function(suppressEvent){if(this.isFiltered()){this.data=this.snapshot;delete this.snapshot;if(suppressEvent!==true){this.fireEvent('datachanged',this);}}},isFiltered:function(){return!!this.snapshot&&this.snapshot!=this.data;},query:function(property,value,anyMatch,caseSensitive){var fn=this.createFilterFn(property,value,anyMatch,caseSensitive);return fn?this.queryBy(fn):this.data.clone();},queryBy:function(fn,scope){var data=this.snapshot||this.data;return data.filterBy(fn,scope||this);},find:function(property,value,start,anyMatch,caseSensitive){var fn=this.createFilterFn(property,value,anyMatch,caseSensitive);return fn?this.data.findIndexBy(fn,null,start):-1;},findExact:function(property,value,start){return this.data.findIndexBy(function(rec){return rec.get(property)===value;},this,start);},findBy:function(fn,scope,start){return this.data.findIndexBy(fn,scope,start);},collect:function(dataIndex,allowNull,bypassFilter){var d=(bypassFilter===true&&this.snapshot)?this.snapshot.items:this.data.items;var v,sv,r=[],l={};for(var i=0,len=d.length;i<len;i++){v=d[i].data[dataIndex];sv=String(v);if((allowNull||!Ext.isEmpty(v))&&!l[sv]){l[sv]=true;r[r.length]=v;}}
+return r;},afterEdit:function(record){if(this.modified.indexOf(record)==-1){this.modified.push(record);}
+this.fireEvent('update',this,record,Ext.data.Record.EDIT);},afterReject:function(record){this.modified.remove(record);this.fireEvent('update',this,record,Ext.data.Record.REJECT);},afterCommit:function(record){this.modified.remove(record);this.fireEvent('update',this,record,Ext.data.Record.COMMIT);},commitChanges:function(){var modified=this.modified.slice(0),length=modified.length,i;for(i=0;i<length;i++){modified[i].commit();}
+this.modified=[];this.removed=[];},rejectChanges:function(){var modified=this.modified.slice(0),removed=this.removed.slice(0).reverse(),mLength=modified.length,rLength=removed.length,i;for(i=0;i<mLength;i++){modified[i].reject();}
+for(i=0;i<rLength;i++){this.insert(removed[i].lastIndex||0,removed[i]);removed[i].reject();}
+this.modified=[];this.removed=[];},onMetaChange:function(meta){this.recordType=this.reader.recordType;this.fields=this.recordType.prototype.fields;delete this.snapshot;if(this.reader.meta.sortInfo){this.sortInfo=this.reader.meta.sortInfo;}else if(this.sortInfo&&!this.fields.get(this.sortInfo.field)){delete this.sortInfo;}
+if(this.writer){this.writer.meta=this.reader.meta;}
+this.modified=[];this.fireEvent('metachange',this,this.reader.meta);},findInsertIndex:function(record){this.suspendEvents();var data=this.data.clone();this.data.add(record);this.applySort();var index=this.data.indexOf(record);this.data=data;this.resumeEvents();return index;},setBaseParam:function(name,value){this.baseParams=this.baseParams||{};this.baseParams[name]=value;}});Ext.reg('store',Ext.data.Store);Ext.data.Store.Error=Ext.extend(Ext.Error,{name:'Ext.data.Store'});Ext.apply(Ext.data.Store.Error.prototype,{lang:{'writer-undefined':'Attempted to execute a write-action without a DataWriter installed.'}});Ext.data.Field=Ext.extend(Object,{constructor:function(config){if(Ext.isString(config)){config={name:config};}
+Ext.apply(this,config);var types=Ext.data.Types,st=this.sortType,t;if(this.type){if(Ext.isString(this.type)){this.type=Ext.data.Types[this.type.toUpperCase()]||types.AUTO;}}else{this.type=types.AUTO;}
+if(Ext.isString(st)){this.sortType=Ext.data.SortTypes[st];}else if(Ext.isEmpty(st)){this.sortType=this.type.sortType;}
+if(!this.convert){this.convert=this.type.convert;}},dateFormat:null,useNull:false,defaultValue:"",mapping:null,sortType:null,sortDir:"ASC",allowBlank:true});Ext.data.DataReader=function(meta,recordType){this.meta=meta;this.recordType=Ext.isArray(recordType)?Ext.data.Record.create(recordType):recordType;if(this.recordType){this.buildExtractors();}};Ext.data.DataReader.prototype={getTotal:Ext.emptyFn,getRoot:Ext.emptyFn,getMessage:Ext.emptyFn,getSuccess:Ext.emptyFn,getId:Ext.emptyFn,buildExtractors:Ext.emptyFn,extractValues:Ext.emptyFn,realize:function(rs,data){if(Ext.isArray(rs)){for(var i=rs.length-1;i>=0;i--){if(Ext.isArray(data)){this.realize(rs.splice(i,1).shift(),data.splice(i,1).shift());}
+else{this.realize(rs.splice(i,1).shift(),data);}}}
+else{if(Ext.isArray(data)&&data.length==1){data=data.shift();}
+if(!this.isData(data)){throw new Ext.data.DataReader.Error('realize',rs);}
+rs.phantom=false;rs._phid=rs.id;rs.id=this.getId(data);rs.data=data;rs.commit();}},update:function(rs,data){if(Ext.isArray(rs)){for(var i=rs.length-1;i>=0;i--){if(Ext.isArray(data)){this.update(rs.splice(i,1).shift(),data.splice(i,1).shift());}
+else{this.update(rs.splice(i,1).shift(),data);}}}
+else{if(Ext.isArray(data)&&data.length==1){data=data.shift();}
+if(this.isData(data)){rs.data=Ext.apply(rs.data,data);}
+rs.commit();}},extractData:function(root,returnRecords){var rawName=(this instanceof Ext.data.JsonReader)?'json':'node';var rs=[];if(this.isData(root)&&!(this instanceof Ext.data.XmlReader)){root=[root];}
+var f=this.recordType.prototype.fields,fi=f.items,fl=f.length,rs=[];if(returnRecords===true){var Record=this.recordType;for(var i=0;i<root.length;i++){var n=root[i];var record=new Record(this.extractValues(n,fi,fl),this.getId(n));record[rawName]=n;rs.push(record);}}
+else{for(var i=0;i<root.length;i++){var data=this.extractValues(root[i],fi,fl);data[this.meta.idProperty]=this.getId(root[i]);rs.push(data);}}
+return rs;},isData:function(data){return(data&&Ext.isObject(data)&&!Ext.isEmpty(this.getId(data)))?true:false;},onMetaChange:function(meta){delete this.ef;this.meta=meta;this.recordType=Ext.data.Record.create(meta.fields);this.buildExtractors();}};Ext.data.DataReader.Error=Ext.extend(Ext.Error,{constructor:function(message,arg){this.arg=arg;Ext.Error.call(this,message);},name:'Ext.data.DataReader'});Ext.apply(Ext.data.DataReader.Error.prototype,{lang:{'update':"#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",'realize':"#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",'invalid-response':"#readResponse received an invalid response from the server."}});Ext.data.DataWriter=function(config){Ext.apply(this,config);};Ext.data.DataWriter.prototype={writeAllFields:false,listful:false,apply:function(params,baseParams,action,rs){var data=[],renderer=action+'Record';if(Ext.isArray(rs)){Ext.each(rs,function(rec){data.push(this[renderer](rec));},this);}
+else if(rs instanceof Ext.data.Record){data=this[renderer](rs);}
+this.render(params,baseParams,data);},render:Ext.emptyFn,updateRecord:Ext.emptyFn,createRecord:Ext.emptyFn,destroyRecord:Ext.emptyFn,toHash:function(rec,config){var map=rec.fields.map,data={},raw=(this.writeAllFields===false&&rec.phantom===false)?rec.getChanges():rec.data,m;Ext.iterate(raw,function(prop,value){if((m=map[prop])){data[m.mapping?m.mapping:m.name]=value;}});if(rec.phantom){if(rec.fields.containsKey(this.meta.idProperty)&&Ext.isEmpty(rec.data[this.meta.idProperty])){delete data[this.meta.idProperty];}}else{data[this.meta.idProperty]=rec.id;}
+return data;},toArray:function(data){var fields=[];Ext.iterate(data,function(k,v){fields.push({name:k,value:v});},this);return fields;}};Ext.data.DataProxy=function(conn){conn=conn||{};this.api=conn.api;this.url=conn.url;this.restful=conn.restful;this.listeners=conn.listeners;this.prettyUrls=conn.prettyUrls;this.addEvents('exception','beforeload','load','loadexception','beforewrite','write');Ext.data.DataProxy.superclass.constructor.call(this);try{Ext.data.Api.prepare(this);}catch(e){if(e instanceof Ext.data.Api.Error){e.toConsole();}}
+Ext.data.DataProxy.relayEvents(this,['beforewrite','write','exception']);};Ext.extend(Ext.data.DataProxy,Ext.util.Observable,{restful:false,setApi:function(){if(arguments.length==1){var valid=Ext.data.Api.isValid(arguments[0]);if(valid===true){this.api=arguments[0];}
+else{throw new Ext.data.Api.Error('invalid',valid);}}
+else if(arguments.length==2){if(!Ext.data.Api.isAction(arguments[0])){throw new Ext.data.Api.Error('invalid',arguments[0]);}
+this.api[arguments[0]]=arguments[1];}
+Ext.data.Api.prepare(this);},isApiAction:function(action){return(this.api[action])?true:false;},request:function(action,rs,params,reader,callback,scope,options){if(!this.api[action]&&!this.load){throw new Ext.data.DataProxy.Error('action-undefined',action);}
+params=params||{};if((action===Ext.data.Api.actions.read)?this.fireEvent("beforeload",this,params):this.fireEvent("beforewrite",this,action,rs,params)!==false){this.doRequest.apply(this,arguments);}
+else{callback.call(scope||this,null,options,false);}},load:null,doRequest:function(action,rs,params,reader,callback,scope,options){this.load(params,reader,callback,scope,options);},onRead:Ext.emptyFn,onWrite:Ext.emptyFn,buildUrl:function(action,record){record=record||null;var url=(this.conn&&this.conn.url)?this.conn.url:(this.api[action])?this.api[action].url:this.url;if(!url){throw new Ext.data.Api.Error('invalid-url',action);}
+var provides=null;var m=url.match(/(.*)(\.json|\.xml|\.html)$/);if(m){provides=m[2];url=m[1];}
+if((this.restful===true||this.prettyUrls===true)&&record instanceof Ext.data.Record&&!record.phantom){url+='/'+record.id;}
+return(provides===null)?url:url+provides;},destroy:function(){this.purgeListeners();}});Ext.apply(Ext.data.DataProxy,Ext.util.Observable.prototype);Ext.util.Observable.call(Ext.data.DataProxy);Ext.data.DataProxy.Error=Ext.extend(Ext.Error,{constructor:function(message,arg){this.arg=arg;Ext.Error.call(this,message);},name:'Ext.data.DataProxy'});Ext.apply(Ext.data.DataProxy.Error.prototype,{lang:{'action-undefined':"DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.",'api-invalid':'Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'}});Ext.data.Request=function(params){Ext.apply(this,params);};Ext.data.Request.prototype={action:undefined,rs:undefined,params:undefined,callback:Ext.emptyFn,scope:undefined,reader:undefined};Ext.data.Response=function(params){Ext.apply(this,params);};Ext.data.Response.prototype={action:undefined,success:undefined,message:undefined,data:undefined,raw:undefined,records:undefined};Ext.data.ScriptTagProxy=function(config){Ext.apply(this,config);Ext.data.ScriptTagProxy.superclass.constructor.call(this,config);this.head=document.getElementsByTagName("head")[0];};Ext.data.ScriptTagProxy.TRANS_ID=1000;Ext.extend(Ext.data.ScriptTagProxy,Ext.data.DataProxy,{timeout:30000,callbackParam:"callback",nocache:true,doRequest:function(action,rs,params,reader,callback,scope,arg){var p=Ext.urlEncode(Ext.apply(params,this.extraParams));var url=this.buildUrl(action,rs);if(!url){throw new Ext.data.Api.Error('invalid-url',url);}
+url=Ext.urlAppend(url,p);if(this.nocache){url=Ext.urlAppend(url,'_dc='+(new Date().getTime()));}
+var transId=++Ext.data.ScriptTagProxy.TRANS_ID;var trans={id:transId,action:action,cb:"stcCallback"+transId,scriptId:"stcScript"+transId,params:params,arg:arg,url:url,callback:callback,scope:scope,reader:reader};window[trans.cb]=this.createCallback(action,rs,trans);url+=String.format("&{0}={1}",this.callbackParam,trans.cb);if(this.autoAbort!==false){this.abort();}
+trans.timeoutId=this.handleFailure.defer(this.timeout,this,[trans]);var script=document.createElement("script");script.setAttribute("src",url);script.setAttribute("type","text/javascript");script.setAttribute("id",trans.scriptId);this.head.appendChild(script);this.trans=trans;},createCallback:function(action,rs,trans){var self=this;return function(res){self.trans=false;self.destroyTrans(trans,true);if(action===Ext.data.Api.actions.read){self.onRead.call(self,action,trans,res);}else{self.onWrite.call(self,action,trans,res,rs);}};},onRead:function(action,trans,res){var result;try{result=trans.reader.readRecords(res);}catch(e){this.fireEvent("loadexception",this,trans,res,e);this.fireEvent('exception',this,'response',action,trans,res,e);trans.callback.call(trans.scope||window,null,trans.arg,false);return;}
+if(result.success===false){this.fireEvent('loadexception',this,trans,res);this.fireEvent('exception',this,'remote',action,trans,res,null);}else{this.fireEvent("load",this,res,trans.arg);}
+trans.callback.call(trans.scope||window,result,trans.arg,result.success);},onWrite:function(action,trans,response,rs){var reader=trans.reader;try{var res=reader.readResponse(action,response);}catch(e){this.fireEvent('exception',this,'response',action,trans,res,e);trans.callback.call(trans.scope||window,null,res,false);return;}
+if(!res.success===true){this.fireEvent('exception',this,'remote',action,trans,res,rs);trans.callback.call(trans.scope||window,null,res,false);return;}
+this.fireEvent("write",this,action,res.data,res,rs,trans.arg);trans.callback.call(trans.scope||window,res.data,res,true);},isLoading:function(){return this.trans?true:false;},abort:function(){if(this.isLoading()){this.destroyTrans(this.trans);}},destroyTrans:function(trans,isLoaded){this.head.removeChild(document.getElementById(trans.scriptId));clearTimeout(trans.timeoutId);if(isLoaded){window[trans.cb]=undefined;try{delete window[trans.cb];}catch(e){}}else{window[trans.cb]=function(){window[trans.cb]=undefined;try{delete window[trans.cb];}catch(e){}};}},handleFailure:function(trans){this.trans=false;this.destroyTrans(trans,false);if(trans.action===Ext.data.Api.actions.read){this.fireEvent("loadexception",this,null,trans.arg);}
+this.fireEvent('exception',this,'response',trans.action,{response:null,options:trans.arg});trans.callback.call(trans.scope||window,null,trans.arg,false);},destroy:function(){this.abort();Ext.data.ScriptTagProxy.superclass.destroy.call(this);}});Ext.data.HttpProxy=function(conn){Ext.data.HttpProxy.superclass.constructor.call(this,conn);this.conn=conn;this.conn.url=null;this.useAjax=!conn||!conn.events;var actions=Ext.data.Api.actions;this.activeRequest={};for(var verb in actions){this.activeRequest[actions[verb]]=undefined;}};Ext.extend(Ext.data.HttpProxy,Ext.data.DataProxy,{getConnection:function(){return this.useAjax?Ext.Ajax:this.conn;},setUrl:function(url,makePermanent){this.conn.url=url;if(makePermanent===true){this.url=url;this.api=null;Ext.data.Api.prepare(this);}},doRequest:function(action,rs,params,reader,cb,scope,arg){var o={method:(this.api[action])?this.api[action]['method']:undefined,request:{callback:cb,scope:scope,arg:arg},reader:reader,callback:this.createCallback(action,rs),scope:this};if(params.jsonData){o.jsonData=params.jsonData;}else if(params.xmlData){o.xmlData=params.xmlData;}else{o.params=params||{};}
+this.conn.url=this.buildUrl(action,rs);if(this.useAjax){Ext.applyIf(o,this.conn);if(this.activeRequest[action]){}
+this.activeRequest[action]=Ext.Ajax.request(o);}else{this.conn.request(o);}
+this.conn.url=null;},createCallback:function(action,rs){return function(o,success,response){this.activeRequest[action]=undefined;if(!success){if(action===Ext.data.Api.actions.read){this.fireEvent('loadexception',this,o,response);}
+this.fireEvent('exception',this,'response',action,o,response);o.request.callback.call(o.request.scope,null,o.request.arg,false);return;}
+if(action===Ext.data.Api.actions.read){this.onRead(action,o,response);}else{this.onWrite(action,o,response,rs);}};},onRead:function(action,o,response){var result;try{result=o.reader.read(response);}catch(e){this.fireEvent('loadexception',this,o,response,e);this.fireEvent('exception',this,'response',action,o,response,e);o.request.callback.call(o.request.scope,null,o.request.arg,false);return;}
+if(result.success===false){this.fireEvent('loadexception',this,o,response);var res=o.reader.readResponse(action,response);this.fireEvent('exception',this,'remote',action,o,res,null);}
+else{this.fireEvent('load',this,o,o.request.arg);}
+o.request.callback.call(o.request.scope,result,o.request.arg,result.success);},onWrite:function(action,o,response,rs){var reader=o.reader;var res;try{res=reader.readResponse(action,response);}catch(e){this.fireEvent('exception',this,'response',action,o,response,e);o.request.callback.call(o.request.scope,null,o.request.arg,false);return;}
+if(res.success===true){this.fireEvent('write',this,action,res.data,res,rs,o.request.arg);}else{this.fireEvent('exception',this,'remote',action,o,res,rs);}
+o.request.callback.call(o.request.scope,res.data,res,res.success);},destroy:function(){if(!this.useAjax){this.conn.abort();}else if(this.activeRequest){var actions=Ext.data.Api.actions;for(var verb in actions){if(this.activeRequest[actions[verb]]){Ext.Ajax.abort(this.activeRequest[actions[verb]]);}}}
+Ext.data.HttpProxy.superclass.destroy.call(this);}});Ext.data.MemoryProxy=function(data){var api={};api[Ext.data.Api.actions.read]=true;Ext.data.MemoryProxy.superclass.constructor.call(this,{api:api});this.data=data;};Ext.extend(Ext.data.MemoryProxy,Ext.data.DataProxy,{doRequest:function(action,rs,params,reader,callback,scope,arg){params=params||{};var result;try{result=reader.readRecords(this.data);}catch(e){this.fireEvent("loadexception",this,null,arg,e);this.fireEvent('exception',this,'response',action,arg,null,e);callback.call(scope,null,arg,false);return;}
+callback.call(scope,result,arg,true);}});Ext.data.Types=new function(){var st=Ext.data.SortTypes;Ext.apply(this,{stripRe:/[\$,%]/g,AUTO:{convert:function(v){return v;},sortType:st.none,type:'auto'},STRING:{convert:function(v){return(v===undefined||v===null)?'':String(v);},sortType:st.asUCString,type:'string'},INT:{convert:function(v){return v!==undefined&&v!==null&&v!==''?parseInt(String(v).replace(Ext.data.Types.stripRe,''),10):(this.useNull?null:0);},sortType:st.none,type:'int'},FLOAT:{convert:function(v){return v!==undefined&&v!==null&&v!==''?parseFloat(String(v).replace(Ext.data.Types.stripRe,''),10):(this.useNull?null:0);},sortType:st.none,type:'float'},BOOL:{convert:function(v){return v===true||v==='true'||v==1;},sortType:st.none,type:'bool'},DATE:{convert:function(v){var df=this.dateFormat;if(!v){return null;}
+if(Ext.isDate(v)){return v;}
+if(df){if(df=='timestamp'){return new Date(v*1000);}
+if(df=='time'){return new Date(parseInt(v,10));}
+return Date.parseDate(v,df);}
+var parsed=Date.parse(v);return parsed?new Date(parsed):null;},sortType:st.asDate,type:'date'}});Ext.apply(this,{BOOLEAN:this.BOOL,INTEGER:this.INT,NUMBER:this.FLOAT});};Ext.data.JsonWriter=Ext.extend(Ext.data.DataWriter,{encode:true,encodeDelete:false,constructor:function(config){Ext.data.JsonWriter.superclass.constructor.call(this,config);},render:function(params,baseParams,data){if(this.encode===true){Ext.apply(params,baseParams);params[this.meta.root]=Ext.encode(data);}else{var jdata=Ext.apply({},baseParams);jdata[this.meta.root]=data;params.jsonData=jdata;}},createRecord:function(rec){return this.toHash(rec);},updateRecord:function(rec){return this.toHash(rec);},destroyRecord:function(rec){if(this.encodeDelete){var data={};data[this.meta.idProperty]=rec.id;return data;}else{return rec.id;}}});Ext.data.JsonReader=function(meta,recordType){meta=meta||{};Ext.applyIf(meta,{idProperty:'id',successProperty:'success',totalProperty:'total'});Ext.data.JsonReader.superclass.constructor.call(this,meta,recordType||meta.fields);};Ext.extend(Ext.data.JsonReader,Ext.data.DataReader,{read:function(response){var json=response.responseText;var o=Ext.decode(json);if(!o){throw{message:'JsonReader.read: Json object not found'};}
+return this.readRecords(o);},readResponse:function(action,response){var o=(response.responseText!==undefined)?Ext.decode(response.responseText):response;if(!o){throw new Ext.data.JsonReader.Error('response');}
+var root=this.getRoot(o);if(action===Ext.data.Api.actions.create){var def=Ext.isDefined(root);if(def&&Ext.isEmpty(root)){throw new Ext.data.JsonReader.Error('root-empty',this.meta.root);}
+else if(!def){throw new Ext.data.JsonReader.Error('root-undefined-response',this.meta.root);}}
+var res=new Ext.data.Response({action:action,success:this.getSuccess(o),data:(root)?this.extractData(root,false):[],message:this.getMessage(o),raw:o});if(Ext.isEmpty(res.success)){throw new Ext.data.JsonReader.Error('successProperty-response',this.meta.successProperty);}
+return res;},readRecords:function(o){this.jsonData=o;if(o.metaData){this.onMetaChange(o.metaData);}
+var s=this.meta,Record=this.recordType,f=Record.prototype.fields,fi=f.items,fl=f.length,v;var root=this.getRoot(o),c=root.length,totalRecords=c,success=true;if(s.totalProperty){v=parseInt(this.getTotal(o),10);if(!isNaN(v)){totalRecords=v;}}
+if(s.successProperty){v=this.getSuccess(o);if(v===false||v==='false'){success=false;}}
+return{success:success,records:this.extractData(root,true),totalRecords:totalRecords};},buildExtractors:function(){if(this.ef){return;}
+var s=this.meta,Record=this.recordType,f=Record.prototype.fields,fi=f.items,fl=f.length;if(s.totalProperty){this.getTotal=this.createAccessor(s.totalProperty);}
+if(s.successProperty){this.getSuccess=this.createAccessor(s.successProperty);}
+if(s.messageProperty){this.getMessage=this.createAccessor(s.messageProperty);}
+this.getRoot=s.root?this.createAccessor(s.root):function(p){return p;};if(s.id||s.idProperty){var g=this.createAccessor(s.id||s.idProperty);this.getId=function(rec){var r=g(rec);return(r===undefined||r==='')?null:r;};}else{this.getId=function(){return null;};}
+var ef=[];for(var i=0;i<fl;i++){f=fi[i];var map=(f.mapping!==undefined&&f.mapping!==null)?f.mapping:f.name;ef.push(this.createAccessor(map));}
+this.ef=ef;},simpleAccess:function(obj,subsc){return obj[subsc];},createAccessor:function(){var re=/[\[\.]/;return function(expr){if(Ext.isEmpty(expr)){return Ext.emptyFn;}
+if(Ext.isFunction(expr)){return expr;}
+var i=String(expr).search(re);if(i>=0){return new Function('obj','return obj'+(i>0?'.':'')+expr);}
+return function(obj){return obj[expr];};};}(),extractValues:function(data,items,len){var f,values={};for(var j=0;j<len;j++){f=items[j];var v=this.ef[j](data);values[f.name]=f.convert((v!==undefined)?v:f.defaultValue,data);}
+return values;}});Ext.data.JsonReader.Error=Ext.extend(Ext.Error,{constructor:function(message,arg){this.arg=arg;Ext.Error.call(this,message);},name:'Ext.data.JsonReader'});Ext.apply(Ext.data.JsonReader.Error.prototype,{lang:{'response':'An error occurred while json-decoding your server response','successProperty-response':'Could not locate your "successProperty" in your server response.  Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response.  See the JsonReader docs.','root-undefined-config':'Your JsonReader was configured without a "root" property.  Please review your JsonReader config and make sure to define the root property.  See the JsonReader docs.','idProperty-undefined':'Your JsonReader was configured without an "idProperty"  Please review your JsonReader configuration and ensure the "idProperty" is set (e.g.: "id").  See the JsonReader docs.','root-empty':'Data was expected to be returned by the server in the "root" property of the response.  Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response.  See JsonReader docs.'}});Ext.data.ArrayReader=Ext.extend(Ext.data.JsonReader,{readRecords:function(o){this.arrayData=o;var s=this.meta,sid=s?Ext.num(s.idIndex,s.id):null,recordType=this.recordType,fields=recordType.prototype.fields,records=[],success=true,v;var root=this.getRoot(o);for(var i=0,len=root.length;i<len;i++){var n=root[i],values={},id=((sid||sid===0)&&n[sid]!==undefined&&n[sid]!==""?n[sid]:null);for(var j=0,jlen=fields.length;j<jlen;j++){var f=fields.items[j],k=f.mapping!==undefined&&f.mapping!==null?f.mapping:j;v=n[k]!==undefined?n[k]:f.defaultValue;v=f.convert(v,n);values[f.name]=v;}
+var record=new recordType(values,id);record.json=n;records[records.length]=record;}
+var totalRecords=records.length;if(s.totalProperty){v=parseInt(this.getTotal(o),10);if(!isNaN(v)){totalRecords=v;}}
+if(s.successProperty){v=this.getSuccess(o);if(v===false||v==='false'){success=false;}}
+return{success:success,records:records,totalRecords:totalRecords};}});Ext.data.ArrayStore=Ext.extend(Ext.data.Store,{constructor:function(config){Ext.data.ArrayStore.superclass.constructor.call(this,Ext.apply(config,{reader:new Ext.data.ArrayReader(config)}));},loadData:function(data,append){if(this.expandData===true){var r=[];for(var i=0,len=data.length;i<len;i++){r[r.length]=[data[i]];}
+data=r;}
+Ext.data.ArrayStore.superclass.loadData.call(this,data,append);}});Ext.reg('arraystore',Ext.data.ArrayStore);Ext.data.SimpleStore=Ext.data.ArrayStore;Ext.reg('simplestore',Ext.data.SimpleStore);Ext.data.JsonStore=Ext.extend(Ext.data.Store,{constructor:function(config){Ext.data.JsonStore.superclass.constructor.call(this,Ext.apply(config,{reader:new Ext.data.JsonReader(config)}));}});Ext.reg('jsonstore',Ext.data.JsonStore);Ext.form.Field=Ext.extend(Ext.BoxComponent,{invalidClass:'x-form-invalid',invalidText:'The value in this field is invalid',focusClass:'x-form-focus',validationEvent:'keyup',validateOnBlur:true,validationDelay:250,defaultAutoCreate:{tag:'input',type:'text',size:'20',autocomplete:'off'},fieldClass:'x-form-field',msgTarget:'qtip',msgFx:'normal',readOnly:false,disabled:false,submitValue:true,isFormField:true,msgDisplay:'',hasFocus:false,initComponent:function(){Ext.form.Field.superclass.initComponent.call(this);this.addEvents('focus','blur','specialkey','change','invalid','valid');},getName:function(){return this.rendered&&this.el.dom.name?this.el.dom.name:this.name||this.id||'';},onRender:function(ct,position){if(!this.el){var cfg=this.getAutoCreate();if(!cfg.name){cfg.name=this.name||this.id;}
+if(this.inputType){cfg.type=this.inputType;}
+this.autoEl=cfg;}
+Ext.form.Field.superclass.onRender.call(this,ct,position);if(this.submitValue===false){this.el.dom.removeAttribute('name');}
+var type=this.el.dom.type;if(type){if(type=='password'){type='text';}
+this.el.addClass('x-form-'+type);}
+if(this.readOnly){this.setReadOnly(true);}
+if(this.tabIndex!==undefined){this.el.dom.setAttribute('tabIndex',this.tabIndex);}
+this.el.addClass([this.fieldClass,this.cls]);},getItemCt:function(){return this.itemCt;},initValue:function(){if(this.value!==undefined){this.setValue(this.value);}else if(!Ext.isEmpty(this.el.dom.value)&&this.el.dom.value!=this.emptyText){this.setValue(this.el.dom.value);}
+this.originalValue=this.getValue();},isDirty:function(){if(this.disabled||!this.rendered){return false;}
+return String(this.getValue())!==String(this.originalValue);},setReadOnly:function(readOnly){if(this.rendered){this.el.dom.readOnly=readOnly;}
+this.readOnly=readOnly;},afterRender:function(){Ext.form.Field.superclass.afterRender.call(this);this.initEvents();this.initValue();},fireKey:function(e){if(e.isSpecialKey()){this.fireEvent('specialkey',this,e);}},reset:function(){this.setValue(this.originalValue);this.clearInvalid();},initEvents:function(){this.mon(this.el,Ext.EventManager.getKeyEvent(),this.fireKey,this);this.mon(this.el,'focus',this.onFocus,this);this.mon(this.el,'blur',this.onBlur,this,this.inEditor?{buffer:10}:null);},preFocus:Ext.emptyFn,onFocus:function(){this.preFocus();if(this.focusClass){this.el.addClass(this.focusClass);}
+if(!this.hasFocus){this.hasFocus=true;this.startValue=this.getValue();this.fireEvent('focus',this);}},beforeBlur:Ext.emptyFn,onBlur:function(){this.beforeBlur();if(this.focusClass){this.el.removeClass(this.focusClass);}
+this.hasFocus=false;if(this.validationEvent!==false&&(this.validateOnBlur||this.validationEvent=='blur')){this.validate();}
+var v=this.getValue();if(String(v)!==String(this.startValue)){this.fireEvent('change',this,v,this.startValue);}
+this.fireEvent('blur',this);this.postBlur();},postBlur:Ext.emptyFn,isValid:function(preventMark){if(this.disabled){return true;}
+var restore=this.preventMark;this.preventMark=preventMark===true;var v=this.validateValue(this.processValue(this.getRawValue()));this.preventMark=restore;return v;},validate:function(){if(this.disabled||this.validateValue(this.processValue(this.getRawValue()))){this.clearInvalid();return true;}
+return false;},processValue:function(value){return value;},validateValue:function(value){var error=this.getErrors(value)[0];if(error==undefined){return true;}else{this.markInvalid(error);return false;}},getErrors:function(){return[];},getActiveError:function(){return this.activeError||'';},markInvalid:function(msg){if(this.rendered&&!this.preventMark){msg=msg||this.invalidText;var mt=this.getMessageHandler();if(mt){mt.mark(this,msg);}else if(this.msgTarget){this.el.addClass(this.invalidClass);var t=Ext.getDom(this.msgTarget);if(t){t.innerHTML=msg;t.style.display=this.msgDisplay;}}}
+this.setActiveError(msg);},clearInvalid:function(){if(this.rendered&&!this.preventMark){this.el.removeClass(this.invalidClass);var mt=this.getMessageHandler();if(mt){mt.clear(this);}else if(this.msgTarget){this.el.removeClass(this.invalidClass);var t=Ext.getDom(this.msgTarget);if(t){t.innerHTML='';t.style.display='none';}}}
+this.unsetActiveError();},setActiveError:function(msg,suppressEvent){this.activeError=msg;if(suppressEvent!==true)this.fireEvent('invalid',this,msg);},unsetActiveError:function(suppressEvent){delete this.activeError;if(suppressEvent!==true)this.fireEvent('valid',this);},getMessageHandler:function(){return Ext.form.MessageTargets[this.msgTarget];},getErrorCt:function(){return this.el.findParent('.x-form-element',5,true)||this.el.findParent('.x-form-field-wrap',5,true);},alignErrorEl:function(){this.errorEl.setWidth(this.getErrorCt().getWidth(true)-20);},alignErrorIcon:function(){this.errorIcon.alignTo(this.el,'tl-tr',[2,0]);},getRawValue:function(){var v=this.rendered?this.el.getValue():Ext.value(this.value,'');if(v===this.emptyText){v='';}
+return v;},getValue:function(){if(!this.rendered){return this.value;}
+var v=this.el.getValue();if(v===this.emptyText||v===undefined){v='';}
+return v;},setRawValue:function(v){return this.rendered?(this.el.dom.value=(Ext.isEmpty(v)?'':v)):'';},setValue:function(v){this.value=v;if(this.rendered){this.el.dom.value=(Ext.isEmpty(v)?'':v);this.validate();}
+return this;},append:function(v){this.setValue([this.getValue(),v].join(''));}});Ext.form.MessageTargets={'qtip':{mark:function(field,msg){field.el.addClass(field.invalidClass);field.el.dom.qtip=msg;field.el.dom.qclass='x-form-invalid-tip';if(Ext.QuickTips){Ext.QuickTips.enable();}},clear:function(field){field.el.removeClass(field.invalidClass);field.el.dom.qtip='';}},'title':{mark:function(field,msg){field.el.addClass(field.invalidClass);field.el.dom.title=msg;},clear:function(field){field.el.dom.title='';}},'under':{mark:function(field,msg){field.el.addClass(field.invalidClass);if(!field.errorEl){var elp=field.getErrorCt();if(!elp){field.el.dom.title=msg;return;}
+field.errorEl=elp.createChild({cls:'x-form-invalid-msg'});field.on('resize',field.alignErrorEl,field);field.on('destroy',function(){Ext.destroy(this.errorEl);},field);}
+field.alignErrorEl();field.errorEl.update(msg);Ext.form.Field.msgFx[field.msgFx].show(field.errorEl,field);},clear:function(field){field.el.removeClass(field.invalidClass);if(field.errorEl){Ext.form.Field.msgFx[field.msgFx].hide(field.errorEl,field);}else{field.el.dom.title='';}}},'side':{mark:function(field,msg){field.el.addClass(field.invalidClass);if(!field.errorIcon){var elp=field.getErrorCt();if(!elp){field.el.dom.title=msg;return;}
+field.errorIcon=elp.createChild({cls:'x-form-invalid-icon'});if(field.ownerCt){field.ownerCt.on('afterlayout',field.alignErrorIcon,field);field.ownerCt.on('expand',field.alignErrorIcon,field);}
+field.on('resize',field.alignErrorIcon,field);field.on('destroy',function(){Ext.destroy(this.errorIcon);},field);}
+field.alignErrorIcon();field.errorIcon.dom.qtip=msg;field.errorIcon.dom.qclass='x-form-invalid-tip';field.errorIcon.show();},clear:function(field){field.el.removeClass(field.invalidClass);if(field.errorIcon){field.errorIcon.dom.qtip='';field.errorIcon.hide();}else{field.el.dom.title='';}}}};Ext.form.Field.msgFx={normal:{show:function(msgEl,f){msgEl.setDisplayed('block');},hide:function(msgEl,f){msgEl.setDisplayed(false).update('');}},slide:{show:function(msgEl,f){msgEl.slideIn('t',{stopFx:true});},hide:function(msgEl,f){msgEl.slideOut('t',{stopFx:true,useDisplay:true});}},slideRight:{show:function(msgEl,f){msgEl.fixDisplay();msgEl.alignTo(f.el,'tl-tr');msgEl.slideIn('l',{stopFx:true});},hide:function(msgEl,f){msgEl.slideOut('l',{stopFx:true,useDisplay:true});}}};Ext.reg('field',Ext.form.Field);Ext.form.TextField=Ext.extend(Ext.form.Field,{grow:false,growMin:30,growMax:800,vtype:null,maskRe:null,disableKeyFilter:false,allowBlank:true,minLength:0,maxLength:Number.MAX_VALUE,minLengthText:'The minimum length for this field is {0}',maxLengthText:'The maximum length for this field is {0}',selectOnFocus:false,blankText:'This field is required',validator:null,regex:null,regexText:'',emptyText:null,emptyClass:'x-form-empty-field',initComponent:function(){Ext.form.TextField.superclass.initComponent.call(this);this.addEvents('autosize','keydown','keyup','keypress');},initEvents:function(){Ext.form.TextField.superclass.initEvents.call(this);if(this.validationEvent=='keyup'){this.validationTask=new Ext.util.DelayedTask(this.validate,this);this.mon(this.el,'keyup',this.filterValidation,this);}
+else if(this.validationEvent!==false&&this.validationEvent!='blur'){this.mon(this.el,this.validationEvent,this.validate,this,{buffer:this.validationDelay});}
+if(this.selectOnFocus||this.emptyText){this.mon(this.el,'mousedown',this.onMouseDown,this);if(this.emptyText){this.applyEmptyText();}}
+if(this.maskRe||(this.vtype&&this.disableKeyFilter!==true&&(this.maskRe=Ext.form.VTypes[this.vtype+'Mask']))){this.mon(this.el,'keypress',this.filterKeys,this);}
+if(this.grow){this.mon(this.el,'keyup',this.onKeyUpBuffered,this,{buffer:50});this.mon(this.el,'click',this.autoSize,this);}
+if(this.enableKeyEvents){this.mon(this.el,{scope:this,keyup:this.onKeyUp,keydown:this.onKeyDown,keypress:this.onKeyPress});}},onMouseDown:function(e){if(!this.hasFocus){this.mon(this.el,'mouseup',Ext.emptyFn,this,{single:true,preventDefault:true});}},processValue:function(value){if(this.stripCharsRe){var newValue=value.replace(this.stripCharsRe,'');if(newValue!==value){this.setRawValue(newValue);return newValue;}}
+return value;},filterValidation:function(e){if(!e.isNavKeyPress()){this.validationTask.delay(this.validationDelay);}},onDisable:function(){Ext.form.TextField.superclass.onDisable.call(this);if(Ext.isIE){this.el.dom.unselectable='on';}},onEnable:function(){Ext.form.TextField.superclass.onEnable.call(this);if(Ext.isIE){this.el.dom.unselectable='';}},onKeyUpBuffered:function(e){if(this.doAutoSize(e)){this.autoSize();}},doAutoSize:function(e){return!e.isNavKeyPress();},onKeyUp:function(e){this.fireEvent('keyup',this,e);},onKeyDown:function(e){this.fireEvent('keydown',this,e);},onKeyPress:function(e){this.fireEvent('keypress',this,e);},reset:function(){Ext.form.TextField.superclass.reset.call(this);this.applyEmptyText();},applyEmptyText:function(){if(this.rendered&&this.emptyText&&this.getRawValue().length<1&&!this.hasFocus){this.setRawValue(this.emptyText);this.el.addClass(this.emptyClass);}},preFocus:function(){var el=this.el,isEmpty;if(this.emptyText){if(el.dom.value==this.emptyText){this.setRawValue('');isEmpty=true;}
+el.removeClass(this.emptyClass);}
+if(this.selectOnFocus||isEmpty){el.dom.select();}},postBlur:function(){this.applyEmptyText();},filterKeys:function(e){if(e.ctrlKey){return;}
+var k=e.getKey();if(Ext.isGecko&&(e.isNavKeyPress()||k==e.BACKSPACE||(k==e.DELETE&&e.button==-1))){return;}
+var cc=String.fromCharCode(e.getCharCode());if(!Ext.isGecko&&e.isSpecialKey()&&!cc){return;}
+if(!this.maskRe.test(cc)){e.stopEvent();}},setValue:function(v){if(this.emptyText&&this.el&&!Ext.isEmpty(v)){this.el.removeClass(this.emptyClass);}
+Ext.form.TextField.superclass.setValue.apply(this,arguments);this.applyEmptyText();this.autoSize();return this;},getErrors:function(value){var errors=Ext.form.TextField.superclass.getErrors.apply(this,arguments);value=Ext.isDefined(value)?value:this.processValue(this.getRawValue());if(Ext.isFunction(this.validator)){var msg=this.validator(value);if(msg!==true){errors.push(msg);}}
+if(value.length<1||value===this.emptyText){if(this.allowBlank){return errors;}else{errors.push(this.blankText);}}
+if(!this.allowBlank&&(value.length<1||value===this.emptyText)){errors.push(this.blankText);}
+if(value.length<this.minLength){errors.push(String.format(this.minLengthText,this.minLength));}
+if(value.length>this.maxLength){errors.push(String.format(this.maxLengthText,this.maxLength));}
+if(this.vtype){var vt=Ext.form.VTypes;if(!vt[this.vtype](value,this)){errors.push(this.vtypeText||vt[this.vtype+'Text']);}}
+if(this.regex&&!this.regex.test(value)){errors.push(this.regexText);}
+return errors;},selectText:function(start,end){var v=this.getRawValue();var doFocus=false;if(v.length>0){start=start===undefined?0:start;end=end===undefined?v.length:end;var d=this.el.dom;if(d.setSelectionRange){d.setSelectionRange(start,end);}else if(d.createTextRange){var range=d.createTextRange();range.moveStart('character',start);range.moveEnd('character',end-v.length);range.select();}
+doFocus=Ext.isGecko||Ext.isOpera;}else{doFocus=true;}
+if(doFocus){this.focus();}},autoSize:function(){if(!this.grow||!this.rendered){return;}
+if(!this.metrics){this.metrics=Ext.util.TextMetrics.createInstance(this.el);}
+var el=this.el;var v=el.dom.value;var d=document.createElement('div');d.appendChild(document.createTextNode(v));v=d.innerHTML;Ext.removeNode(d);d=null;v+='&#160;';var w=Math.min(this.growMax,Math.max(this.metrics.getWidth(v)+10,this.growMin));this.el.setWidth(w);this.fireEvent('autosize',this,w);},onDestroy:function(){if(this.validationTask){this.validationTask.cancel();this.validationTask=null;}
+Ext.form.TextField.superclass.onDestroy.call(this);}});Ext.reg('textfield',Ext.form.TextField);Ext.form.TriggerField=Ext.extend(Ext.form.TextField,{defaultAutoCreate:{tag:"input",type:"text",size:"16",autocomplete:"off"},hideTrigger:false,editable:true,readOnly:false,wrapFocusClass:'x-trigger-wrap-focus',autoSize:Ext.emptyFn,monitorTab:true,deferHeight:true,mimicing:false,actionMode:'wrap',defaultTriggerWidth:17,onResize:function(w,h){Ext.form.TriggerField.superclass.onResize.call(this,w,h);var tw=this.getTriggerWidth();if(Ext.isNumber(w)){this.el.setWidth(w-tw);}
+this.wrap.setWidth(this.el.getWidth()+tw);},getTriggerWidth:function(){var tw=this.trigger.getWidth();if(!this.hideTrigger&&!this.readOnly&&tw===0){tw=this.defaultTriggerWidth;}
+return tw;},alignErrorIcon:function(){if(this.wrap){this.errorIcon.alignTo(this.wrap,'tl-tr',[2,0]);}},onRender:function(ct,position){this.doc=Ext.isIE?Ext.getBody():Ext.getDoc();Ext.form.TriggerField.superclass.onRender.call(this,ct,position);this.wrap=this.el.wrap({cls:'x-form-field-wrap x-form-field-trigger-wrap'});this.trigger=this.wrap.createChild(this.triggerConfig||{tag:"img",src:Ext.BLANK_IMAGE_URL,alt:"",cls:"x-form-trigger "+this.triggerClass});this.initTrigger();if(!this.width){this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());}
+this.resizeEl=this.positionEl=this.wrap;},getWidth:function(){return(this.el.getWidth()+this.trigger.getWidth());},updateEditState:function(){if(this.rendered){if(this.readOnly){this.el.dom.readOnly=true;this.el.addClass('x-trigger-noedit');this.mun(this.el,'click',this.onTriggerClick,this);this.trigger.setDisplayed(false);}else{if(!this.editable){this.el.dom.readOnly=true;this.el.addClass('x-trigger-noedit');this.mon(this.el,'click',this.onTriggerClick,this);}else{this.el.dom.readOnly=false;this.el.removeClass('x-trigger-noedit');this.mun(this.el,'click',this.onTriggerClick,this);}
+this.trigger.setDisplayed(!this.hideTrigger);}
+this.onResize(this.width||this.wrap.getWidth());}},setHideTrigger:function(hideTrigger){if(hideTrigger!=this.hideTrigger){this.hideTrigger=hideTrigger;this.updateEditState();}},setEditable:function(editable){if(editable!=this.editable){this.editable=editable;this.updateEditState();}},setReadOnly:function(readOnly){if(readOnly!=this.readOnly){this.readOnly=readOnly;this.updateEditState();}},afterRender:function(){Ext.form.TriggerField.superclass.afterRender.call(this);this.updateEditState();},initTrigger:function(){this.mon(this.trigger,'click',this.onTriggerClick,this,{preventDefault:true});this.trigger.addClassOnOver('x-form-trigger-over');this.trigger.addClassOnClick('x-form-trigger-click');},onDestroy:function(){Ext.destroy(this.trigger,this.wrap);if(this.mimicing){this.doc.un('mousedown',this.mimicBlur,this);}
+delete this.doc;Ext.form.TriggerField.superclass.onDestroy.call(this);},onFocus:function(){Ext.form.TriggerField.superclass.onFocus.call(this);if(!this.mimicing){this.wrap.addClass(this.wrapFocusClass);this.mimicing=true;this.doc.on('mousedown',this.mimicBlur,this,{delay:10});if(this.monitorTab){this.on('specialkey',this.checkTab,this);}}},checkTab:function(me,e){if(e.getKey()==e.TAB){this.triggerBlur();}},onBlur:Ext.emptyFn,mimicBlur:function(e){if(!this.isDestroyed&&!this.wrap.contains(e.target)&&this.validateBlur(e)){this.triggerBlur();}},triggerBlur:function(){this.mimicing=false;this.doc.un('mousedown',this.mimicBlur,this);if(this.monitorTab&&this.el){this.un('specialkey',this.checkTab,this);}
+Ext.form.TriggerField.superclass.onBlur.call(this);if(this.wrap){this.wrap.removeClass(this.wrapFocusClass);}},beforeBlur:Ext.emptyFn,validateBlur:function(e){return true;},onTriggerClick:Ext.emptyFn});Ext.form.TwinTriggerField=Ext.extend(Ext.form.TriggerField,{initComponent:function(){Ext.form.TwinTriggerField.superclass.initComponent.call(this);this.triggerConfig={tag:'span',cls:'x-form-twin-triggers',cn:[{tag:"img",src:Ext.BLANK_IMAGE_URL,alt:"",cls:"x-form-trigger "+this.trigger1Class},{tag:"img",src:Ext.BLANK_IMAGE_URL,alt:"",cls:"x-form-trigger "+this.trigger2Class}]};},getTrigger:function(index){return this.triggers[index];},afterRender:function(){Ext.form.TwinTriggerField.superclass.afterRender.call(this);var triggers=this.triggers,i=0,len=triggers.length;for(;i<len;++i){if(this['hideTrigger'+(i+1)]){triggers[i].hide();}}},initTrigger:function(){var ts=this.trigger.select('.x-form-trigger',true),triggerField=this;ts.each(function(t,all,index){var triggerIndex='Trigger'+(index+1);t.hide=function(){var w=triggerField.wrap.getWidth();this.dom.style.display='none';triggerField.el.setWidth(w-triggerField.trigger.getWidth());triggerField['hidden'+triggerIndex]=true;};t.show=function(){var w=triggerField.wrap.getWidth();this.dom.style.display='';triggerField.el.setWidth(w-triggerField.trigger.getWidth());triggerField['hidden'+triggerIndex]=false;};this.mon(t,'click',this['on'+triggerIndex+'Click'],this,{preventDefault:true});t.addClassOnOver('x-form-trigger-over');t.addClassOnClick('x-form-trigger-click');},this);this.triggers=ts.elements;},getTriggerWidth:function(){var tw=0;Ext.each(this.triggers,function(t,index){var triggerIndex='Trigger'+(index+1),w=t.getWidth();if(w===0&&!this['hidden'+triggerIndex]){tw+=this.defaultTriggerWidth;}else{tw+=w;}},this);return tw;},onDestroy:function(){Ext.destroy(this.triggers);Ext.form.TwinTriggerField.superclass.onDestroy.call(this);},onTrigger1Click:Ext.emptyFn,onTrigger2Click:Ext.emptyFn});Ext.reg('trigger',Ext.form.TriggerField);Ext.form.TextArea=Ext.extend(Ext.form.TextField,{growMin:60,growMax:1000,growAppend:'&#160;\n&#160;',enterIsSpecial:false,preventScrollbars:false,onRender:function(ct,position){if(!this.el){this.defaultAutoCreate={tag:"textarea",style:"width:100px;height:60px;",autocomplete:"off"};}
+Ext.form.TextArea.superclass.onRender.call(this,ct,position);if(this.grow){this.textSizeEl=Ext.DomHelper.append(document.body,{tag:"pre",cls:"x-form-grow-sizer"});if(this.preventScrollbars){this.el.setStyle("overflow","hidden");}
+this.el.setHeight(this.growMin);}},onDestroy:function(){Ext.removeNode(this.textSizeEl);Ext.form.TextArea.superclass.onDestroy.call(this);},fireKey:function(e){if(e.isSpecialKey()&&(this.enterIsSpecial||(e.getKey()!=e.ENTER||e.hasModifier()))){this.fireEvent("specialkey",this,e);}},doAutoSize:function(e){return!e.isNavKeyPress()||e.getKey()==e.ENTER;},filterValidation:function(e){if(!e.isNavKeyPress()||(!this.enterIsSpecial&&e.keyCode==e.ENTER)){this.validationTask.delay(this.validationDelay);}},autoSize:function(){if(!this.grow||!this.textSizeEl){return;}
+var el=this.el,v=Ext.util.Format.htmlEncode(el.dom.value),ts=this.textSizeEl,h;Ext.fly(ts).setWidth(this.el.getWidth());if(v.length<1){v="&#160;&#160;";}else{v+=this.growAppend;if(Ext.isIE){v=v.replace(/\n/g,'&#160;<br />');}}
+ts.innerHTML=v;h=Math.min(this.growMax,Math.max(ts.offsetHeight,this.growMin));if(h!=this.lastHeight){this.lastHeight=h;this.el.setHeight(h);this.fireEvent("autosize",this,h);}}});Ext.reg('textarea',Ext.form.TextArea);Ext.form.NumberField=Ext.extend(Ext.form.TextField,{fieldClass:"x-form-field x-form-num-field",allowDecimals:true,decimalSeparator:".",decimalPrecision:2,allowNegative:true,minValue:Number.NEGATIVE_INFINITY,maxValue:Number.MAX_VALUE,minText:"The minimum value for this field is {0}",maxText:"The maximum value for this field is {0}",nanText:"{0} is not a valid number",baseChars:"0123456789",autoStripChars:false,initEvents:function(){var allowed=this.baseChars+'';if(this.allowDecimals){allowed+=this.decimalSeparator;}
+if(this.allowNegative){allowed+='-';}
+allowed=Ext.escapeRe(allowed);this.maskRe=new RegExp('['+allowed+']');if(this.autoStripChars){this.stripCharsRe=new RegExp('[^'+allowed+']','gi');}
+Ext.form.NumberField.superclass.initEvents.call(this);},getErrors:function(value){var errors=Ext.form.NumberField.superclass.getErrors.apply(this,arguments);value=Ext.isDefined(value)?value:this.processValue(this.getRawValue());if(value.length<1){return errors;}
+value=String(value).replace(this.decimalSeparator,".");if(isNaN(value)){errors.push(String.format(this.nanText,value));}
+var num=this.parseValue(value);if(num<this.minValue){errors.push(String.format(this.minText,this.minValue));}
+if(num>this.maxValue){errors.push(String.format(this.maxText,this.maxValue));}
+return errors;},getValue:function(){return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));},setValue:function(v){v=this.fixPrecision(v);v=Ext.isNumber(v)?v:parseFloat(String(v).replace(this.decimalSeparator,"."));v=isNaN(v)?'':String(v).replace(".",this.decimalSeparator);return Ext.form.NumberField.superclass.setValue.call(this,v);},setMinValue:function(value){this.minValue=Ext.num(value,Number.NEGATIVE_INFINITY);},setMaxValue:function(value){this.maxValue=Ext.num(value,Number.MAX_VALUE);},parseValue:function(value){value=parseFloat(String(value).replace(this.decimalSeparator,"."));return isNaN(value)?'':value;},fixPrecision:function(value){var nan=isNaN(value);if(!this.allowDecimals||this.decimalPrecision==-1||nan||!value){return nan?'':value;}
+return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));},beforeBlur:function(){var v=this.parseValue(this.getRawValue());if(!Ext.isEmpty(v)){this.setValue(v);}}});Ext.reg('numberfield',Ext.form.NumberField);Ext.form.DateField=Ext.extend(Ext.form.TriggerField,{format:"m/d/Y",altFormats:"m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j",disabledDaysText:"Disabled",disabledDatesText:"Disabled",minText:"The date in this field must be equal to or after {0}",maxText:"The date in this field must be equal to or before {0}",invalidText:"{0} is not a valid date - it must be in the format {1}",triggerClass:'x-form-date-trigger',showToday:true,startDay:0,defaultAutoCreate:{tag:"input",type:"text",size:"10",autocomplete:"off"},initTime:'12',initTimeFormat:'H',safeParse:function(value,format){if(/[gGhH]/.test(format.replace(/(\\.)/g,''))){return Date.parseDate(value,format);}else{var parsedDate=Date.parseDate(value+' '+this.initTime,format+' '+this.initTimeFormat);if(parsedDate){return parsedDate.clearTime();}}},initComponent:function(){Ext.form.DateField.superclass.initComponent.call(this);this.addEvents('select');if(Ext.isString(this.minValue)){this.minValue=this.parseDate(this.minValue);}
+if(Ext.isString(this.maxValue)){this.maxValue=this.parseDate(this.maxValue);}
+this.disabledDatesRE=null;this.initDisabledDays();},initEvents:function(){Ext.form.DateField.superclass.initEvents.call(this);this.keyNav=new Ext.KeyNav(this.el,{"down":function(e){this.onTriggerClick();},scope:this,forceKeyDown:true});},initDisabledDays:function(){if(this.disabledDates){var dd=this.disabledDates,len=dd.length-1,re="(?:";Ext.each(dd,function(d,i){re+=Ext.isDate(d)?'^'+Ext.escapeRe(d.dateFormat(this.format))+'$':dd[i];if(i!=len){re+='|';}},this);this.disabledDatesRE=new RegExp(re+')');}},setDisabledDates:function(dd){this.disabledDates=dd;this.initDisabledDays();if(this.menu){this.menu.picker.setDisabledDates(this.disabledDatesRE);}},setDisabledDays:function(dd){this.disabledDays=dd;if(this.menu){this.menu.picker.setDisabledDays(dd);}},setMinValue:function(dt){this.minValue=(Ext.isString(dt)?this.parseDate(dt):dt);if(this.menu){this.menu.picker.setMinDate(this.minValue);}},setMaxValue:function(dt){this.maxValue=(Ext.isString(dt)?this.parseDate(dt):dt);if(this.menu){this.menu.picker.setMaxDate(this.maxValue);}},getErrors:function(value){var errors=Ext.form.DateField.superclass.getErrors.apply(this,arguments);value=this.formatDate(value||this.processValue(this.getRawValue()));if(value.length<1){return errors;}
+var svalue=value;value=this.parseDate(value);if(!value){errors.push(String.format(this.invalidText,svalue,this.format));return errors;}
+var time=value.getTime();if(this.minValue&&time<this.minValue.clearTime().getTime()){errors.push(String.format(this.minText,this.formatDate(this.minValue)));}
+if(this.maxValue&&time>this.maxValue.clearTime().getTime()){errors.push(String.format(this.maxText,this.formatDate(this.maxValue)));}
+if(this.disabledDays){var day=value.getDay();for(var i=0;i<this.disabledDays.length;i++){if(day===this.disabledDays[i]){errors.push(this.disabledDaysText);break;}}}
+var fvalue=this.formatDate(value);if(this.disabledDatesRE&&this.disabledDatesRE.test(fvalue)){errors.push(String.format(this.disabledDatesText,fvalue));}
+return errors;},validateBlur:function(){return!this.menu||!this.menu.isVisible();},getValue:function(){return this.parseDate(Ext.form.DateField.superclass.getValue.call(this))||"";},setValue:function(date){return Ext.form.DateField.superclass.setValue.call(this,this.formatDate(this.parseDate(date)));},parseDate:function(value){if(!value||Ext.isDate(value)){return value;}
+var v=this.safeParse(value,this.format),af=this.altFormats,afa=this.altFormatsArray;if(!v&&af){afa=afa||af.split("|");for(var i=0,len=afa.length;i<len&&!v;i++){v=this.safeParse(value,afa[i]);}}
+return v;},onDestroy:function(){Ext.destroy(this.menu,this.keyNav);Ext.form.DateField.superclass.onDestroy.call(this);},formatDate:function(date){return Ext.isDate(date)?date.dateFormat(this.format):date;},onTriggerClick:function(){if(this.disabled){return;}
+if(this.menu==null){this.menu=new Ext.menu.DateMenu({hideOnClick:false,focusOnSelect:false});}
+this.onFocus();Ext.apply(this.menu.picker,{minDate:this.minValue,maxDate:this.maxValue,disabledDatesRE:this.disabledDatesRE,disabledDatesText:this.disabledDatesText,disabledDays:this.disabledDays,disabledDaysText:this.disabledDaysText,format:this.format,showToday:this.showToday,startDay:this.startDay,minText:String.format(this.minText,this.formatDate(this.minValue)),maxText:String.format(this.maxText,this.formatDate(this.maxValue))});this.menu.picker.setValue(this.getValue()||new Date());this.menu.show(this.el,"tl-bl?");this.menuEvents('on');},menuEvents:function(method){this.menu[method]('select',this.onSelect,this);this.menu[method]('hide',this.onMenuHide,this);this.menu[method]('show',this.onFocus,this);},onSelect:function(m,d){this.setValue(d);this.fireEvent('select',this,d);this.menu.hide();},onMenuHide:function(){this.focus(false,60);this.menuEvents('un');},beforeBlur:function(){var v=this.parseDate(this.getRawValue());if(v){this.setValue(v);}}});Ext.reg('datefield',Ext.form.DateField);Ext.form.DisplayField=Ext.extend(Ext.form.Field,{validationEvent:false,validateOnBlur:false,defaultAutoCreate:{tag:"div"},fieldClass:"x-form-display-field",htmlEncode:false,initEvents:Ext.emptyFn,isValid:function(){return true;},validate:function(){return true;},getRawValue:function(){var v=this.rendered?this.el.dom.innerHTML:Ext.value(this.value,'');if(v===this.emptyText){v='';}
+if(this.htmlEncode){v=Ext.util.Format.htmlDecode(v);}
+return v;},getValue:function(){return this.getRawValue();},getName:function(){return this.name;},setRawValue:function(v){if(this.htmlEncode){v=Ext.util.Format.htmlEncode(v);}
+return this.rendered?(this.el.dom.innerHTML=(Ext.isEmpty(v)?'':v)):(this.value=v);},setValue:function(v){this.setRawValue(v);return this;}});Ext.reg('displayfield',Ext.form.DisplayField);Ext.form.ComboBox=Ext.extend(Ext.form.TriggerField,{defaultAutoCreate:{tag:"input",type:"text",size:"24",autocomplete:"off"},listClass:'',selectedClass:'x-combo-selected',listEmptyText:'',triggerClass:'x-form-arrow-trigger',shadow:'sides',listAlign:'tl-bl?',maxHeight:300,minHeight:90,triggerAction:'query',minChars:4,autoSelect:true,typeAhead:false,queryDelay:500,pageSize:0,selectOnFocus:false,queryParam:'query',loadingText:'Loading...',resizable:false,handleHeight:8,allQuery:'',mode:'remote',minListWidth:70,forceSelection:false,typeAheadDelay:250,lazyInit:true,clearFilterOnReset:true,submitValue:undefined,initComponent:function(){Ext.form.ComboBox.superclass.initComponent.call(this);this.addEvents('expand','collapse','beforeselect','select','beforequery');if(this.transform){var s=Ext.getDom(this.transform);if(!this.hiddenName){this.hiddenName=s.name;}
+if(!this.store){this.mode='local';var d=[],opts=s.options;for(var i=0,len=opts.length;i<len;i++){var o=opts[i],value=(o.hasAttribute?o.hasAttribute('value'):o.getAttributeNode('value').specified)?o.value:o.text;if(o.selected&&Ext.isEmpty(this.value,true)){this.value=value;}
+d.push([value,o.text]);}
+this.store=new Ext.data.ArrayStore({idIndex:0,fields:['value','text'],data:d,autoDestroy:true});this.valueField='value';this.displayField='text';}
+s.name=Ext.id();if(!this.lazyRender){this.target=true;this.el=Ext.DomHelper.insertBefore(s,this.autoCreate||this.defaultAutoCreate);this.render(this.el.parentNode,s);}
+Ext.removeNode(s);}
+else if(this.store){this.store=Ext.StoreMgr.lookup(this.store);if(this.store.autoCreated){this.displayField=this.valueField='field1';if(!this.store.expandData){this.displayField='field2';}
+this.mode='local';}}
+this.selectedIndex=-1;if(this.mode=='local'){if(!Ext.isDefined(this.initialConfig.queryDelay)){this.queryDelay=10;}
+if(!Ext.isDefined(this.initialConfig.minChars)){this.minChars=0;}}},onRender:function(ct,position){if(this.hiddenName&&!Ext.isDefined(this.submitValue)){this.submitValue=false;}
+Ext.form.ComboBox.superclass.onRender.call(this,ct,position);if(this.hiddenName){this.hiddenField=this.el.insertSibling({tag:'input',type:'hidden',name:this.hiddenName,id:(this.hiddenId||Ext.id())},'before',true);}
+if(Ext.isGecko){this.el.dom.setAttribute('autocomplete','off');}
+if(!this.lazyInit){this.initList();}else{this.on('focus',this.initList,this,{single:true});}},initValue:function(){Ext.form.ComboBox.superclass.initValue.call(this);if(this.hiddenField){this.hiddenField.value=Ext.value(Ext.isDefined(this.hiddenValue)?this.hiddenValue:this.value,'');}},getParentZIndex:function(){var zindex;if(this.ownerCt){this.findParentBy(function(ct){zindex=parseInt(ct.getPositionEl().getStyle('z-index'),10);return!!zindex;});}
+return zindex;},getZIndex:function(listParent){listParent=listParent||Ext.getDom(this.getListParent()||Ext.getBody());var zindex=parseInt(Ext.fly(listParent).getStyle('z-index'),10);if(!zindex){zindex=this.getParentZIndex();}
+return(zindex||12000)+5;},initList:function(){if(!this.list){var cls='x-combo-list',listParent=Ext.getDom(this.getListParent()||Ext.getBody());this.list=new Ext.Layer({parentEl:listParent,shadow:this.shadow,cls:[cls,this.listClass].join(' '),constrain:false,zindex:this.getZIndex(listParent)});var lw=this.listWidth||Math.max(this.wrap.getWidth(),this.minListWidth);this.list.setSize(lw,0);this.list.swallowEvent('mousewheel');this.assetHeight=0;if(this.syncFont!==false){this.list.setStyle('font-size',this.el.getStyle('font-size'));}
+if(this.title){this.header=this.list.createChild({cls:cls+'-hd',html:this.title});this.assetHeight+=this.header.getHeight();}
+this.innerList=this.list.createChild({cls:cls+'-inner'});this.mon(this.innerList,'mouseover',this.onViewOver,this);this.mon(this.innerList,'mousemove',this.onViewMove,this);this.innerList.setWidth(lw-this.list.getFrameWidth('lr'));if(this.pageSize){this.footer=this.list.createChild({cls:cls+'-ft'});this.pageTb=new Ext.PagingToolbar({store:this.store,pageSize:this.pageSize,renderTo:this.footer});this.assetHeight+=this.footer.getHeight();}
+if(!this.tpl){this.tpl='<tpl for="."><div class="'+cls+'-item">{'+this.displayField+'}</div></tpl>';}
+this.view=new Ext.DataView({applyTo:this.innerList,tpl:this.tpl,singleSelect:true,selectedClass:this.selectedClass,itemSelector:this.itemSelector||'.'+cls+'-item',emptyText:this.listEmptyText,deferEmptyText:false});this.mon(this.view,{containerclick:this.onViewClick,click:this.onViewClick,scope:this});this.bindStore(this.store,true);if(this.resizable){this.resizer=new Ext.Resizable(this.list,{pinned:true,handles:'se'});this.mon(this.resizer,'resize',function(r,w,h){this.maxHeight=h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;this.listWidth=w;this.innerList.setWidth(w-this.list.getFrameWidth('lr'));this.restrictHeight();},this);this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom',this.handleHeight+'px');}}},getListParent:function(){return document.body;},getStore:function(){return this.store;},bindStore:function(store,initial){if(this.store&&!initial){if(this.store!==store&&this.store.autoDestroy){this.store.destroy();}else{this.store.un('beforeload',this.onBeforeLoad,this);this.store.un('load',this.onLoad,this);this.store.un('exception',this.collapse,this);}
+if(!store){this.store=null;if(this.view){this.view.bindStore(null);}
+if(this.pageTb){this.pageTb.bindStore(null);}}}
+if(store){if(!initial){this.lastQuery=null;if(this.pageTb){this.pageTb.bindStore(store);}}
+this.store=Ext.StoreMgr.lookup(store);this.store.on({scope:this,beforeload:this.onBeforeLoad,load:this.onLoad,exception:this.collapse});if(this.view){this.view.bindStore(store);}}},reset:function(){if(this.clearFilterOnReset&&this.mode=='local'){this.store.clearFilter();}
+Ext.form.ComboBox.superclass.reset.call(this);},initEvents:function(){Ext.form.ComboBox.superclass.initEvents.call(this);this.keyNav=new Ext.KeyNav(this.el,{"up":function(e){this.inKeyMode=true;this.selectPrev();},"down":function(e){if(!this.isExpanded()){this.onTriggerClick();}else{this.inKeyMode=true;this.selectNext();}},"enter":function(e){this.onViewClick();},"esc":function(e){this.collapse();},"tab":function(e){if(this.forceSelection===true){this.collapse();}else{this.onViewClick(false);}
+return true;},scope:this,doRelay:function(e,h,hname){if(hname=='down'||this.scope.isExpanded()){var relay=Ext.KeyNav.prototype.doRelay.apply(this,arguments);if(!Ext.isIE&&Ext.EventManager.useKeydown){this.scope.fireKey(e);}
+return relay;}
+return true;},forceKeyDown:true,defaultEventAction:'stopEvent'});this.queryDelay=Math.max(this.queryDelay||10,this.mode=='local'?10:250);this.dqTask=new Ext.util.DelayedTask(this.initQuery,this);if(this.typeAhead){this.taTask=new Ext.util.DelayedTask(this.onTypeAhead,this);}
+if(!this.enableKeyEvents){this.mon(this.el,'keyup',this.onKeyUp,this);}},onDestroy:function(){if(this.dqTask){this.dqTask.cancel();this.dqTask=null;}
+this.bindStore(null);Ext.destroy(this.resizer,this.view,this.pageTb,this.list);Ext.destroyMembers(this,'hiddenField');Ext.form.ComboBox.superclass.onDestroy.call(this);},fireKey:function(e){if(!this.isExpanded()){Ext.form.ComboBox.superclass.fireKey.call(this,e);}},onResize:function(w,h){Ext.form.ComboBox.superclass.onResize.apply(this,arguments);if(!isNaN(w)&&this.isVisible()&&this.list){this.doResize(w);}else{this.bufferSize=w;}},doResize:function(w){if(!Ext.isDefined(this.listWidth)){var lw=Math.max(w,this.minListWidth);this.list.setWidth(lw);this.innerList.setWidth(lw-this.list.getFrameWidth('lr'));}},onEnable:function(){Ext.form.ComboBox.superclass.onEnable.apply(this,arguments);if(this.hiddenField){this.hiddenField.disabled=false;}},onDisable:function(){Ext.form.ComboBox.superclass.onDisable.apply(this,arguments);if(this.hiddenField){this.hiddenField.disabled=true;}},onBeforeLoad:function(){if(!this.hasFocus){return;}
+this.innerList.update(this.loadingText?'<div class="loading-indicator">'+this.loadingText+'</div>':'');this.restrictHeight();this.selectedIndex=-1;},onLoad:function(){if(!this.hasFocus){return;}
+if(this.store.getCount()>0||this.listEmptyText){this.expand();this.restrictHeight();if(this.lastQuery==this.allQuery){if(this.editable){this.el.dom.select();}
+if(this.autoSelect!==false&&!this.selectByValue(this.value,true)){this.select(0,true);}}else{if(this.autoSelect!==false){this.selectNext();}
+if(this.typeAhead&&this.lastKey!=Ext.EventObject.BACKSPACE&&this.lastKey!=Ext.EventObject.DELETE){this.taTask.delay(this.typeAheadDelay);}}}else{this.collapse();}},onTypeAhead:function(){if(this.store.getCount()>0){var r=this.store.getAt(0);var newValue=r.data[this.displayField];var len=newValue.length;var selStart=this.getRawValue().length;if(selStart!=len){this.setRawValue(newValue);this.selectText(selStart,newValue.length);}}},assertValue:function(){var val=this.getRawValue(),rec;if(this.valueField&&Ext.isDefined(this.value)){rec=this.findRecord(this.valueField,this.value);}
+if(!rec||rec.get(this.displayField)!=val){rec=this.findRecord(this.displayField,val);}
+if(!rec&&this.forceSelection){if(val.length>0&&val!=this.emptyText){this.el.dom.value=Ext.value(this.lastSelectionText,'');this.applyEmptyText();}else{this.clearValue();}}else{if(rec&&this.valueField){if(this.value==val){return;}
+val=rec.get(this.valueField||this.displayField);}
+this.setValue(val);}},onSelect:function(record,index){if(this.fireEvent('beforeselect',this,record,index)!==false){this.setValue(record.data[this.valueField||this.displayField]);this.collapse();this.fireEvent('select',this,record,index);}},getName:function(){var hf=this.hiddenField;return hf&&hf.name?hf.name:this.hiddenName||Ext.form.ComboBox.superclass.getName.call(this);},getValue:function(){if(this.valueField){return Ext.isDefined(this.value)?this.value:'';}else{return Ext.form.ComboBox.superclass.getValue.call(this);}},clearValue:function(){if(this.hiddenField){this.hiddenField.value='';}
+this.setRawValue('');this.lastSelectionText='';this.applyEmptyText();this.value='';},setValue:function(v){var text=v;if(this.valueField){var r=this.findRecord(this.valueField,v);if(r){text=r.data[this.displayField];}else if(Ext.isDefined(this.valueNotFoundText)){text=this.valueNotFoundText;}}
+this.lastSelectionText=text;if(this.hiddenField){this.hiddenField.value=Ext.value(v,'');}
+Ext.form.ComboBox.superclass.setValue.call(this,text);this.value=v;return this;},findRecord:function(prop,value){var record;if(this.store.getCount()>0){this.store.each(function(r){if(r.data[prop]==value){record=r;return false;}});}
+return record;},onViewMove:function(e,t){this.inKeyMode=false;},onViewOver:function(e,t){if(this.inKeyMode){return;}
+var item=this.view.findItemFromChild(t);if(item){var index=this.view.indexOf(item);this.select(index,false);}},onViewClick:function(doFocus){var index=this.view.getSelectedIndexes()[0],s=this.store,r=s.getAt(index);if(r){this.onSelect(r,index);}else{this.collapse();}
+if(doFocus!==false){this.el.focus();}},restrictHeight:function(){this.innerList.dom.style.height='';var inner=this.innerList.dom,pad=this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight,h=Math.max(inner.clientHeight,inner.offsetHeight,inner.scrollHeight),ha=this.getPosition()[1]-Ext.getBody().getScroll().top,hb=Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,space=Math.max(ha,hb,this.minHeight||0)-this.list.shadowOffset-pad-5;h=Math.min(h,space,this.maxHeight);this.innerList.setHeight(h);this.list.beginUpdate();this.list.setHeight(h+pad);this.list.alignTo.apply(this.list,[this.el].concat(this.listAlign));this.list.endUpdate();},isExpanded:function(){return this.list&&this.list.isVisible();},selectByValue:function(v,scrollIntoView){if(!Ext.isEmpty(v,true)){var r=this.findRecord(this.valueField||this.displayField,v);if(r){this.select(this.store.indexOf(r),scrollIntoView);return true;}}
+return false;},select:function(index,scrollIntoView){this.selectedIndex=index;this.view.select(index);if(scrollIntoView!==false){var el=this.view.getNode(index);if(el){this.innerList.scrollChildIntoView(el,false);}}},selectNext:function(){var ct=this.store.getCount();if(ct>0){if(this.selectedIndex==-1){this.select(0);}else if(this.selectedIndex<ct-1){this.select(this.selectedIndex+1);}}},selectPrev:function(){var ct=this.store.getCount();if(ct>0){if(this.selectedIndex==-1){this.select(0);}else if(this.selectedIndex!==0){this.select(this.selectedIndex-1);}}},onKeyUp:function(e){var k=e.getKey();if(this.editable!==false&&this.readOnly!==true&&(k==e.BACKSPACE||!e.isSpecialKey())){this.lastKey=k;this.dqTask.delay(this.queryDelay);}
+Ext.form.ComboBox.superclass.onKeyUp.call(this,e);},validateBlur:function(){return!this.list||!this.list.isVisible();},initQuery:function(){this.doQuery(this.getRawValue());},beforeBlur:function(){this.assertValue();},postBlur:function(){Ext.form.ComboBox.superclass.postBlur.call(this);this.collapse();this.inKeyMode=false;},doQuery:function(q,forceAll){q=Ext.isEmpty(q)?'':q;var qe={query:q,forceAll:forceAll,combo:this,cancel:false};if(this.fireEvent('beforequery',qe)===false||qe.cancel){return false;}
+q=qe.query;forceAll=qe.forceAll;if(forceAll===true||(q.length>=this.minChars)){if(this.lastQuery!==q){this.lastQuery=q;if(this.mode=='local'){this.selectedIndex=-1;if(forceAll){this.store.clearFilter();}else{this.store.filter(this.displayField,q);}
+this.onLoad();}else{this.store.baseParams[this.queryParam]=q;this.store.load({params:this.getParams(q)});this.expand();}}else{this.selectedIndex=-1;this.onLoad();}}},getParams:function(q){var params={},paramNames=this.store.paramNames;if(this.pageSize){params[paramNames.start]=0;params[paramNames.limit]=this.pageSize;}
+return params;},collapse:function(){if(!this.isExpanded()){return;}
+this.list.hide();Ext.getDoc().un('mousewheel',this.collapseIf,this);Ext.getDoc().un('mousedown',this.collapseIf,this);this.fireEvent('collapse',this);},collapseIf:function(e){if(!this.isDestroyed&&!e.within(this.wrap)&&!e.within(this.list)){this.collapse();}},expand:function(){if(this.isExpanded()||!this.hasFocus){return;}
+if(this.title||this.pageSize){this.assetHeight=0;if(this.title){this.assetHeight+=this.header.getHeight();}
+if(this.pageSize){this.assetHeight+=this.footer.getHeight();}}
+if(this.bufferSize){this.doResize(this.bufferSize);delete this.bufferSize;}
+this.list.alignTo.apply(this.list,[this.el].concat(this.listAlign));this.list.setZIndex(this.getZIndex());this.list.show();if(Ext.isGecko2){this.innerList.setOverflow('auto');}
+this.mon(Ext.getDoc(),{scope:this,mousewheel:this.collapseIf,mousedown:this.collapseIf});this.fireEvent('expand',this);},onTriggerClick:function(){if(this.readOnly||this.disabled){return;}
+if(this.isExpanded()){this.collapse();this.el.focus();}else{this.onFocus({});if(this.triggerAction=='all'){this.doQuery(this.allQuery,true);}else{this.doQuery(this.getRawValue());}
+this.el.focus();}}});Ext.reg('combo',Ext.form.ComboBox);Ext.form.Checkbox=Ext.extend(Ext.form.Field,{focusClass:undefined,fieldClass:'x-form-field',checked:false,boxLabel:'&#160;',defaultAutoCreate:{tag:'input',type:'checkbox',autocomplete:'off'},actionMode:'wrap',initComponent:function(){Ext.form.Checkbox.superclass.initComponent.call(this);this.addEvents('check');},onResize:function(){Ext.form.Checkbox.superclass.onResize.apply(this,arguments);if(!this.boxLabel&&!this.fieldLabel){this.el.alignTo(this.wrap,'c-c');}},initEvents:function(){Ext.form.Checkbox.superclass.initEvents.call(this);this.mon(this.el,{scope:this,click:this.onClick,change:this.onClick});},markInvalid:Ext.emptyFn,clearInvalid:Ext.emptyFn,onRender:function(ct,position){Ext.form.Checkbox.superclass.onRender.call(this,ct,position);if(this.inputValue!==undefined){this.el.dom.value=this.inputValue;}
+this.wrap=this.el.wrap({cls:'x-form-check-wrap'});if(this.boxLabel){this.wrap.createChild({tag:'label',htmlFor:this.el.id,cls:'x-form-cb-label',html:this.boxLabel});}
+if(this.checked){this.setValue(true);}else{this.checked=this.el.dom.checked;}
+if(Ext.isIE&&!Ext.isStrict){this.wrap.repaint();}
+this.resizeEl=this.positionEl=this.wrap;},onDestroy:function(){Ext.destroy(this.wrap);Ext.form.Checkbox.superclass.onDestroy.call(this);},initValue:function(){this.originalValue=this.getValue();},getValue:function(){if(this.rendered){return this.el.dom.checked;}
+return this.checked;},onClick:function(){if(this.el.dom.checked!=this.checked){this.setValue(this.el.dom.checked);}},setValue:function(v){var checked=this.checked,inputVal=this.inputValue;this.checked=(v===true||v==='true'||v=='1'||(inputVal?v==inputVal:String(v).toLowerCase()=='on'));if(this.rendered){this.el.dom.checked=this.checked;this.el.dom.defaultChecked=this.checked;}
+if(checked!=this.checked){this.fireEvent('check',this,this.checked);if(this.handler){this.handler.call(this.scope||this,this,this.checked);}}
+return this;}});Ext.reg('checkbox',Ext.form.Checkbox);Ext.form.CheckboxGroup=Ext.extend(Ext.form.Field,{columns:'auto',vertical:false,allowBlank:true,blankText:"You must select at least one item in this group",defaultType:'checkbox',groupCls:'x-form-check-group',initComponent:function(){this.addEvents('change');this.on('change',this.validate,this);Ext.form.CheckboxGroup.superclass.initComponent.call(this);},onRender:function(ct,position){if(!this.el){var panelCfg={autoEl:{id:this.id},cls:this.groupCls,layout:'column',renderTo:ct,bufferResize:false};var colCfg={xtype:'container',defaultType:this.defaultType,layout:'form',defaults:{hideLabel:true,anchor:'100%'}};if(this.items[0].items){Ext.apply(panelCfg,{layoutConfig:{columns:this.items.length},defaults:this.defaults,items:this.items});for(var i=0,len=this.items.length;i<len;i++){Ext.applyIf(this.items[i],colCfg);}}else{var numCols,cols=[];if(typeof this.columns=='string'){this.columns=this.items.length;}
+if(!Ext.isArray(this.columns)){var cs=[];for(var i=0;i<this.columns;i++){cs.push((100/this.columns)*.01);}
+this.columns=cs;}
+numCols=this.columns.length;for(var i=0;i<numCols;i++){var cc=Ext.apply({items:[]},colCfg);cc[this.columns[i]<=1?'columnWidth':'width']=this.columns[i];if(this.defaults){cc.defaults=Ext.apply(cc.defaults||{},this.defaults);}
+cols.push(cc);};if(this.vertical){var rows=Math.ceil(this.items.length/numCols),ri=0;for(var i=0,len=this.items.length;i<len;i++){if(i>0&&i%rows==0){ri++;}
+if(this.items[i].fieldLabel){this.items[i].hideLabel=false;}
+cols[ri].items.push(this.items[i]);};}else{for(var i=0,len=this.items.length;i<len;i++){var ci=i%numCols;if(this.items[i].fieldLabel){this.items[i].hideLabel=false;}
+cols[ci].items.push(this.items[i]);};}
+Ext.apply(panelCfg,{layoutConfig:{columns:numCols},items:cols});}
+this.panel=new Ext.Container(panelCfg);this.panel.ownerCt=this;this.el=this.panel.getEl();if(this.forId&&this.itemCls){var l=this.el.up(this.itemCls).child('label',true);if(l){l.setAttribute('htmlFor',this.forId);}}
+var fields=this.panel.findBy(function(c){return c.isFormField;},this);this.items=new Ext.util.MixedCollection();this.items.addAll(fields);}
+Ext.form.CheckboxGroup.superclass.onRender.call(this,ct,position);},initValue:function(){if(this.value){this.setValue.apply(this,this.buffered?this.value:[this.value]);delete this.buffered;delete this.value;}},afterRender:function(){Ext.form.CheckboxGroup.superclass.afterRender.call(this);this.eachItem(function(item){item.on('check',this.fireChecked,this);item.inGroup=true;});},doLayout:function(){if(this.rendered){this.panel.forceLayout=this.ownerCt.forceLayout;this.panel.doLayout();}},fireChecked:function(){var arr=[];this.eachItem(function(item){if(item.checked){arr.push(item);}});this.fireEvent('change',this,arr);},getErrors:function(){var errors=Ext.form.CheckboxGroup.superclass.getErrors.apply(this,arguments);if(!this.allowBlank){var blank=true;this.eachItem(function(f){if(f.checked){return(blank=false);}});if(blank)errors.push(this.blankText);}
+return errors;},isDirty:function(){if(this.disabled||!this.rendered){return false;}
+var dirty=false;this.eachItem(function(item){if(item.isDirty()){dirty=true;return false;}});return dirty;},setReadOnly:function(readOnly){if(this.rendered){this.eachItem(function(item){item.setReadOnly(readOnly);});}
+this.readOnly=readOnly;},onDisable:function(){this.eachItem(function(item){item.disable();});},onEnable:function(){this.eachItem(function(item){item.enable();});},onResize:function(w,h){this.panel.setSize(w,h);this.panel.doLayout();},reset:function(){if(this.originalValue){this.eachItem(function(c){if(c.setValue){c.setValue(false);c.originalValue=c.getValue();}});this.resetOriginal=true;this.setValue(this.originalValue);delete this.resetOriginal;}else{this.eachItem(function(c){if(c.reset){c.reset();}});}
+(function(){this.clearInvalid();}).defer(50,this);},setValue:function(){if(this.rendered){this.onSetValue.apply(this,arguments);}else{this.buffered=true;this.value=arguments;}
+return this;},onSetValue:function(id,value){if(arguments.length==1){if(Ext.isArray(id)){Ext.each(id,function(val,idx){if(Ext.isObject(val)&&val.setValue){val.setValue(true);if(this.resetOriginal===true){val.originalValue=val.getValue();}}else{var item=this.items.itemAt(idx);if(item){item.setValue(val);}}},this);}else if(Ext.isObject(id)){for(var i in id){var f=this.getBox(i);if(f){f.setValue(id[i]);}}}else{this.setValueForItem(id);}}else{var f=this.getBox(id);if(f){f.setValue(value);}}},beforeDestroy:function(){Ext.destroy(this.panel);if(!this.rendered){Ext.destroy(this.items);}
+Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this);},setValueForItem:function(val){val=String(val).split(',');this.eachItem(function(item){if(val.indexOf(item.inputValue)>-1){item.setValue(true);}});},getBox:function(id){var box=null;this.eachItem(function(f){if(id==f||f.dataIndex==id||f.id==id||f.getName()==id){box=f;return false;}});return box;},getValue:function(){var out=[];this.eachItem(function(item){if(item.checked){out.push(item);}});return out;},eachItem:function(fn,scope){if(this.items&&this.items.each){this.items.each(fn,scope||this);}},getRawValue:Ext.emptyFn,setRawValue:Ext.emptyFn});Ext.reg('checkboxgroup',Ext.form.CheckboxGroup);Ext.form.CompositeField=Ext.extend(Ext.form.Field,{defaultMargins:'0 5 0 0',skipLastItemMargin:true,isComposite:true,combineErrors:true,labelConnector:', ',initComponent:function(){var labels=[],items=this.items,item;for(var i=0,j=items.length;i<j;i++){item=items[i];if(!Ext.isEmpty(item.ref)){item.ref='../'+item.ref;}
+labels.push(item.fieldLabel);Ext.applyIf(item,this.defaults);if(!(i==j-1&&this.skipLastItemMargin)){Ext.applyIf(item,{margins:this.defaultMargins});}}
+this.fieldLabel=this.fieldLabel||this.buildLabel(labels);this.fieldErrors=new Ext.util.MixedCollection(true,function(item){return item.field;});this.fieldErrors.on({scope:this,add:this.updateInvalidMark,remove:this.updateInvalidMark,replace:this.updateInvalidMark});Ext.form.CompositeField.superclass.initComponent.apply(this,arguments);this.innerCt=new Ext.Container({layout:'hbox',items:this.items,cls:'x-form-composite',defaultMargins:'0 3 0 0',ownerCt:this});this.innerCt.ownerCt=undefined;var fields=this.innerCt.findBy(function(c){return c.isFormField;},this);this.items=new Ext.util.MixedCollection();this.items.addAll(fields);},onRender:function(ct,position){if(!this.el){var innerCt=this.innerCt;innerCt.render(ct);this.el=innerCt.getEl();if(this.combineErrors){this.eachItem(function(field){Ext.apply(field,{markInvalid:this.onFieldMarkInvalid.createDelegate(this,[field],0),clearInvalid:this.onFieldClearInvalid.createDelegate(this,[field],0)});});}
+var l=this.el.parent().parent().child('label',true);if(l){l.setAttribute('for',this.items.items[0].id);}}
+Ext.form.CompositeField.superclass.onRender.apply(this,arguments);},onFieldMarkInvalid:function(field,message){var name=field.getName(),error={field:name,errorName:field.fieldLabel||name,error:message};this.fieldErrors.replace(name,error);field.el.addClass(field.invalidClass);},onFieldClearInvalid:function(field){this.fieldErrors.removeKey(field.getName());field.el.removeClass(field.invalidClass);},updateInvalidMark:function(){var ieStrict=Ext.isIE6&&Ext.isStrict;if(this.fieldErrors.length==0){this.clearInvalid();if(ieStrict){this.clearInvalid.defer(50,this);}}else{var message=this.buildCombinedErrorMessage(this.fieldErrors.items);this.sortErrors();this.markInvalid(message);if(ieStrict){this.markInvalid(message);}}},validateValue:function(){var valid=true;this.eachItem(function(field){if(!field.isValid())valid=false;});return valid;},buildCombinedErrorMessage:function(errors){var combined=[],error;for(var i=0,j=errors.length;i<j;i++){error=errors[i];combined.push(String.format("{0}: {1}",error.errorName,error.error));}
+return combined.join("<br />");},sortErrors:function(){var fields=this.items;this.fieldErrors.sort("ASC",function(a,b){var findByName=function(key){return function(field){return field.getName()==key;};};var aIndex=fields.findIndexBy(findByName(a.field)),bIndex=fields.findIndexBy(findByName(b.field));return aIndex<bIndex?-1:1;});},reset:function(){this.eachItem(function(item){item.reset();});(function(){this.clearInvalid();}).defer(50,this);},clearInvalidChildren:function(){this.eachItem(function(item){item.clearInvalid();});},buildLabel:function(segments){return Ext.clean(segments).join(this.labelConnector);},isDirty:function(){if(this.disabled||!this.rendered){return false;}
+var dirty=false;this.eachItem(function(item){if(item.isDirty()){dirty=true;return false;}});return dirty;},eachItem:function(fn,scope){if(this.items&&this.items.each){this.items.each(fn,scope||this);}},onResize:function(adjWidth,adjHeight,rawWidth,rawHeight){var innerCt=this.innerCt;if(this.rendered&&innerCt.rendered){innerCt.setSize(adjWidth,adjHeight);}
+Ext.form.CompositeField.superclass.onResize.apply(this,arguments);},doLayout:function(shallow,force){if(this.rendered){var innerCt=this.innerCt;innerCt.forceLayout=this.ownerCt.forceLayout;innerCt.doLayout(shallow,force);}},beforeDestroy:function(){Ext.destroy(this.innerCt);Ext.form.CompositeField.superclass.beforeDestroy.call(this);},setReadOnly:function(readOnly){if(readOnly==undefined){readOnly=true;}
+readOnly=!!readOnly;if(this.rendered){this.eachItem(function(item){item.setReadOnly(readOnly);});}
+this.readOnly=readOnly;},onShow:function(){Ext.form.CompositeField.superclass.onShow.call(this);this.doLayout();},onDisable:function(){this.eachItem(function(item){item.disable();});},onEnable:function(){this.eachItem(function(item){item.enable();});}});Ext.reg('compositefield',Ext.form.CompositeField);Ext.form.Radio=Ext.extend(Ext.form.Checkbox,{inputType:'radio',markInvalid:Ext.emptyFn,clearInvalid:Ext.emptyFn,getGroupValue:function(){var p=this.el.up('form')||Ext.getBody();var c=p.child('input[name='+this.el.dom.name+']:checked',true);return c?c.value:null;},setValue:function(v){var checkEl,els,radio;if(typeof v=='boolean'){Ext.form.Radio.superclass.setValue.call(this,v);}else if(this.rendered){checkEl=this.getCheckEl();radio=checkEl.child('input[name='+this.el.dom.name+'][value='+v+']',true);if(radio){Ext.getCmp(radio.id).setValue(true);}}
+if(this.rendered&&this.checked){checkEl=checkEl||this.getCheckEl();els=this.getCheckEl().select('input[name='+this.el.dom.name+']');els.each(function(el){if(el.dom.id!=this.id){Ext.getCmp(el.dom.id).setValue(false);}},this);}
+return this;},getCheckEl:function(){if(this.inGroup){return this.el.up('.x-form-radio-group');}
+return this.el.up('form')||Ext.getBody();}});Ext.reg('radio',Ext.form.Radio);Ext.form.RadioGroup=Ext.extend(Ext.form.CheckboxGroup,{allowBlank:true,blankText:'You must select one item in this group',defaultType:'radio',groupCls:'x-form-radio-group',getValue:function(){var out=null;this.eachItem(function(item){if(item.checked){out=item;return false;}});return out;},onSetValue:function(id,value){if(arguments.length>1){var f=this.getBox(id);if(f){f.setValue(value);if(f.checked){this.eachItem(function(item){if(item!==f){item.setValue(false);}});}}}else{this.setValueForItem(id);}},setValueForItem:function(val){val=String(val).split(',')[0];this.eachItem(function(item){item.setValue(val==item.inputValue);});},fireChecked:function(){if(!this.checkTask){this.checkTask=new Ext.util.DelayedTask(this.bufferChecked,this);}
+this.checkTask.delay(10);},bufferChecked:function(){var out=null;this.eachItem(function(item){if(item.checked){out=item;return false;}});this.fireEvent('change',this,out);},onDestroy:function(){if(this.checkTask){this.checkTask.cancel();this.checkTask=null;}
+Ext.form.RadioGroup.superclass.onDestroy.call(this);}});Ext.reg('radiogroup',Ext.form.RadioGroup);Ext.form.Hidden=Ext.extend(Ext.form.Field,{inputType:'hidden',shouldLayout:false,onRender:function(){Ext.form.Hidden.superclass.onRender.apply(this,arguments);},initEvents:function(){this.originalValue=this.getValue();},setSize:Ext.emptyFn,setWidth:Ext.emptyFn,setHeight:Ext.emptyFn,setPosition:Ext.emptyFn,setPagePosition:Ext.emptyFn,markInvalid:Ext.emptyFn,clearInvalid:Ext.emptyFn});Ext.reg('hidden',Ext.form.Hidden);Ext.form.BasicForm=Ext.extend(Ext.util.Observable,{constructor:function(el,config){Ext.apply(this,config);if(Ext.isString(this.paramOrder)){this.paramOrder=this.paramOrder.split(/[\s,|]/);}
+this.items=new Ext.util.MixedCollection(false,function(o){return o.getItemId();});this.addEvents('beforeaction','actionfailed','actioncomplete');if(el){this.initEl(el);}
+Ext.form.BasicForm.superclass.constructor.call(this);},timeout:30,paramOrder:undefined,paramsAsHash:false,waitTitle:'Please Wait...',activeAction:null,trackResetOnLoad:false,initEl:function(el){this.el=Ext.get(el);this.id=this.el.id||Ext.id();if(!this.standardSubmit){this.el.on('submit',this.onSubmit,this);}
+this.el.addClass('x-form');},getEl:function(){return this.el;},onSubmit:function(e){e.stopEvent();},destroy:function(bound){if(bound!==true){this.items.each(function(f){Ext.destroy(f);});Ext.destroy(this.el);}
+this.items.clear();this.purgeListeners();},isValid:function(){var valid=true;this.items.each(function(f){if(!f.validate()){valid=false;}});return valid;},isDirty:function(){var dirty=false;this.items.each(function(f){if(f.isDirty()){dirty=true;return false;}});return dirty;},doAction:function(action,options){if(Ext.isString(action)){action=new Ext.form.Action.ACTION_TYPES[action](this,options);}
+if(this.fireEvent('beforeaction',this,action)!==false){this.beforeAction(action);action.run.defer(100,action);}
+return this;},submit:function(options){options=options||{};if(this.standardSubmit){var v=options.clientValidation===false||this.isValid();if(v){var el=this.el.dom;if(this.url&&Ext.isEmpty(el.action)){el.action=this.url;}
+el.submit();}
+return v;}
+var submitAction=String.format('{0}submit',this.api?'direct':'');this.doAction(submitAction,options);return this;},load:function(options){var loadAction=String.format('{0}load',this.api?'direct':'');this.doAction(loadAction,options);return this;},updateRecord:function(record){record.beginEdit();var fs=record.fields,field,value;fs.each(function(f){field=this.findField(f.name);if(field){value=field.getValue();if(typeof value!=undefined&&value.getGroupValue){value=value.getGroupValue();}else if(field.eachItem){value=[];field.eachItem(function(item){value.push(item.getValue());});}
+record.set(f.name,value);}},this);record.endEdit();return this;},loadRecord:function(record){this.setValues(record.data);return this;},beforeAction:function(action){this.items.each(function(f){if(f.isFormField&&f.syncValue){f.syncValue();}});var o=action.options;if(o.waitMsg){if(this.waitMsgTarget===true){this.el.mask(o.waitMsg,'x-mask-loading');}else if(this.waitMsgTarget){this.waitMsgTarget=Ext.get(this.waitMsgTarget);this.waitMsgTarget.mask(o.waitMsg,'x-mask-loading');}else{Ext.MessageBox.wait(o.waitMsg,o.waitTitle||this.waitTitle);}}},afterAction:function(action,success){this.activeAction=null;var o=action.options;if(o.waitMsg){if(this.waitMsgTarget===true){this.el.unmask();}else if(this.waitMsgTarget){this.waitMsgTarget.unmask();}else{Ext.MessageBox.updateProgress(1);Ext.MessageBox.hide();}}
+if(success){if(o.reset){this.reset();}
+Ext.callback(o.success,o.scope,[this,action]);this.fireEvent('actioncomplete',this,action);}else{Ext.callback(o.failure,o.scope,[this,action]);this.fireEvent('actionfailed',this,action);}},findField:function(id){var field=this.items.get(id);if(!Ext.isObject(field)){var findMatchingField=function(f){if(f.isFormField){if(f.dataIndex==id||f.id==id||f.getName()==id){field=f;return false;}else if(f.isComposite){return f.items.each(findMatchingField);}else if(f instanceof Ext.form.CheckboxGroup&&f.rendered){return f.eachItem(findMatchingField);}}};this.items.each(findMatchingField);}
+return field||null;},markInvalid:function(errors){if(Ext.isArray(errors)){for(var i=0,len=errors.length;i<len;i++){var fieldError=errors[i];var f=this.findField(fieldError.id);if(f){f.markInvalid(fieldError.msg);}}}else{var field,id;for(id in errors){if(!Ext.isFunction(errors[id])&&(field=this.findField(id))){field.markInvalid(errors[id]);}}}
+return this;},setValues:function(values){if(Ext.isArray(values)){for(var i=0,len=values.length;i<len;i++){var v=values[i];var f=this.findField(v.id);if(f){f.setValue(v.value);if(this.trackResetOnLoad){f.originalValue=f.getValue();}}}}else{var field,id;for(id in values){if(!Ext.isFunction(values[id])&&(field=this.findField(id))){field.setValue(values[id]);if(this.trackResetOnLoad){field.originalValue=field.getValue();}}}}
+return this;},getValues:function(asString){var fs=Ext.lib.Ajax.serializeForm(this.el.dom);if(asString===true){return fs;}
+return Ext.urlDecode(fs);},getFieldValues:function(dirtyOnly){var o={},n,key,val;this.items.each(function(f){if(!f.disabled&&(dirtyOnly!==true||f.isDirty())){n=f.getName();key=o[n];val=f.getValue();if(Ext.isDefined(key)){if(Ext.isArray(key)){o[n].push(val);}else{o[n]=[key,val];}}else{o[n]=val;}}});return o;},clearInvalid:function(){this.items.each(function(f){f.clearInvalid();});return this;},reset:function(){this.items.each(function(f){f.reset();});return this;},add:function(){this.items.addAll(Array.prototype.slice.call(arguments,0));return this;},remove:function(field){this.items.remove(field);return this;},cleanDestroyed:function(){this.items.filterBy(function(o){return!!o.isDestroyed;}).each(this.remove,this);},render:function(){this.items.each(function(f){if(f.isFormField&&!f.rendered&&document.getElementById(f.id)){f.applyToMarkup(f.id);}});return this;},applyToFields:function(o){this.items.each(function(f){Ext.apply(f,o);});return this;},applyIfToFields:function(o){this.items.each(function(f){Ext.applyIf(f,o);});return this;},callFieldMethod:function(fnName,args){args=args||[];this.items.each(function(f){if(Ext.isFunction(f[fnName])){f[fnName].apply(f,args);}});return this;}});Ext.BasicForm=Ext.form.BasicForm;Ext.FormPanel=Ext.extend(Ext.Panel,{minButtonWidth:75,labelAlign:'left',monitorValid:false,monitorPoll:200,layout:'form',initComponent:function(){this.form=this.createForm();Ext.FormPanel.superclass.initComponent.call(this);this.bodyCfg={tag:'form',cls:this.baseCls+'-body',method:this.method||'POST',id:this.formId||Ext.id()};if(this.fileUpload){this.bodyCfg.enctype='multipart/form-data';}
+this.initItems();this.addEvents('clientvalidation');this.relayEvents(this.form,['beforeaction','actionfailed','actioncomplete']);},createForm:function(){var config=Ext.applyIf({listeners:{}},this.initialConfig);return new Ext.form.BasicForm(null,config);},initFields:function(){var f=this.form;var formPanel=this;var fn=function(c){if(formPanel.isField(c)){f.add(c);}else if(c.findBy&&c!=formPanel){formPanel.applySettings(c);if(c.items&&c.items.each){c.items.each(fn,this);}}};this.items.each(fn,this);},applySettings:function(c){var ct=c.ownerCt;Ext.applyIf(c,{labelAlign:ct.labelAlign,labelWidth:ct.labelWidth,itemCls:ct.itemCls});},getLayoutTarget:function(){return this.form.el;},getForm:function(){return this.form;},onRender:function(ct,position){this.initFields();Ext.FormPanel.superclass.onRender.call(this,ct,position);this.form.initEl(this.body);},beforeDestroy:function(){this.stopMonitoring();this.form.destroy(true);Ext.FormPanel.superclass.beforeDestroy.call(this);},isField:function(c){return!!c.setValue&&!!c.getValue&&!!c.markInvalid&&!!c.clearInvalid;},initEvents:function(){Ext.FormPanel.superclass.initEvents.call(this);this.on({scope:this,add:this.onAddEvent,remove:this.onRemoveEvent});if(this.monitorValid){this.startMonitoring();}},onAdd:function(c){Ext.FormPanel.superclass.onAdd.call(this,c);this.processAdd(c);},onAddEvent:function(ct,c){if(ct!==this){this.processAdd(c);}},processAdd:function(c){if(this.isField(c)){this.form.add(c);}else if(c.findBy){this.applySettings(c);this.form.add.apply(this.form,c.findBy(this.isField));}},onRemove:function(c){Ext.FormPanel.superclass.onRemove.call(this,c);this.processRemove(c);},onRemoveEvent:function(ct,c){if(ct!==this){this.processRemove(c);}},processRemove:function(c){if(!this.destroying){if(this.isField(c)){this.form.remove(c);}else if(c.findBy){Ext.each(c.findBy(this.isField),this.form.remove,this.form);this.form.cleanDestroyed();}}},startMonitoring:function(){if(!this.validTask){this.validTask=new Ext.util.TaskRunner();this.validTask.start({run:this.bindHandler,interval:this.monitorPoll||200,scope:this});}},stopMonitoring:function(){if(this.validTask){this.validTask.stopAll();this.validTask=null;}},load:function(){this.form.load.apply(this.form,arguments);},onDisable:function(){Ext.FormPanel.superclass.onDisable.call(this);if(this.form){this.form.items.each(function(){this.disable();});}},onEnable:function(){Ext.FormPanel.superclass.onEnable.call(this);if(this.form){this.form.items.each(function(){this.enable();});}},bindHandler:function(){var valid=true;this.form.items.each(function(f){if(!f.isValid(true)){valid=false;return false;}});if(this.fbar){var fitems=this.fbar.items.items;for(var i=0,len=fitems.length;i<len;i++){var btn=fitems[i];if(btn.formBind===true&&btn.disabled===valid){btn.setDisabled(!valid);}}}
+this.fireEvent('clientvalidation',this,valid);}});Ext.reg('form',Ext.FormPanel);Ext.form.FormPanel=Ext.FormPanel;Ext.form.FieldSet=Ext.extend(Ext.Panel,{baseCls:'x-fieldset',layout:'form',animCollapse:false,onRender:function(ct,position){if(!this.el){this.el=document.createElement('fieldset');this.el.id=this.id;if(this.title||this.header||this.checkboxToggle){this.el.appendChild(document.createElement('legend')).className=this.baseCls+'-header';}}
+Ext.form.FieldSet.superclass.onRender.call(this,ct,position);if(this.checkboxToggle){var o=typeof this.checkboxToggle=='object'?this.checkboxToggle:{tag:'input',type:'checkbox',name:this.checkboxName||this.id+'-checkbox'};this.checkbox=this.header.insertFirst(o);this.checkbox.dom.checked=!this.collapsed;this.mon(this.checkbox,'click',this.onCheckClick,this);}},onCollapse:function(doAnim,animArg){if(this.checkbox){this.checkbox.dom.checked=false;}
+Ext.form.FieldSet.superclass.onCollapse.call(this,doAnim,animArg);},onExpand:function(doAnim,animArg){if(this.checkbox){this.checkbox.dom.checked=true;}
+Ext.form.FieldSet.superclass.onExpand.call(this,doAnim,animArg);},onCheckClick:function(){this[this.checkbox.dom.checked?'expand':'collapse']();}});Ext.reg('fieldset',Ext.form.FieldSet);Ext.form.HtmlEditor=Ext.extend(Ext.form.Field,{enableFormat:true,enableFontSize:true,enableColors:true,enableAlignments:true,enableLists:true,enableSourceEdit:true,enableLinks:true,enableFont:true,createLinkText:'Please enter the URL for the link:',defaultLinkValue:'http:/'+'/',fontFamilies:['Arial','Courier New','Tahoma','Times New Roman','Verdana'],defaultFont:'tahoma',defaultValue:(Ext.isOpera||Ext.isIE6)?'&#160;':'&#8203;',actionMode:'wrap',validationEvent:false,deferHeight:true,initialized:false,activated:false,sourceEditMode:false,onFocus:Ext.emptyFn,iframePad:3,hideMode:'offsets',defaultAutoCreate:{tag:"textarea",style:"width:500px;height:300px;",autocomplete:"off"},initComponent:function(){this.addEvents('initialize','activate','beforesync','beforepush','sync','push','editmodechange');Ext.form.HtmlEditor.superclass.initComponent.call(this);},createFontOptions:function(){var buf=[],fs=this.fontFamilies,ff,lc;for(var i=0,len=fs.length;i<len;i++){ff=fs[i];lc=ff.toLowerCase();buf.push('<option value="',lc,'" style="font-family:',ff,';"',(this.defaultFont==lc?' selected="true">':'>'),ff,'</option>');}
+return buf.join('');},createToolbar:function(editor){var items=[];var tipsEnabled=Ext.QuickTips&&Ext.QuickTips.isEnabled();function btn(id,toggle,handler){return{itemId:id,cls:'x-btn-icon',iconCls:'x-edit-'+id,enableToggle:toggle!==false,scope:editor,handler:handler||editor.relayBtnCmd,clickEvent:'mousedown',tooltip:tipsEnabled?editor.buttonTips[id]||undefined:undefined,overflowText:editor.buttonTips[id].title||undefined,tabIndex:-1};}
+if(this.enableFont&&!Ext.isSafari2){var fontSelectItem=new Ext.Toolbar.Item({autoEl:{tag:'select',cls:'x-font-select',html:this.createFontOptions()}});items.push(fontSelectItem,'-');}
+if(this.enableFormat){items.push(btn('bold'),btn('italic'),btn('underline'));}
+if(this.enableFontSize){items.push('-',btn('increasefontsize',false,this.adjustFont),btn('decreasefontsize',false,this.adjustFont));}
+if(this.enableColors){items.push('-',{itemId:'forecolor',cls:'x-btn-icon',iconCls:'x-edit-forecolor',clickEvent:'mousedown',tooltip:tipsEnabled?editor.buttonTips.forecolor||undefined:undefined,tabIndex:-1,menu:new Ext.menu.ColorMenu({allowReselect:true,focus:Ext.emptyFn,value:'000000',plain:true,listeners:{scope:this,select:function(cp,color){this.execCmd('forecolor',Ext.isWebKit||Ext.isIE?'#'+color:color);this.deferFocus();}},clickEvent:'mousedown'})},{itemId:'backcolor',cls:'x-btn-icon',iconCls:'x-edit-backcolor',clickEvent:'mousedown',tooltip:tipsEnabled?editor.buttonTips.backcolor||undefined:undefined,tabIndex:-1,menu:new Ext.menu.ColorMenu({focus:Ext.emptyFn,value:'FFFFFF',plain:true,allowReselect:true,listeners:{scope:this,select:function(cp,color){if(Ext.isGecko){this.execCmd('useCSS',false);this.execCmd('hilitecolor',color);this.execCmd('useCSS',true);this.deferFocus();}else{this.execCmd(Ext.isOpera?'hilitecolor':'backcolor',Ext.isWebKit||Ext.isIE?'#'+color:color);this.deferFocus();}}},clickEvent:'mousedown'})});}
+if(this.enableAlignments){items.push('-',btn('justifyleft'),btn('justifycenter'),btn('justifyright'));}
+if(!Ext.isSafari2){if(this.enableLinks){items.push('-',btn('createlink',false,this.createLink));}
+if(this.enableLists){items.push('-',btn('insertorderedlist'),btn('insertunorderedlist'));}
+if(this.enableSourceEdit){items.push('-',btn('sourceedit',true,function(btn){this.toggleSourceEdit(!this.sourceEditMode);}));}}
+var tb=new Ext.Toolbar({renderTo:this.wrap.dom.firstChild,items:items});if(fontSelectItem){this.fontSelect=fontSelectItem.el;this.mon(this.fontSelect,'change',function(){var font=this.fontSelect.dom.value;this.relayCmd('fontname',font);this.deferFocus();},this);}
+this.mon(tb.el,'click',function(e){e.preventDefault();});this.tb=tb;this.tb.doLayout();},onDisable:function(){this.wrap.mask();Ext.form.HtmlEditor.superclass.onDisable.call(this);},onEnable:function(){this.wrap.unmask();Ext.form.HtmlEditor.superclass.onEnable.call(this);},setReadOnly:function(readOnly){Ext.form.HtmlEditor.superclass.setReadOnly.call(this,readOnly);if(this.initialized){if(Ext.isIE){this.getEditorBody().contentEditable=!readOnly;}else{this.setDesignMode(!readOnly);}
+var bd=this.getEditorBody();if(bd){bd.style.cursor=this.readOnly?'default':'text';}
+this.disableItems(readOnly);}},getDocMarkup:function(){var h=Ext.fly(this.iframe).getHeight()-this.iframePad*2;return String.format('<html><head><style type="text/css">body{border: 0; margin: 0; padding: {0}px; height: {1}px; cursor: text}</style></head><body></body></html>',this.iframePad,h);},getEditorBody:function(){var doc=this.getDoc();return doc.body||doc.documentElement;},getDoc:function(){return Ext.isIE?this.getWin().document:(this.iframe.contentDocument||this.getWin().document);},getWin:function(){return Ext.isIE?this.iframe.contentWindow:window.frames[this.iframe.name];},onRender:function(ct,position){Ext.form.HtmlEditor.superclass.onRender.call(this,ct,position);this.el.dom.style.border='0 none';this.el.dom.setAttribute('tabIndex',-1);this.el.addClass('x-hidden');if(Ext.isIE){this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;');}
+this.wrap=this.el.wrap({cls:'x-html-editor-wrap',cn:{cls:'x-html-editor-tb'}});this.createToolbar(this);this.disableItems(true);this.tb.doLayout();this.createIFrame();if(!this.width){var sz=this.el.getSize();this.setSize(sz.width,this.height||sz.height);}
+this.resizeEl=this.positionEl=this.wrap;},createIFrame:function(){var iframe=document.createElement('iframe');iframe.name=Ext.id();iframe.frameBorder='0';iframe.style.overflow='auto';iframe.src=Ext.SSL_SECURE_URL;this.wrap.dom.appendChild(iframe);this.iframe=iframe;this.monitorTask=Ext.TaskMgr.start({run:this.checkDesignMode,scope:this,interval:100});},initFrame:function(){Ext.TaskMgr.stop(this.monitorTask);var doc=this.getDoc();this.win=this.getWin();doc.open();doc.write(this.getDocMarkup());doc.close();var task={run:function(){var doc=this.getDoc();if(doc.body||doc.readyState=='complete'){Ext.TaskMgr.stop(task);this.setDesignMode(true);this.initEditor.defer(10,this);}},interval:10,duration:10000,scope:this};Ext.TaskMgr.start(task);},checkDesignMode:function(){if(this.wrap&&this.wrap.dom.offsetWidth){var doc=this.getDoc();if(!doc){return;}
+if(!doc.editorInitialized||this.getDesignMode()!='on'){this.initFrame();}}},setDesignMode:function(mode){var doc=this.getDoc();if(doc){if(this.readOnly){mode=false;}
+doc.designMode=(/on|true/i).test(String(mode).toLowerCase())?'on':'off';}},getDesignMode:function(){var doc=this.getDoc();if(!doc){return'';}
+return String(doc.designMode).toLowerCase();},disableItems:function(disabled){if(this.fontSelect){this.fontSelect.dom.disabled=disabled;}
+this.tb.items.each(function(item){if(item.getItemId()!='sourceedit'){item.setDisabled(disabled);}});},onResize:function(w,h){Ext.form.HtmlEditor.superclass.onResize.apply(this,arguments);if(this.el&&this.iframe){if(Ext.isNumber(w)){var aw=w-this.wrap.getFrameWidth('lr');this.el.setWidth(aw);this.tb.setWidth(aw);this.iframe.style.width=Math.max(aw,0)+'px';}
+if(Ext.isNumber(h)){var ah=h-this.wrap.getFrameWidth('tb')-this.tb.el.getHeight();this.el.setHeight(ah);this.iframe.style.height=Math.max(ah,0)+'px';var bd=this.getEditorBody();if(bd){bd.style.height=Math.max((ah-(this.iframePad*2)),0)+'px';}}}},toggleSourceEdit:function(sourceEditMode){var iframeHeight,elHeight;if(sourceEditMode===undefined){sourceEditMode=!this.sourceEditMode;}
+this.sourceEditMode=sourceEditMode===true;var btn=this.tb.getComponent('sourceedit');if(btn.pressed!==this.sourceEditMode){btn.toggle(this.sourceEditMode);if(!btn.xtbHidden){return;}}
+if(this.sourceEditMode){this.previousSize=this.getSize();iframeHeight=Ext.get(this.iframe).getHeight();this.disableItems(true);this.syncValue();this.iframe.className='x-hidden';this.el.removeClass('x-hidden');this.el.dom.removeAttribute('tabIndex');this.el.focus();this.el.dom.style.height=iframeHeight+'px';}
+else{elHeight=parseInt(this.el.dom.style.height,10);if(this.initialized){this.disableItems(this.readOnly);}
+this.pushValue();this.iframe.className='';this.el.addClass('x-hidden');this.el.dom.setAttribute('tabIndex',-1);this.deferFocus();this.setSize(this.previousSize);delete this.previousSize;this.iframe.style.height=elHeight+'px';}
+this.fireEvent('editmodechange',this,this.sourceEditMode);},createLink:function(){var url=prompt(this.createLinkText,this.defaultLinkValue);if(url&&url!='http:/'+'/'){this.relayCmd('createlink',url);}},initEvents:function(){this.originalValue=this.getValue();},markInvalid:Ext.emptyFn,clearInvalid:Ext.emptyFn,setValue:function(v){Ext.form.HtmlEditor.superclass.setValue.call(this,v);this.pushValue();return this;},cleanHtml:function(html){html=String(html);if(Ext.isWebKit){html=html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi,'');}
+if(html.charCodeAt(0)==this.defaultValue.replace(/\D/g,'')){html=html.substring(1);}
+return html;},syncValue:function(){if(this.initialized){var bd=this.getEditorBody();var html=bd.innerHTML;if(Ext.isWebKit){var bs=bd.getAttribute('style');var m=bs.match(/text-align:(.*?);/i);if(m&&m[1]){html='<div style="'+m[0]+'">'+html+'</div>';}}
+html=this.cleanHtml(html);if(this.fireEvent('beforesync',this,html)!==false){this.el.dom.value=html;this.fireEvent('sync',this,html);}}},getValue:function(){this[this.sourceEditMode?'pushValue':'syncValue']();return Ext.form.HtmlEditor.superclass.getValue.call(this);},pushValue:function(){if(this.initialized){var v=this.el.dom.value;if(!this.activated&&v.length<1){v=this.defaultValue;}
+if(this.fireEvent('beforepush',this,v)!==false){this.getEditorBody().innerHTML=v;if(Ext.isGecko){this.setDesignMode(false);this.setDesignMode(true);}
+this.fireEvent('push',this,v);}}},deferFocus:function(){this.focus.defer(10,this);},focus:function(){if(this.win&&!this.sourceEditMode){this.win.focus();}else{this.el.focus();}},initEditor:function(){try{var dbody=this.getEditorBody(),ss=this.el.getStyles('font-size','font-family','background-image','background-repeat','background-color','color'),doc,fn;ss['background-attachment']='fixed';dbody.bgProperties='fixed';Ext.DomHelper.applyStyles(dbody,ss);doc=this.getDoc();if(doc){try{Ext.EventManager.removeAll(doc);}catch(e){}}
+fn=this.onEditorEvent.createDelegate(this);Ext.EventManager.on(doc,{mousedown:fn,dblclick:fn,click:fn,keyup:fn,buffer:100});if(Ext.isGecko){Ext.EventManager.on(doc,'keypress',this.applyCommand,this);}
+if(Ext.isIE||Ext.isWebKit||Ext.isOpera){Ext.EventManager.on(doc,'keydown',this.fixKeys,this);}
+doc.editorInitialized=true;this.initialized=true;this.pushValue();this.setReadOnly(this.readOnly);this.fireEvent('initialize',this);}catch(e){}},beforeDestroy:function(){if(this.monitorTask){Ext.TaskMgr.stop(this.monitorTask);}
+if(this.rendered){Ext.destroy(this.tb);var doc=this.getDoc();if(doc){try{Ext.EventManager.removeAll(doc);for(var prop in doc){delete doc[prop];}}catch(e){}}
+if(this.wrap){this.wrap.dom.innerHTML='';this.wrap.remove();}}
+Ext.form.HtmlEditor.superclass.beforeDestroy.call(this);},onFirstFocus:function(){this.activated=true;this.disableItems(this.readOnly);if(Ext.isGecko){this.win.focus();var s=this.win.getSelection();if(!s.focusNode||s.focusNode.nodeType!=3){var r=s.getRangeAt(0);r.selectNodeContents(this.getEditorBody());r.collapse(true);this.deferFocus();}
+try{this.execCmd('useCSS',true);this.execCmd('styleWithCSS',false);}catch(e){}}
+this.fireEvent('activate',this);},adjustFont:function(btn){var adjust=btn.getItemId()=='increasefontsize'?1:-1,doc=this.getDoc(),v=parseInt(doc.queryCommandValue('FontSize')||2,10);if((Ext.isSafari&&!Ext.isSafari2)||Ext.isChrome||Ext.isAir){if(v<=10){v=1+adjust;}else if(v<=13){v=2+adjust;}else if(v<=16){v=3+adjust;}else if(v<=18){v=4+adjust;}else if(v<=24){v=5+adjust;}else{v=6+adjust;}
+v=v.constrain(1,6);}else{if(Ext.isSafari){adjust*=2;}
+v=Math.max(1,v+adjust)+(Ext.isSafari?'px':0);}
+this.execCmd('FontSize',v);},onEditorEvent:function(e){this.updateToolbar();},updateToolbar:function(){if(this.readOnly){return;}
+if(!this.activated){this.onFirstFocus();return;}
+var btns=this.tb.items.map,doc=this.getDoc();if(this.enableFont&&!Ext.isSafari2){var name=(doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();if(name!=this.fontSelect.dom.value){this.fontSelect.dom.value=name;}}
+if(this.enableFormat){btns.bold.toggle(doc.queryCommandState('bold'));btns.italic.toggle(doc.queryCommandState('italic'));btns.underline.toggle(doc.queryCommandState('underline'));}
+if(this.enableAlignments){btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));btns.justifyright.toggle(doc.queryCommandState('justifyright'));}
+if(!Ext.isSafari2&&this.enableLists){btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));}
+Ext.menu.MenuMgr.hideAll();this.syncValue();},relayBtnCmd:function(btn){this.relayCmd(btn.getItemId());},relayCmd:function(cmd,value){(function(){this.focus();this.execCmd(cmd,value);this.updateToolbar();}).defer(10,this);},execCmd:function(cmd,value){var doc=this.getDoc();doc.execCommand(cmd,false,value===undefined?null:value);this.syncValue();},applyCommand:function(e){if(e.ctrlKey){var c=e.getCharCode(),cmd;if(c>0){c=String.fromCharCode(c);switch(c){case'b':cmd='bold';break;case'i':cmd='italic';break;case'u':cmd='underline';break;}
+if(cmd){this.win.focus();this.execCmd(cmd);this.deferFocus();e.preventDefault();}}}},insertAtCursor:function(text){if(!this.activated){return;}
+if(Ext.isIE){this.win.focus();var doc=this.getDoc(),r=doc.selection.createRange();if(r){r.pasteHTML(text);this.syncValue();this.deferFocus();}}else{this.win.focus();this.execCmd('InsertHTML',text);this.deferFocus();}},fixKeys:function(){if(Ext.isIE){return function(e){var k=e.getKey(),doc=this.getDoc(),r;if(k==e.TAB){e.stopEvent();r=doc.selection.createRange();if(r){r.collapse(true);r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');this.deferFocus();}}else if(k==e.ENTER){r=doc.selection.createRange();if(r){var target=r.parentElement();if(!target||target.tagName.toLowerCase()!='li'){e.stopEvent();r.pasteHTML('<br />');r.collapse(false);r.select();}}}};}else if(Ext.isOpera){return function(e){var k=e.getKey();if(k==e.TAB){e.stopEvent();this.win.focus();this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');this.deferFocus();}};}else if(Ext.isWebKit){return function(e){var k=e.getKey();if(k==e.TAB){e.stopEvent();this.execCmd('InsertText','\t');this.deferFocus();}else if(k==e.ENTER){e.stopEvent();this.execCmd('InsertHtml','<br /><br />');this.deferFocus();}};}}(),getToolbar:function(){return this.tb;},buttonTips:{bold:{title:'Bold (Ctrl+B)',text:'Make the selected text bold.',cls:'x-html-editor-tip'},italic:{title:'Italic (Ctrl+I)',text:'Make the selected text italic.',cls:'x-html-editor-tip'},underline:{title:'Underline (Ctrl+U)',text:'Underline the selected text.',cls:'x-html-editor-tip'},increasefontsize:{title:'Grow Text',text:'Increase the font size.',cls:'x-html-editor-tip'},decreasefontsize:{title:'Shrink Text',text:'Decrease the font size.',cls:'x-html-editor-tip'},backcolor:{title:'Text Highlight Color',text:'Change the background color of the selected text.',cls:'x-html-editor-tip'},forecolor:{title:'Font Color',text:'Change the color of the selected text.',cls:'x-html-editor-tip'},justifyleft:{title:'Align Text Left',text:'Align text to the left.',cls:'x-html-editor-tip'},justifycenter:{title:'Center Text',text:'Center text in the editor.',cls:'x-html-editor-tip'},justifyright:{title:'Align Text Right',text:'Align text to the right.',cls:'x-html-editor-tip'},insertunorderedlist:{title:'Bullet List',text:'Start a bulleted list.',cls:'x-html-editor-tip'},insertorderedlist:{title:'Numbered List',text:'Start a numbered list.',cls:'x-html-editor-tip'},createlink:{title:'Hyperlink',text:'Make the selected text a hyperlink.',cls:'x-html-editor-tip'},sourceedit:{title:'Source Edit',text:'Switch to source editing mode.',cls:'x-html-editor-tip'}}});Ext.reg('htmleditor',Ext.form.HtmlEditor);Ext.form.TimeField=Ext.extend(Ext.form.ComboBox,{minValue:undefined,maxValue:undefined,minText:"The time in this field must be equal to or after {0}",maxText:"The time in this field must be equal to or before {0}",invalidText:"{0} is not a valid time",format:"g:i A",altFormats:"g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A",increment:15,mode:'local',triggerAction:'all',typeAhead:false,initDate:'1/1/2008',initDateFormat:'j/n/Y',initComponent:function(){if(Ext.isDefined(this.minValue)){this.setMinValue(this.minValue,true);}
+if(Ext.isDefined(this.maxValue)){this.setMaxValue(this.maxValue,true);}
+if(!this.store){this.generateStore(true);}
+Ext.form.TimeField.superclass.initComponent.call(this);},setMinValue:function(value,initial){this.setLimit(value,true,initial);return this;},setMaxValue:function(value,initial){this.setLimit(value,false,initial);return this;},generateStore:function(initial){var min=this.minValue||new Date(this.initDate).clearTime(),max=this.maxValue||new Date(this.initDate).clearTime().add('mi',(24*60)-1),times=[];while(min<=max){times.push(min.dateFormat(this.format));min=min.add('mi',this.increment);}
+this.bindStore(times,initial);},setLimit:function(value,isMin,initial){var d;if(Ext.isString(value)){d=this.parseDate(value);}else if(Ext.isDate(value)){d=value;}
+if(d){var val=new Date(this.initDate).clearTime();val.setHours(d.getHours(),d.getMinutes(),d.getSeconds(),d.getMilliseconds());this[isMin?'minValue':'maxValue']=val;if(!initial){this.generateStore();}}},getValue:function(){var v=Ext.form.TimeField.superclass.getValue.call(this);return this.formatDate(this.parseDate(v))||'';},setValue:function(value){return Ext.form.TimeField.superclass.setValue.call(this,this.formatDate(this.parseDate(value)));},validateValue:Ext.form.DateField.prototype.validateValue,formatDate:Ext.form.DateField.prototype.formatDate,parseDate:function(value){if(!value||Ext.isDate(value)){return value;}
+var id=this.initDate+' ',idf=this.initDateFormat+' ',v=Date.parseDate(id+value,idf+this.format),af=this.altFormats;if(!v&&af){if(!this.altFormatsArray){this.altFormatsArray=af.split("|");}
+for(var i=0,afa=this.altFormatsArray,len=afa.length;i<len&&!v;i++){v=Date.parseDate(id+value,idf+afa[i]);}}
+return v;}});Ext.reg('timefield',Ext.form.TimeField);Ext.form.SliderField=Ext.extend(Ext.form.Field,{useTips:true,tipText:null,actionMode:'wrap',initComponent:function(){var cfg=Ext.copyTo({id:this.id+'-slider'},this.initialConfig,['vertical','minValue','maxValue','decimalPrecision','keyIncrement','increment','clickToChange','animate']);if(this.useTips){var plug=this.tipText?{getText:this.tipText}:{};cfg.plugins=[new Ext.slider.Tip(plug)];}
+this.slider=new Ext.Slider(cfg);Ext.form.SliderField.superclass.initComponent.call(this);},onRender:function(ct,position){this.autoCreate={id:this.id,name:this.name,type:'hidden',tag:'input'};Ext.form.SliderField.superclass.onRender.call(this,ct,position);this.wrap=this.el.wrap({cls:'x-form-field-wrap'});this.resizeEl=this.positionEl=this.wrap;this.slider.render(this.wrap);},onResize:function(w,h,aw,ah){Ext.form.SliderField.superclass.onResize.call(this,w,h,aw,ah);this.slider.setSize(w,h);},initEvents:function(){Ext.form.SliderField.superclass.initEvents.call(this);this.slider.on('change',this.onChange,this);},onChange:function(slider,v){this.setValue(v,undefined,true);},onEnable:function(){Ext.form.SliderField.superclass.onEnable.call(this);this.slider.enable();},onDisable:function(){Ext.form.SliderField.superclass.onDisable.call(this);this.slider.disable();},beforeDestroy:function(){Ext.destroy(this.slider);Ext.form.SliderField.superclass.beforeDestroy.call(this);},alignErrorIcon:function(){this.errorIcon.alignTo(this.slider.el,'tl-tr',[2,0]);},setMinValue:function(v){this.slider.setMinValue(v);return this;},setMaxValue:function(v){this.slider.setMaxValue(v);return this;},setValue:function(v,animate,silent){if(!silent){this.slider.setValue(v,animate);}
+return Ext.form.SliderField.superclass.setValue.call(this,this.slider.getValue());},getValue:function(){return this.slider.getValue();}});Ext.reg('sliderfield',Ext.form.SliderField);Ext.form.Label=Ext.extend(Ext.BoxComponent,{onRender:function(ct,position){if(!this.el){this.el=document.createElement('label');this.el.id=this.getId();this.el.innerHTML=this.text?Ext.util.Format.htmlEncode(this.text):(this.html||'');if(this.forId){this.el.setAttribute('for',this.forId);}}
+Ext.form.Label.superclass.onRender.call(this,ct,position);},setText:function(t,encode){var e=encode===false;this[!e?'text':'html']=t;delete this[e?'text':'html'];if(this.rendered){this.el.dom.innerHTML=encode!==false?Ext.util.Format.htmlEncode(t):t;}
+return this;}});Ext.reg('label',Ext.form.Label);Ext.form.Action=function(form,options){this.form=form;this.options=options||{};};Ext.form.Action.CLIENT_INVALID='client';Ext.form.Action.SERVER_INVALID='server';Ext.form.Action.CONNECT_FAILURE='connect';Ext.form.Action.LOAD_FAILURE='load';Ext.form.Action.prototype={type:'default',run:function(options){},success:function(response){},handleResponse:function(response){},failure:function(response){this.response=response;this.failureType=Ext.form.Action.CONNECT_FAILURE;this.form.afterAction(this,false);},processResponse:function(response){this.response=response;if(!response.responseText&&!response.responseXML){return true;}
+this.result=this.handleResponse(response);return this.result;},getUrl:function(appendParams){var url=this.options.url||this.form.url||this.form.el.dom.action;if(appendParams){var p=this.getParams();if(p){url=Ext.urlAppend(url,p);}}
+return url;},getMethod:function(){return(this.options.method||this.form.method||this.form.el.dom.method||'POST').toUpperCase();},getParams:function(){var bp=this.form.baseParams;var p=this.options.params;if(p){if(typeof p=="object"){p=Ext.urlEncode(Ext.applyIf(p,bp));}else if(typeof p=='string'&&bp){p+='&'+Ext.urlEncode(bp);}}else if(bp){p=Ext.urlEncode(bp);}
+return p;},createCallback:function(opts){var opts=opts||{};return{success:this.success,failure:this.failure,scope:this,timeout:(opts.timeout*1000)||(this.form.timeout*1000),upload:this.form.fileUpload?this.success:undefined};}};Ext.form.Action.Submit=function(form,options){Ext.form.Action.Submit.superclass.constructor.call(this,form,options);};Ext.extend(Ext.form.Action.Submit,Ext.form.Action,{type:'submit',run:function(){var o=this.options,method=this.getMethod(),isGet=method=='GET';if(o.clientValidation===false||this.form.isValid()){if(o.submitEmptyText===false){var fields=this.form.items,emptyFields=[],setupEmptyFields=function(f){if(f.el.getValue()==f.emptyText){emptyFields.push(f);f.el.dom.value="";}
+if(f.isComposite&&f.rendered){f.items.each(setupEmptyFields);}};fields.each(setupEmptyFields);}
+Ext.Ajax.request(Ext.apply(this.createCallback(o),{form:this.form.el.dom,url:this.getUrl(isGet),method:method,headers:o.headers,params:!isGet?this.getParams():null,isUpload:this.form.fileUpload}));if(o.submitEmptyText===false){Ext.each(emptyFields,function(f){if(f.applyEmptyText){f.applyEmptyText();}});}}else if(o.clientValidation!==false){this.failureType=Ext.form.Action.CLIENT_INVALID;this.form.afterAction(this,false);}},success:function(response){var result=this.processResponse(response);if(result===true||result.success){this.form.afterAction(this,true);return;}
+if(result.errors){this.form.markInvalid(result.errors);}
+this.failureType=Ext.form.Action.SERVER_INVALID;this.form.afterAction(this,false);},handleResponse:function(response){if(this.form.errorReader){var rs=this.form.errorReader.read(response);var errors=[];if(rs.records){for(var i=0,len=rs.records.length;i<len;i++){var r=rs.records[i];errors[i]=r.data;}}
+if(errors.length<1){errors=null;}
+return{success:rs.success,errors:errors};}
+return Ext.decode(response.responseText);}});Ext.form.Action.Load=function(form,options){Ext.form.Action.Load.superclass.constructor.call(this,form,options);this.reader=this.form.reader;};Ext.extend(Ext.form.Action.Load,Ext.form.Action,{type:'load',run:function(){Ext.Ajax.request(Ext.apply(this.createCallback(this.options),{method:this.getMethod(),url:this.getUrl(false),headers:this.options.headers,params:this.getParams()}));},success:function(response){var result=this.processResponse(response);if(result===true||!result.success||!result.data){this.failureType=Ext.form.Action.LOAD_FAILURE;this.form.afterAction(this,false);return;}
+this.form.clearInvalid();this.form.setValues(result.data);this.form.afterAction(this,true);},handleResponse:function(response){if(this.form.reader){var rs=this.form.reader.read(response);var data=rs.records&&rs.records[0]?rs.records[0].data:null;return{success:rs.success,data:data};}
+return Ext.decode(response.responseText);}});Ext.form.Action.DirectLoad=Ext.extend(Ext.form.Action.Load,{constructor:function(form,opts){Ext.form.Action.DirectLoad.superclass.constructor.call(this,form,opts);},type:'directload',run:function(){var args=this.getParams();args.push(this.success,this);this.form.api.load.apply(window,args);},getParams:function(){var buf=[],o={};var bp=this.form.baseParams;var p=this.options.params;Ext.apply(o,p,bp);var paramOrder=this.form.paramOrder;if(paramOrder){for(var i=0,len=paramOrder.length;i<len;i++){buf.push(o[paramOrder[i]]);}}else if(this.form.paramsAsHash){buf.push(o);}
+return buf;},processResponse:function(result){this.result=result;return result;},success:function(response,trans){if(trans.type==Ext.Direct.exceptions.SERVER){response={};}
+Ext.form.Action.DirectLoad.superclass.success.call(this,response);}});Ext.form.Action.DirectSubmit=Ext.extend(Ext.form.Action.Submit,{constructor:function(form,opts){Ext.form.Action.DirectSubmit.superclass.constructor.call(this,form,opts);},type:'directsubmit',run:function(){var o=this.options;if(o.clientValidation===false||this.form.isValid()){this.success.params=this.getParams();this.form.api.submit(this.form.el.dom,this.success,this);}else if(o.clientValidation!==false){this.failureType=Ext.form.Action.CLIENT_INVALID;this.form.afterAction(this,false);}},getParams:function(){var o={};var bp=this.form.baseParams;var p=this.options.params;Ext.apply(o,p,bp);return o;},processResponse:function(result){this.result=result;return result;},success:function(response,trans){if(trans.type==Ext.Direct.exceptions.SERVER){response={};}
+Ext.form.Action.DirectSubmit.superclass.success.call(this,response);}});Ext.form.Action.ACTION_TYPES={'load':Ext.form.Action.Load,'submit':Ext.form.Action.Submit,'directload':Ext.form.Action.DirectLoad,'directsubmit':Ext.form.Action.DirectSubmit};Ext.form.VTypes=function(){var alpha=/^[a-zA-Z_]+$/,alphanum=/^[a-zA-Z0-9_]+$/,email=/^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,url=/(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;return{'email':function(v){return email.test(v);},'emailText':'This field should be an e-mail address in the format "user@example.com"','emailMask':/[a-z0-9_\.\-@\+]/i,'url':function(v){return url.test(v);},'urlText':'This field should be a URL in the format "http:/'+'/www.example.com"','alpha':function(v){return alpha.test(v);},'alphaText':'This field should only contain letters and _','alphaMask':/[a-z_]/i,'alphanum':function(v){return alphanum.test(v);},'alphanumText':'This field should only contain letters, numbers and _','alphanumMask':/[a-z0-9_]/i};}();Ext.Button=Ext.extend(Ext.BoxComponent,{hidden:false,disabled:false,pressed:false,enableToggle:false,menuAlign:'tl-bl?',type:'button',menuClassTarget:'tr:nth(2)',clickEvent:'click',handleMouseEvents:true,tooltipType:'qtip',buttonSelector:'button:first-child',scale:'small',iconAlign:'left',arrowAlign:'right',initComponent:function(){if(this.menu){this.menu=Ext.menu.MenuMgr.get(this.menu);this.menu.ownerCt=this;}
+Ext.Button.superclass.initComponent.call(this);this.addEvents('click','toggle','mouseover','mouseout','menushow','menuhide','menutriggerover','menutriggerout');if(this.menu){this.menu.ownerCt=undefined;}
+if(Ext.isString(this.toggleGroup)){this.enableToggle=true;}},getTemplateArgs:function(){return[this.type,'x-btn-'+this.scale+' x-btn-icon-'+this.scale+'-'+this.iconAlign,this.getMenuClass(),this.cls,this.id];},setButtonClass:function(){if(this.useSetClass){if(!Ext.isEmpty(this.oldCls)){this.el.removeClass([this.oldCls,'x-btn-pressed']);}
+this.oldCls=(this.iconCls||this.icon)?(this.text?'x-btn-text-icon':'x-btn-icon'):'x-btn-noicon';this.el.addClass([this.oldCls,this.pressed?'x-btn-pressed':null]);}},getMenuClass:function(){return this.menu?(this.arrowAlign!='bottom'?'x-btn-arrow':'x-btn-arrow-bottom'):'';},onRender:function(ct,position){if(!this.template){if(!Ext.Button.buttonTemplate){Ext.Button.buttonTemplate=new Ext.Template('<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">','<tr><td class="x-btn-tl"><i>&#160;</i></td><td class="x-btn-tc"></td><td class="x-btn-tr"><i>&#160;</i></td></tr>','<tr><td class="x-btn-ml"><i>&#160;</i></td><td class="x-btn-mc"><em class="{2}" unselectable="on"><button type="{0}"></button></em></td><td class="x-btn-mr"><i>&#160;</i></td></tr>','<tr><td class="x-btn-bl"><i>&#160;</i></td><td class="x-btn-bc"></td><td class="x-btn-br"><i>&#160;</i></td></tr>','</tbody></table>');Ext.Button.buttonTemplate.compile();}
+this.template=Ext.Button.buttonTemplate;}
+var btn,targs=this.getTemplateArgs();if(position){btn=this.template.insertBefore(position,targs,true);}else{btn=this.template.append(ct,targs,true);}
+this.btnEl=btn.child(this.buttonSelector);this.mon(this.btnEl,{scope:this,focus:this.onFocus,blur:this.onBlur});this.initButtonEl(btn,this.btnEl);Ext.ButtonToggleMgr.register(this);},initButtonEl:function(btn,btnEl){this.el=btn;this.setIcon(this.icon);this.setText(this.text);this.setIconClass(this.iconCls);if(Ext.isDefined(this.tabIndex)){btnEl.dom.tabIndex=this.tabIndex;}
+if(this.tooltip){this.setTooltip(this.tooltip,true);}
+if(this.handleMouseEvents){this.mon(btn,{scope:this,mouseover:this.onMouseOver,mousedown:this.onMouseDown});}
+if(this.menu){this.mon(this.menu,{scope:this,show:this.onMenuShow,hide:this.onMenuHide});}
+if(this.repeat){var repeater=new Ext.util.ClickRepeater(btn,Ext.isObject(this.repeat)?this.repeat:{});this.mon(repeater,'click',this.onRepeatClick,this);}else{this.mon(btn,this.clickEvent,this.onClick,this);}},afterRender:function(){Ext.Button.superclass.afterRender.call(this);this.useSetClass=true;this.setButtonClass();this.doc=Ext.getDoc();this.doAutoWidth();},setIconClass:function(cls){this.iconCls=cls;if(this.el){this.btnEl.dom.className='';this.btnEl.addClass(['x-btn-text',cls||'']);this.setButtonClass();}
+return this;},setTooltip:function(tooltip,initial){if(this.rendered){if(!initial){this.clearTip();}
+if(Ext.isObject(tooltip)){Ext.QuickTips.register(Ext.apply({target:this.btnEl.id},tooltip));this.tooltip=tooltip;}else{this.btnEl.dom[this.tooltipType]=tooltip;}}else{this.tooltip=tooltip;}
+return this;},clearTip:function(){if(Ext.isObject(this.tooltip)){Ext.QuickTips.unregister(this.btnEl);}},beforeDestroy:function(){if(this.rendered){this.clearTip();}
+if(this.menu&&this.destroyMenu!==false){Ext.destroy(this.btnEl,this.menu);}
+Ext.destroy(this.repeater);},onDestroy:function(){if(this.rendered){this.doc.un('mouseover',this.monitorMouseOver,this);this.doc.un('mouseup',this.onMouseUp,this);delete this.doc;delete this.btnEl;Ext.ButtonToggleMgr.unregister(this);}
+Ext.Button.superclass.onDestroy.call(this);},doAutoWidth:function(){if(this.autoWidth!==false&&this.el&&this.text&&this.width===undefined){this.el.setWidth('auto');if(Ext.isIE7&&Ext.isStrict){var ib=this.btnEl;if(ib&&ib.getWidth()>20){ib.clip();ib.setWidth(Ext.util.TextMetrics.measure(ib,this.text).width+ib.getFrameWidth('lr'));}}
+if(this.minWidth){if(this.el.getWidth()<this.minWidth){this.el.setWidth(this.minWidth);}}}},setHandler:function(handler,scope){this.handler=handler;this.scope=scope;return this;},setText:function(text){this.text=text;if(this.el){this.btnEl.update(text||'&#160;');this.setButtonClass();}
+this.doAutoWidth();return this;},setIcon:function(icon){this.icon=icon;if(this.el){this.btnEl.setStyle('background-image',icon?'url('+icon+')':'');this.setButtonClass();}
+return this;},getText:function(){return this.text;},toggle:function(state,suppressEvent){state=state===undefined?!this.pressed:!!state;if(state!=this.pressed){if(this.rendered){this.el[state?'addClass':'removeClass']('x-btn-pressed');}
+this.pressed=state;if(!suppressEvent){this.fireEvent('toggle',this,state);if(this.toggleHandler){this.toggleHandler.call(this.scope||this,this,state);}}}
+return this;},onDisable:function(){this.onDisableChange(true);},onEnable:function(){this.onDisableChange(false);},onDisableChange:function(disabled){if(this.el){if(!Ext.isIE6||!this.text){this.el[disabled?'addClass':'removeClass'](this.disabledClass);}
+this.el.dom.disabled=disabled;}
+this.disabled=disabled;},showMenu:function(){if(this.rendered&&this.menu){if(this.tooltip){Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);}
+if(this.menu.isVisible()){this.menu.hide();}
+this.menu.ownerCt=this;this.menu.show(this.el,this.menuAlign);}
+return this;},hideMenu:function(){if(this.hasVisibleMenu()){this.menu.hide();}
+return this;},hasVisibleMenu:function(){return this.menu&&this.menu.ownerCt==this&&this.menu.isVisible();},onRepeatClick:function(repeat,e){this.onClick(e);},onClick:function(e){if(e){e.preventDefault();}
+if(e.button!==0){return;}
+if(!this.disabled){this.doToggle();if(this.menu&&!this.hasVisibleMenu()&&!this.ignoreNextClick){this.showMenu();}
+this.fireEvent('click',this,e);if(this.handler){this.handler.call(this.scope||this,this,e);}}},doToggle:function(){if(this.enableToggle&&(this.allowDepress!==false||!this.pressed)){this.toggle();}},isMenuTriggerOver:function(e,internal){return this.menu&&!internal;},isMenuTriggerOut:function(e,internal){return this.menu&&!internal;},onMouseOver:function(e){if(!this.disabled){var internal=e.within(this.el,true);if(!internal){this.el.addClass('x-btn-over');if(!this.monitoringMouseOver){this.doc.on('mouseover',this.monitorMouseOver,this);this.monitoringMouseOver=true;}
+this.fireEvent('mouseover',this,e);}
+if(this.isMenuTriggerOver(e,internal)){this.fireEvent('menutriggerover',this,this.menu,e);}}},monitorMouseOver:function(e){if(e.target!=this.el.dom&&!e.within(this.el)){if(this.monitoringMouseOver){this.doc.un('mouseover',this.monitorMouseOver,this);this.monitoringMouseOver=false;}
+this.onMouseOut(e);}},onMouseOut:function(e){var internal=e.within(this.el)&&e.target!=this.el.dom;this.el.removeClass('x-btn-over');this.fireEvent('mouseout',this,e);if(this.isMenuTriggerOut(e,internal)){this.fireEvent('menutriggerout',this,this.menu,e);}},focus:function(){this.btnEl.focus();},blur:function(){this.btnEl.blur();},onFocus:function(e){if(!this.disabled){this.el.addClass('x-btn-focus');}},onBlur:function(e){this.el.removeClass('x-btn-focus');},getClickEl:function(e,isUp){return this.el;},onMouseDown:function(e){if(!this.disabled&&e.button===0){this.getClickEl(e).addClass('x-btn-click');this.doc.on('mouseup',this.onMouseUp,this);}},onMouseUp:function(e){if(e.button===0){this.getClickEl(e,true).removeClass('x-btn-click');this.doc.un('mouseup',this.onMouseUp,this);}},onMenuShow:function(e){if(this.menu.ownerCt==this){this.menu.ownerCt=this;this.ignoreNextClick=0;this.el.addClass('x-btn-menu-active');this.fireEvent('menushow',this,this.menu);}},onMenuHide:function(e){if(this.menu.ownerCt==this){this.el.removeClass('x-btn-menu-active');this.ignoreNextClick=this.restoreClick.defer(250,this);this.fireEvent('menuhide',this,this.menu);delete this.menu.ownerCt;}},restoreClick:function(){this.ignoreNextClick=0;}});Ext.reg('button',Ext.Button);Ext.ButtonToggleMgr=function(){var groups={};function toggleGroup(btn,state){if(state){var g=groups[btn.toggleGroup];for(var i=0,l=g.length;i<l;i++){if(g[i]!=btn){g[i].toggle(false);}}}}
+return{register:function(btn){if(!btn.toggleGroup){return;}
+var g=groups[btn.toggleGroup];if(!g){g=groups[btn.toggleGroup]=[];}
+g.push(btn);btn.on('toggle',toggleGroup);},unregister:function(btn){if(!btn.toggleGroup){return;}
+var g=groups[btn.toggleGroup];if(g){g.remove(btn);btn.un('toggle',toggleGroup);}},getPressed:function(group){var g=groups[group];if(g){for(var i=0,len=g.length;i<len;i++){if(g[i].pressed===true){return g[i];}}}
+return null;}};}();Ext.SplitButton=Ext.extend(Ext.Button,{arrowSelector:'em',split:true,initComponent:function(){Ext.SplitButton.superclass.initComponent.call(this);this.addEvents("arrowclick");},onRender:function(){Ext.SplitButton.superclass.onRender.apply(this,arguments);if(this.arrowTooltip){this.el.child(this.arrowSelector).dom[this.tooltipType]=this.arrowTooltip;}},setArrowHandler:function(handler,scope){this.arrowHandler=handler;this.scope=scope;},getMenuClass:function(){return'x-btn-split'+(this.arrowAlign=='bottom'?'-bottom':'');},isClickOnArrow:function(e){if(this.arrowAlign!='bottom'){var visBtn=this.el.child('em.x-btn-split');var right=visBtn.getRegion().right-visBtn.getPadding('r');return e.getPageX()>right;}else{return e.getPageY()>this.btnEl.getRegion().bottom;}},onClick:function(e,t){e.preventDefault();if(!this.disabled){if(this.isClickOnArrow(e)){if(this.menu&&!this.menu.isVisible()&&!this.ignoreNextClick){this.showMenu();}
+this.fireEvent("arrowclick",this,e);if(this.arrowHandler){this.arrowHandler.call(this.scope||this,this,e);}}else{this.doToggle();this.fireEvent("click",this,e);if(this.handler){this.handler.call(this.scope||this,this,e);}}}},isMenuTriggerOver:function(e){return this.menu&&e.target.tagName==this.arrowSelector;},isMenuTriggerOut:function(e,internal){return this.menu&&e.target.tagName!=this.arrowSelector;}});Ext.reg('splitbutton',Ext.SplitButton);Ext.CycleButton=Ext.extend(Ext.SplitButton,{getItemText:function(item){if(item&&this.showText===true){var text='';if(this.prependText){text+=this.prependText;}
+text+=item.text;return text;}
+return undefined;},setActiveItem:function(item,suppressEvent){if(!Ext.isObject(item)){item=this.menu.getComponent(item);}
+if(item){if(!this.rendered){this.text=this.getItemText(item);this.iconCls=item.iconCls;}else{var t=this.getItemText(item);if(t){this.setText(t);}
+this.setIconClass(item.iconCls);}
+this.activeItem=item;if(!item.checked){item.setChecked(true,false);}
+if(this.forceIcon){this.setIconClass(this.forceIcon);}
+if(!suppressEvent){this.fireEvent('change',this,item);}}},getActiveItem:function(){return this.activeItem;},initComponent:function(){this.addEvents("change");if(this.changeHandler){this.on('change',this.changeHandler,this.scope||this);delete this.changeHandler;}
+this.itemCount=this.items.length;this.menu={cls:'x-cycle-menu',items:[]};var checked=0;Ext.each(this.items,function(item,i){Ext.apply(item,{group:item.group||this.id,itemIndex:i,checkHandler:this.checkHandler,scope:this,checked:item.checked||false});this.menu.items.push(item);if(item.checked){checked=i;}},this);Ext.CycleButton.superclass.initComponent.call(this);this.on('click',this.toggleSelected,this);this.setActiveItem(checked,true);},checkHandler:function(item,pressed){if(pressed){this.setActiveItem(item);}},toggleSelected:function(){var m=this.menu;m.render();if(!m.hasLayout){m.doLayout();}
+var nextIdx,checkItem;for(var i=1;i<this.itemCount;i++){nextIdx=(this.activeItem.itemIndex+i)%this.itemCount;checkItem=m.items.itemAt(nextIdx);if(!checkItem.disabled){checkItem.setChecked(true);break;}}}});Ext.reg('cycle',Ext.CycleButton);(function(){var Event=Ext.EventManager;var Dom=Ext.lib.Dom;Ext.dd.DragDrop=function(id,sGroup,config){if(id){this.init(id,sGroup,config);}};Ext.dd.DragDrop.prototype={id:null,config:null,dragElId:null,handleElId:null,invalidHandleTypes:null,invalidHandleIds:null,invalidHandleClasses:null,startPageX:0,startPageY:0,groups:null,locked:false,lock:function(){this.locked=true;},moveOnly:false,unlock:function(){this.locked=false;},isTarget:true,padding:null,_domRef:null,__ygDragDrop:true,constrainX:false,constrainY:false,minX:0,maxX:0,minY:0,maxY:0,maintainOffset:false,xTicks:null,yTicks:null,primaryButtonOnly:true,available:false,hasOuterHandles:false,b4StartDrag:function(x,y){},startDrag:function(x,y){},b4Drag:function(e){},onDrag:function(e){},onDragEnter:function(e,id){},b4DragOver:function(e){},onDragOver:function(e,id){},b4DragOut:function(e){},onDragOut:function(e,id){},b4DragDrop:function(e){},onDragDrop:function(e,id){},onInvalidDrop:function(e){},b4EndDrag:function(e){},endDrag:function(e){},b4MouseDown:function(e){},onMouseDown:function(e){},onMouseUp:function(e){},onAvailable:function(){},defaultPadding:{left:0,right:0,top:0,bottom:0},constrainTo:function(constrainTo,pad,inContent){if(Ext.isNumber(pad)){pad={left:pad,right:pad,top:pad,bottom:pad};}
+pad=pad||this.defaultPadding;var b=Ext.get(this.getEl()).getBox(),ce=Ext.get(constrainTo),s=ce.getScroll(),c,cd=ce.dom;if(cd==document.body){c={x:s.left,y:s.top,width:Ext.lib.Dom.getViewWidth(),height:Ext.lib.Dom.getViewHeight()};}else{var xy=ce.getXY();c={x:xy[0],y:xy[1],width:cd.clientWidth,height:cd.clientHeight};}
+var topSpace=b.y-c.y,leftSpace=b.x-c.x;this.resetConstraints();this.setXConstraint(leftSpace-(pad.left||0),c.width-leftSpace-b.width-(pad.right||0),this.xTickSize);this.setYConstraint(topSpace-(pad.top||0),c.height-topSpace-b.height-(pad.bottom||0),this.yTickSize);},getEl:function(){if(!this._domRef){this._domRef=Ext.getDom(this.id);}
+return this._domRef;},getDragEl:function(){return Ext.getDom(this.dragElId);},init:function(id,sGroup,config){this.initTarget(id,sGroup,config);Event.on(this.id,"mousedown",this.handleMouseDown,this);},initTarget:function(id,sGroup,config){this.config=config||{};this.DDM=Ext.dd.DDM;this.groups={};if(typeof id!=="string"){id=Ext.id(id);}
+this.id=id;this.addToGroup((sGroup)?sGroup:"default");this.handleElId=id;this.setDragElId(id);this.invalidHandleTypes={A:"A"};this.invalidHandleIds={};this.invalidHandleClasses=[];this.applyConfig();this.handleOnAvailable();},applyConfig:function(){this.padding=this.config.padding||[0,0,0,0];this.isTarget=(this.config.isTarget!==false);this.maintainOffset=(this.config.maintainOffset);this.primaryButtonOnly=(this.config.primaryButtonOnly!==false);},handleOnAvailable:function(){this.available=true;this.resetConstraints();this.onAvailable();},setPadding:function(iTop,iRight,iBot,iLeft){if(!iRight&&0!==iRight){this.padding=[iTop,iTop,iTop,iTop];}else if(!iBot&&0!==iBot){this.padding=[iTop,iRight,iTop,iRight];}else{this.padding=[iTop,iRight,iBot,iLeft];}},setInitPosition:function(diffX,diffY){var el=this.getEl();if(!this.DDM.verifyEl(el)){return;}
+var dx=diffX||0;var dy=diffY||0;var p=Dom.getXY(el);this.initPageX=p[0]-dx;this.initPageY=p[1]-dy;this.lastPageX=p[0];this.lastPageY=p[1];this.setStartPosition(p);},setStartPosition:function(pos){var p=pos||Dom.getXY(this.getEl());this.deltaSetXY=null;this.startPageX=p[0];this.startPageY=p[1];},addToGroup:function(sGroup){this.groups[sGroup]=true;this.DDM.regDragDrop(this,sGroup);},removeFromGroup:function(sGroup){if(this.groups[sGroup]){delete this.groups[sGroup];}
+this.DDM.removeDDFromGroup(this,sGroup);},setDragElId:function(id){this.dragElId=id;},setHandleElId:function(id){if(typeof id!=="string"){id=Ext.id(id);}
+this.handleElId=id;this.DDM.regHandle(this.id,id);},setOuterHandleElId:function(id){if(typeof id!=="string"){id=Ext.id(id);}
+Event.on(id,"mousedown",this.handleMouseDown,this);this.setHandleElId(id);this.hasOuterHandles=true;},unreg:function(){Event.un(this.id,"mousedown",this.handleMouseDown);this._domRef=null;this.DDM._remove(this);},destroy:function(){this.unreg();},isLocked:function(){return(this.DDM.isLocked()||this.locked);},handleMouseDown:function(e,oDD){if(this.primaryButtonOnly&&e.button!=0){return;}
+if(this.isLocked()){return;}
+this.DDM.refreshCache(this.groups);var pt=new Ext.lib.Point(Ext.lib.Event.getPageX(e),Ext.lib.Event.getPageY(e));if(!this.hasOuterHandles&&!this.DDM.isOverTarget(pt,this)){}else{if(this.clickValidator(e)){this.setStartPosition();this.b4MouseDown(e);this.onMouseDown(e);this.DDM.handleMouseDown(e,this);this.DDM.stopEvent(e);}else{}}},clickValidator:function(e){var target=e.getTarget();return(this.isValidHandleChild(target)&&(this.id==this.handleElId||this.DDM.handleWasClicked(target,this.id)));},addInvalidHandleType:function(tagName){var type=tagName.toUpperCase();this.invalidHandleTypes[type]=type;},addInvalidHandleId:function(id){if(typeof id!=="string"){id=Ext.id(id);}
+this.invalidHandleIds[id]=id;},addInvalidHandleClass:function(cssClass){this.invalidHandleClasses.push(cssClass);},removeInvalidHandleType:function(tagName){var type=tagName.toUpperCase();delete this.invalidHandleTypes[type];},removeInvalidHandleId:function(id){if(typeof id!=="string"){id=Ext.id(id);}
+delete this.invalidHandleIds[id];},removeInvalidHandleClass:function(cssClass){for(var i=0,len=this.invalidHandleClasses.length;i<len;++i){if(this.invalidHandleClasses[i]==cssClass){delete this.invalidHandleClasses[i];}}},isValidHandleChild:function(node){var valid=true;var nodeName;try{nodeName=node.nodeName.toUpperCase();}catch(e){nodeName=node.nodeName;}
+valid=valid&&!this.invalidHandleTypes[nodeName];valid=valid&&!this.invalidHandleIds[node.id];for(var i=0,len=this.invalidHandleClasses.length;valid&&i<len;++i){valid=!Ext.fly(node).hasClass(this.invalidHandleClasses[i]);}
+return valid;},setXTicks:function(iStartX,iTickSize){this.xTicks=[];this.xTickSize=iTickSize;var tickMap={};for(var i=this.initPageX;i>=this.minX;i=i-iTickSize){if(!tickMap[i]){this.xTicks[this.xTicks.length]=i;tickMap[i]=true;}}
+for(i=this.initPageX;i<=this.maxX;i=i+iTickSize){if(!tickMap[i]){this.xTicks[this.xTicks.length]=i;tickMap[i]=true;}}
+this.xTicks.sort(this.DDM.numericSort);},setYTicks:function(iStartY,iTickSize){this.yTicks=[];this.yTickSize=iTickSize;var tickMap={};for(var i=this.initPageY;i>=this.minY;i=i-iTickSize){if(!tickMap[i]){this.yTicks[this.yTicks.length]=i;tickMap[i]=true;}}
+for(i=this.initPageY;i<=this.maxY;i=i+iTickSize){if(!tickMap[i]){this.yTicks[this.yTicks.length]=i;tickMap[i]=true;}}
+this.yTicks.sort(this.DDM.numericSort);},setXConstraint:function(iLeft,iRight,iTickSize){this.leftConstraint=iLeft;this.rightConstraint=iRight;this.minX=this.initPageX-iLeft;this.maxX=this.initPageX+iRight;if(iTickSize){this.setXTicks(this.initPageX,iTickSize);}
+this.constrainX=true;},clearConstraints:function(){this.constrainX=false;this.constrainY=false;this.clearTicks();},clearTicks:function(){this.xTicks=null;this.yTicks=null;this.xTickSize=0;this.yTickSize=0;},setYConstraint:function(iUp,iDown,iTickSize){this.topConstraint=iUp;this.bottomConstraint=iDown;this.minY=this.initPageY-iUp;this.maxY=this.initPageY+iDown;if(iTickSize){this.setYTicks(this.initPageY,iTickSize);}
+this.constrainY=true;},resetConstraints:function(){if(this.initPageX||this.initPageX===0){var dx=(this.maintainOffset)?this.lastPageX-this.initPageX:0;var dy=(this.maintainOffset)?this.lastPageY-this.initPageY:0;this.setInitPosition(dx,dy);}else{this.setInitPosition();}
+if(this.constrainX){this.setXConstraint(this.leftConstraint,this.rightConstraint,this.xTickSize);}
+if(this.constrainY){this.setYConstraint(this.topConstraint,this.bottomConstraint,this.yTickSize);}},getTick:function(val,tickArray){if(!tickArray){return val;}else if(tickArray[0]>=val){return tickArray[0];}else{for(var i=0,len=tickArray.length;i<len;++i){var next=i+1;if(tickArray[next]&&tickArray[next]>=val){var diff1=val-tickArray[i];var diff2=tickArray[next]-val;return(diff2>diff1)?tickArray[i]:tickArray[next];}}
+return tickArray[tickArray.length-1];}},toString:function(){return("DragDrop "+this.id);}};})();if(!Ext.dd.DragDropMgr){Ext.dd.DragDropMgr=function(){var Event=Ext.EventManager;return{ids:{},handleIds:{},dragCurrent:null,dragOvers:{},deltaX:0,deltaY:0,preventDefault:true,stopPropagation:true,initialized:false,locked:false,init:function(){this.initialized=true;},POINT:0,INTERSECT:1,mode:0,_execOnAll:function(sMethod,args){for(var i in this.ids){for(var j in this.ids[i]){var oDD=this.ids[i][j];if(!this.isTypeOfDD(oDD)){continue;}
+oDD[sMethod].apply(oDD,args);}}},_onLoad:function(){this.init();Event.on(document,"mouseup",this.handleMouseUp,this,true);Event.on(document,"mousemove",this.handleMouseMove,this,true);Event.on(window,"unload",this._onUnload,this,true);Event.on(window,"resize",this._onResize,this,true);},_onResize:function(e){this._execOnAll("resetConstraints",[]);},lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isLocked:function(){return this.locked;},locationCache:{},useCache:true,clickPixelThresh:3,clickTimeThresh:350,dragThreshMet:false,clickTimeout:null,startX:0,startY:0,regDragDrop:function(oDD,sGroup){if(!this.initialized){this.init();}
+if(!this.ids[sGroup]){this.ids[sGroup]={};}
+this.ids[sGroup][oDD.id]=oDD;},removeDDFromGroup:function(oDD,sGroup){if(!this.ids[sGroup]){this.ids[sGroup]={};}
+var obj=this.ids[sGroup];if(obj&&obj[oDD.id]){delete obj[oDD.id];}},_remove:function(oDD){for(var g in oDD.groups){if(g&&this.ids[g]&&this.ids[g][oDD.id]){delete this.ids[g][oDD.id];}}
+delete this.handleIds[oDD.id];},regHandle:function(sDDId,sHandleId){if(!this.handleIds[sDDId]){this.handleIds[sDDId]={};}
+this.handleIds[sDDId][sHandleId]=sHandleId;},isDragDrop:function(id){return(this.getDDById(id))?true:false;},getRelated:function(p_oDD,bTargetsOnly){var oDDs=[];for(var i in p_oDD.groups){for(var j in this.ids[i]){var dd=this.ids[i][j];if(!this.isTypeOfDD(dd)){continue;}
+if(!bTargetsOnly||dd.isTarget){oDDs[oDDs.length]=dd;}}}
+return oDDs;},isLegalTarget:function(oDD,oTargetDD){var targets=this.getRelated(oDD,true);for(var i=0,len=targets.length;i<len;++i){if(targets[i].id==oTargetDD.id){return true;}}
+return false;},isTypeOfDD:function(oDD){return(oDD&&oDD.__ygDragDrop);},isHandle:function(sDDId,sHandleId){return(this.handleIds[sDDId]&&this.handleIds[sDDId][sHandleId]);},getDDById:function(id){for(var i in this.ids){if(this.ids[i][id]){return this.ids[i][id];}}
+return null;},handleMouseDown:function(e,oDD){if(Ext.QuickTips){Ext.QuickTips.ddDisable();}
+if(this.dragCurrent){this.handleMouseUp(e);}
+this.currentTarget=e.getTarget();this.dragCurrent=oDD;var el=oDD.getEl();this.startX=e.getPageX();this.startY=e.getPageY();this.deltaX=this.startX-el.offsetLeft;this.deltaY=this.startY-el.offsetTop;this.dragThreshMet=false;this.clickTimeout=setTimeout(function(){var DDM=Ext.dd.DDM;DDM.startDrag(DDM.startX,DDM.startY);},this.clickTimeThresh);},startDrag:function(x,y){clearTimeout(this.clickTimeout);if(this.dragCurrent){this.dragCurrent.b4StartDrag(x,y);this.dragCurrent.startDrag(x,y);}
+this.dragThreshMet=true;},handleMouseUp:function(e){if(Ext.QuickTips){Ext.QuickTips.ddEnable();}
+if(!this.dragCurrent){return;}
+clearTimeout(this.clickTimeout);if(this.dragThreshMet){this.fireEvents(e,true);}else{}
+this.stopDrag(e);this.stopEvent(e);},stopEvent:function(e){if(this.stopPropagation){e.stopPropagation();}
+if(this.preventDefault){e.preventDefault();}},stopDrag:function(e){if(this.dragCurrent){if(this.dragThreshMet){this.dragCurrent.b4EndDrag(e);this.dragCurrent.endDrag(e);}
+this.dragCurrent.onMouseUp(e);}
+this.dragCurrent=null;this.dragOvers={};},handleMouseMove:function(e){if(!this.dragCurrent){return true;}
+if(Ext.isIE&&(e.button!==0&&e.button!==1&&e.button!==2)){this.stopEvent(e);return this.handleMouseUp(e);}
+if(!this.dragThreshMet){var diffX=Math.abs(this.startX-e.getPageX());var diffY=Math.abs(this.startY-e.getPageY());if(diffX>this.clickPixelThresh||diffY>this.clickPixelThresh){this.startDrag(this.startX,this.startY);}}
+if(this.dragThreshMet){this.dragCurrent.b4Drag(e);this.dragCurrent.onDrag(e);if(!this.dragCurrent.moveOnly){this.fireEvents(e,false);}}
+this.stopEvent(e);return true;},fireEvents:function(e,isDrop){var dc=this.dragCurrent;if(!dc||dc.isLocked()){return;}
+var pt=e.getPoint();var oldOvers=[];var outEvts=[];var overEvts=[];var dropEvts=[];var enterEvts=[];for(var i in this.dragOvers){var ddo=this.dragOvers[i];if(!this.isTypeOfDD(ddo)){continue;}
+if(!this.isOverTarget(pt,ddo,this.mode)){outEvts.push(ddo);}
+oldOvers[i]=true;delete this.dragOvers[i];}
+for(var sGroup in dc.groups){if("string"!=typeof sGroup){continue;}
+for(i in this.ids[sGroup]){var oDD=this.ids[sGroup][i];if(!this.isTypeOfDD(oDD)){continue;}
+if(oDD.isTarget&&!oDD.isLocked()&&((oDD!=dc)||(dc.ignoreSelf===false))){if(this.isOverTarget(pt,oDD,this.mode)){if(isDrop){dropEvts.push(oDD);}else{if(!oldOvers[oDD.id]){enterEvts.push(oDD);}else{overEvts.push(oDD);}
+this.dragOvers[oDD.id]=oDD;}}}}}
+if(this.mode){if(outEvts.length){dc.b4DragOut(e,outEvts);dc.onDragOut(e,outEvts);}
+if(enterEvts.length){dc.onDragEnter(e,enterEvts);}
+if(overEvts.length){dc.b4DragOver(e,overEvts);dc.onDragOver(e,overEvts);}
+if(dropEvts.length){dc.b4DragDrop(e,dropEvts);dc.onDragDrop(e,dropEvts);}}else{var len=0;for(i=0,len=outEvts.length;i<len;++i){dc.b4DragOut(e,outEvts[i].id);dc.onDragOut(e,outEvts[i].id);}
+for(i=0,len=enterEvts.length;i<len;++i){dc.onDragEnter(e,enterEvts[i].id);}
+for(i=0,len=overEvts.length;i<len;++i){dc.b4DragOver(e,overEvts[i].id);dc.onDragOver(e,overEvts[i].id);}
+for(i=0,len=dropEvts.length;i<len;++i){dc.b4DragDrop(e,dropEvts[i].id);dc.onDragDrop(e,dropEvts[i].id);}}
+if(isDrop&&!dropEvts.length){dc.onInvalidDrop(e);}},getBestMatch:function(dds){var winner=null;var len=dds.length;if(len==1){winner=dds[0];}else{for(var i=0;i<len;++i){var dd=dds[i];if(dd.cursorIsOver){winner=dd;break;}else{if(!winner||winner.overlap.getArea()<dd.overlap.getArea()){winner=dd;}}}}
+return winner;},refreshCache:function(groups){for(var sGroup in groups){if("string"!=typeof sGroup){continue;}
+for(var i in this.ids[sGroup]){var oDD=this.ids[sGroup][i];if(this.isTypeOfDD(oDD)){var loc=this.getLocation(oDD);if(loc){this.locationCache[oDD.id]=loc;}else{delete this.locationCache[oDD.id];}}}}},verifyEl:function(el){if(el){var parent;if(Ext.isIE){try{parent=el.offsetParent;}catch(e){}}else{parent=el.offsetParent;}
+if(parent){return true;}}
+return false;},getLocation:function(oDD){if(!this.isTypeOfDD(oDD)){return null;}
+var el=oDD.getEl(),pos,x1,x2,y1,y2,t,r,b,l;try{pos=Ext.lib.Dom.getXY(el);}catch(e){}
+if(!pos){return null;}
+x1=pos[0];x2=x1+el.offsetWidth;y1=pos[1];y2=y1+el.offsetHeight;t=y1-oDD.padding[0];r=x2+oDD.padding[1];b=y2+oDD.padding[2];l=x1-oDD.padding[3];return new Ext.lib.Region(t,r,b,l);},isOverTarget:function(pt,oTarget,intersect){var loc=this.locationCache[oTarget.id];if(!loc||!this.useCache){loc=this.getLocation(oTarget);this.locationCache[oTarget.id]=loc;}
+if(!loc){return false;}
+oTarget.cursorIsOver=loc.contains(pt);var dc=this.dragCurrent;if(!dc||!dc.getTargetCoord||(!intersect&&!dc.constrainX&&!dc.constrainY)){return oTarget.cursorIsOver;}
+oTarget.overlap=null;var pos=dc.getTargetCoord(pt.x,pt.y);var el=dc.getDragEl();var curRegion=new Ext.lib.Region(pos.y,pos.x+el.offsetWidth,pos.y+el.offsetHeight,pos.x);var overlap=curRegion.intersect(loc);if(overlap){oTarget.overlap=overlap;return(intersect)?true:oTarget.cursorIsOver;}else{return false;}},_onUnload:function(e,me){Ext.dd.DragDropMgr.unregAll();},unregAll:function(){if(this.dragCurrent){this.stopDrag();this.dragCurrent=null;}
+this._execOnAll("unreg",[]);for(var i in this.elementCache){delete this.elementCache[i];}
+this.elementCache={};this.ids={};},elementCache:{},getElWrapper:function(id){var oWrapper=this.elementCache[id];if(!oWrapper||!oWrapper.el){oWrapper=this.elementCache[id]=new this.ElementWrapper(Ext.getDom(id));}
+return oWrapper;},getElement:function(id){return Ext.getDom(id);},getCss:function(id){var el=Ext.getDom(id);return(el)?el.style:null;},ElementWrapper:function(el){this.el=el||null;this.id=this.el&&el.id;this.css=this.el&&el.style;},getPosX:function(el){return Ext.lib.Dom.getX(el);},getPosY:function(el){return Ext.lib.Dom.getY(el);},swapNode:function(n1,n2){if(n1.swapNode){n1.swapNode(n2);}else{var p=n2.parentNode;var s=n2.nextSibling;if(s==n1){p.insertBefore(n1,n2);}else if(n2==n1.nextSibling){p.insertBefore(n2,n1);}else{n1.parentNode.replaceChild(n2,n1);p.insertBefore(n1,s);}}},getScroll:function(){var t,l,dde=document.documentElement,db=document.body;if(dde&&(dde.scrollTop||dde.scrollLeft)){t=dde.scrollTop;l=dde.scrollLeft;}else if(db){t=db.scrollTop;l=db.scrollLeft;}else{}
+return{top:t,left:l};},getStyle:function(el,styleProp){return Ext.fly(el).getStyle(styleProp);},getScrollTop:function(){return this.getScroll().top;},getScrollLeft:function(){return this.getScroll().left;},moveToEl:function(moveEl,targetEl){var aCoord=Ext.lib.Dom.getXY(targetEl);Ext.lib.Dom.setXY(moveEl,aCoord);},numericSort:function(a,b){return(a-b);},_timeoutCount:0,_addListeners:function(){var DDM=Ext.dd.DDM;if(Ext.lib.Event&&document){DDM._onLoad();}else{if(DDM._timeoutCount>2000){}else{setTimeout(DDM._addListeners,10);if(document&&document.body){DDM._timeoutCount+=1;}}}},handleWasClicked:function(node,id){if(this.isHandle(id,node.id)){return true;}else{var p=node.parentNode;while(p){if(this.isHandle(id,p.id)){return true;}else{p=p.parentNode;}}}
+return false;}};}();Ext.dd.DDM=Ext.dd.DragDropMgr;Ext.dd.DDM._addListeners();}
+Ext.dd.DD=function(id,sGroup,config){if(id){this.init(id,sGroup,config);}};Ext.extend(Ext.dd.DD,Ext.dd.DragDrop,{scroll:true,autoOffset:function(iPageX,iPageY){var x=iPageX-this.startPageX;var y=iPageY-this.startPageY;this.setDelta(x,y);},setDelta:function(iDeltaX,iDeltaY){this.deltaX=iDeltaX;this.deltaY=iDeltaY;},setDragElPos:function(iPageX,iPageY){var el=this.getDragEl();this.alignElWithMouse(el,iPageX,iPageY);},alignElWithMouse:function(el,iPageX,iPageY){var oCoord=this.getTargetCoord(iPageX,iPageY);var fly=el.dom?el:Ext.fly(el,'_dd');if(!this.deltaSetXY){var aCoord=[oCoord.x,oCoord.y];fly.setXY(aCoord);var newLeft=fly.getLeft(true);var newTop=fly.getTop(true);this.deltaSetXY=[newLeft-oCoord.x,newTop-oCoord.y];}else{fly.setLeftTop(oCoord.x+this.deltaSetXY[0],oCoord.y+this.deltaSetXY[1]);}
+this.cachePosition(oCoord.x,oCoord.y);this.autoScroll(oCoord.x,oCoord.y,el.offsetHeight,el.offsetWidth);return oCoord;},cachePosition:function(iPageX,iPageY){if(iPageX){this.lastPageX=iPageX;this.lastPageY=iPageY;}else{var aCoord=Ext.lib.Dom.getXY(this.getEl());this.lastPageX=aCoord[0];this.lastPageY=aCoord[1];}},autoScroll:function(x,y,h,w){if(this.scroll){var clientH=Ext.lib.Dom.getViewHeight();var clientW=Ext.lib.Dom.getViewWidth();var st=this.DDM.getScrollTop();var sl=this.DDM.getScrollLeft();var bot=h+y;var right=w+x;var toBot=(clientH+st-y-this.deltaY);var toRight=(clientW+sl-x-this.deltaX);var thresh=40;var scrAmt=(document.all)?80:30;if(bot>clientH&&toBot<thresh){window.scrollTo(sl,st+scrAmt);}
+if(y<st&&st>0&&y-st<thresh){window.scrollTo(sl,st-scrAmt);}
+if(right>clientW&&toRight<thresh){window.scrollTo(sl+scrAmt,st);}
+if(x<sl&&sl>0&&x-sl<thresh){window.scrollTo(sl-scrAmt,st);}}},getTargetCoord:function(iPageX,iPageY){var x=iPageX-this.deltaX;var y=iPageY-this.deltaY;if(this.constrainX){if(x<this.minX){x=this.minX;}
+if(x>this.maxX){x=this.maxX;}}
+if(this.constrainY){if(y<this.minY){y=this.minY;}
+if(y>this.maxY){y=this.maxY;}}
+x=this.getTick(x,this.xTicks);y=this.getTick(y,this.yTicks);return{x:x,y:y};},applyConfig:function(){Ext.dd.DD.superclass.applyConfig.call(this);this.scroll=(this.config.scroll!==false);},b4MouseDown:function(e){this.autoOffset(e.getPageX(),e.getPageY());},b4Drag:function(e){this.setDragElPos(e.getPageX(),e.getPageY());},toString:function(){return("DD "+this.id);}});Ext.dd.DDProxy=function(id,sGroup,config){if(id){this.init(id,sGroup,config);this.initFrame();}};Ext.dd.DDProxy.dragElId="ygddfdiv";Ext.extend(Ext.dd.DDProxy,Ext.dd.DD,{resizeFrame:true,centerFrame:false,createFrame:function(){var self=this;var body=document.body;if(!body||!body.firstChild){setTimeout(function(){self.createFrame();},50);return;}
+var div=this.getDragEl();if(!div){div=document.createElement("div");div.id=this.dragElId;var s=div.style;s.position="absolute";s.visibility="hidden";s.cursor="move";s.border="2px solid #aaa";s.zIndex=999;body.insertBefore(div,body.firstChild);}},initFrame:function(){this.createFrame();},applyConfig:function(){Ext.dd.DDProxy.superclass.applyConfig.call(this);this.resizeFrame=(this.config.resizeFrame!==false);this.centerFrame=(this.config.centerFrame);this.setDragElId(this.config.dragElId||Ext.dd.DDProxy.dragElId);},showFrame:function(iPageX,iPageY){var el=this.getEl();var dragEl=this.getDragEl();var s=dragEl.style;this._resizeProxy();if(this.centerFrame){this.setDelta(Math.round(parseInt(s.width,10)/2),Math.round(parseInt(s.height,10)/2));}
+this.setDragElPos(iPageX,iPageY);Ext.fly(dragEl).show();},_resizeProxy:function(){if(this.resizeFrame){var el=this.getEl();Ext.fly(this.getDragEl()).setSize(el.offsetWidth,el.offsetHeight);}},b4MouseDown:function(e){var x=e.getPageX();var y=e.getPageY();this.autoOffset(x,y);this.setDragElPos(x,y);},b4StartDrag:function(x,y){this.showFrame(x,y);},b4EndDrag:function(e){Ext.fly(this.getDragEl()).hide();},endDrag:function(e){var lel=this.getEl();var del=this.getDragEl();del.style.visibility="";this.beforeMove();lel.style.visibility="hidden";Ext.dd.DDM.moveToEl(lel,del);del.style.visibility="hidden";lel.style.visibility="";this.afterDrag();},beforeMove:function(){},afterDrag:function(){},toString:function(){return("DDProxy "+this.id);}});Ext.dd.DDTarget=function(id,sGroup,config){if(id){this.initTarget(id,sGroup,config);}};Ext.extend(Ext.dd.DDTarget,Ext.dd.DragDrop,{getDragEl:Ext.emptyFn,isValidHandleChild:Ext.emptyFn,startDrag:Ext.emptyFn,endDrag:Ext.emptyFn,onDrag:Ext.emptyFn,onDragDrop:Ext.emptyFn,onDragEnter:Ext.emptyFn,onDragOut:Ext.emptyFn,onDragOver:Ext.emptyFn,onInvalidDrop:Ext.emptyFn,onMouseDown:Ext.emptyFn,onMouseUp:Ext.emptyFn,setXConstraint:Ext.emptyFn,setYConstraint:Ext.emptyFn,resetConstraints:Ext.emptyFn,clearConstraints:Ext.emptyFn,clearTicks:Ext.emptyFn,setInitPosition:Ext.emptyFn,setDragElId:Ext.emptyFn,setHandleElId:Ext.emptyFn,setOuterHandleElId:Ext.emptyFn,addInvalidHandleClass:Ext.emptyFn,addInvalidHandleId:Ext.emptyFn,addInvalidHandleType:Ext.emptyFn,removeInvalidHandleClass:Ext.emptyFn,removeInvalidHandleId:Ext.emptyFn,removeInvalidHandleType:Ext.emptyFn,toString:function(){return("DDTarget "+this.id);}});Ext.dd.DragTracker=Ext.extend(Ext.util.Observable,{active:false,tolerance:5,autoStart:false,constructor:function(config){Ext.apply(this,config);this.addEvents('mousedown','mouseup','mousemove','dragstart','dragend','drag');this.dragRegion=new Ext.lib.Region(0,0,0,0);if(this.el){this.initEl(this.el);}
+Ext.dd.DragTracker.superclass.constructor.call(this,config);},initEl:function(el){this.el=Ext.get(el);el.on('mousedown',this.onMouseDown,this,this.delegate?{delegate:this.delegate}:undefined);},destroy:function(){this.el.un('mousedown',this.onMouseDown,this);delete this.el;},onMouseDown:function(e,target){if(this.fireEvent('mousedown',this,e)!==false&&this.onBeforeStart(e)!==false){this.startXY=this.lastXY=e.getXY();this.dragTarget=this.delegate?target:this.el.dom;if(this.preventDefault!==false){e.preventDefault();}
+Ext.getDoc().on({scope:this,mouseup:this.onMouseUp,mousemove:this.onMouseMove,selectstart:this.stopSelect});if(this.autoStart){this.timer=this.triggerStart.defer(this.autoStart===true?1000:this.autoStart,this,[e]);}}},onMouseMove:function(e,target){if(this.active&&Ext.isIE&&!e.browserEvent.button){e.preventDefault();this.onMouseUp(e);return;}
+e.preventDefault();var xy=e.getXY(),s=this.startXY;this.lastXY=xy;if(!this.active){if(Math.abs(s[0]-xy[0])>this.tolerance||Math.abs(s[1]-xy[1])>this.tolerance){this.triggerStart(e);}else{return;}}
+this.fireEvent('mousemove',this,e);this.onDrag(e);this.fireEvent('drag',this,e);},onMouseUp:function(e){var doc=Ext.getDoc(),wasActive=this.active;doc.un('mousemove',this.onMouseMove,this);doc.un('mouseup',this.onMouseUp,this);doc.un('selectstart',this.stopSelect,this);e.preventDefault();this.clearStart();this.active=false;delete this.elRegion;this.fireEvent('mouseup',this,e);if(wasActive){this.onEnd(e);this.fireEvent('dragend',this,e);}},triggerStart:function(e){this.clearStart();this.active=true;this.onStart(e);this.fireEvent('dragstart',this,e);},clearStart:function(){if(this.timer){clearTimeout(this.timer);delete this.timer;}},stopSelect:function(e){e.stopEvent();return false;},onBeforeStart:function(e){},onStart:function(xy){},onDrag:function(e){},onEnd:function(e){},getDragTarget:function(){return this.dragTarget;},getDragCt:function(){return this.el;},getXY:function(constrain){return constrain?this.constrainModes[constrain].call(this,this.lastXY):this.lastXY;},getOffset:function(constrain){var xy=this.getXY(constrain),s=this.startXY;return[s[0]-xy[0],s[1]-xy[1]];},constrainModes:{'point':function(xy){if(!this.elRegion){this.elRegion=this.getDragCt().getRegion();}
+var dr=this.dragRegion;dr.left=xy[0];dr.top=xy[1];dr.right=xy[0];dr.bottom=xy[1];dr.constrainTo(this.elRegion);return[dr.left,dr.top];}}});Ext.dd.ScrollManager=function(){var ddm=Ext.dd.DragDropMgr;var els={};var dragEl=null;var proc={};var onStop=function(e){dragEl=null;clearProc();};var triggerRefresh=function(){if(ddm.dragCurrent){ddm.refreshCache(ddm.dragCurrent.groups);}};var doScroll=function(){if(ddm.dragCurrent){var dds=Ext.dd.ScrollManager;var inc=proc.el.ddScrollConfig?proc.el.ddScrollConfig.increment:dds.increment;if(!dds.animate){if(proc.el.scroll(proc.dir,inc)){triggerRefresh();}}else{proc.el.scroll(proc.dir,inc,true,dds.animDuration,triggerRefresh);}}};var clearProc=function(){if(proc.id){clearInterval(proc.id);}
+proc.id=0;proc.el=null;proc.dir="";};var startProc=function(el,dir){clearProc();proc.el=el;proc.dir=dir;var group=el.ddScrollConfig?el.ddScrollConfig.ddGroup:undefined,freq=(el.ddScrollConfig&&el.ddScrollConfig.frequency)?el.ddScrollConfig.frequency:Ext.dd.ScrollManager.frequency;if(group===undefined||ddm.dragCurrent.ddGroup==group){proc.id=setInterval(doScroll,freq);}};var onFire=function(e,isDrop){if(isDrop||!ddm.dragCurrent){return;}
+var dds=Ext.dd.ScrollManager;if(!dragEl||dragEl!=ddm.dragCurrent){dragEl=ddm.dragCurrent;dds.refreshCache();}
+var xy=Ext.lib.Event.getXY(e);var pt=new Ext.lib.Point(xy[0],xy[1]);for(var id in els){var el=els[id],r=el._region;var c=el.ddScrollConfig?el.ddScrollConfig:dds;if(r&&r.contains(pt)&&el.isScrollable()){if(r.bottom-pt.y<=c.vthresh){if(proc.el!=el){startProc(el,"down");}
+return;}else if(r.right-pt.x<=c.hthresh){if(proc.el!=el){startProc(el,"left");}
+return;}else if(pt.y-r.top<=c.vthresh){if(proc.el!=el){startProc(el,"up");}
+return;}else if(pt.x-r.left<=c.hthresh){if(proc.el!=el){startProc(el,"right");}
+return;}}}
+clearProc();};ddm.fireEvents=ddm.fireEvents.createSequence(onFire,ddm);ddm.stopDrag=ddm.stopDrag.createSequence(onStop,ddm);return{register:function(el){if(Ext.isArray(el)){for(var i=0,len=el.length;i<len;i++){this.register(el[i]);}}else{el=Ext.get(el);els[el.id]=el;}},unregister:function(el){if(Ext.isArray(el)){for(var i=0,len=el.length;i<len;i++){this.unregister(el[i]);}}else{el=Ext.get(el);delete els[el.id];}},vthresh:25,hthresh:25,increment:100,frequency:500,animate:true,animDuration:.4,ddGroup:undefined,refreshCache:function(){for(var id in els){if(typeof els[id]=='object'){els[id]._region=els[id].getRegion();}}}};}();Ext.dd.Registry=function(){var elements={};var handles={};var autoIdSeed=0;var getId=function(el,autogen){if(typeof el=="string"){return el;}
+var id=el.id;if(!id&&autogen!==false){id="extdd-"+(++autoIdSeed);el.id=id;}
+return id;};return{register:function(el,data){data=data||{};if(typeof el=="string"){el=document.getElementById(el);}
+data.ddel=el;elements[getId(el)]=data;if(data.isHandle!==false){handles[data.ddel.id]=data;}
+if(data.handles){var hs=data.handles;for(var i=0,len=hs.length;i<len;i++){handles[getId(hs[i])]=data;}}},unregister:function(el){var id=getId(el,false);var data=elements[id];if(data){delete elements[id];if(data.handles){var hs=data.handles;for(var i=0,len=hs.length;i<len;i++){delete handles[getId(hs[i],false)];}}}},getHandle:function(id){if(typeof id!="string"){id=id.id;}
+return handles[id];},getHandleFromEvent:function(e){var t=Ext.lib.Event.getTarget(e);return t?handles[t.id]:null;},getTarget:function(id){if(typeof id!="string"){id=id.id;}
+return elements[id];},getTargetFromEvent:function(e){var t=Ext.lib.Event.getTarget(e);return t?elements[t.id]||handles[t.id]:null;}};}();Ext.dd.StatusProxy=function(config){Ext.apply(this,config);this.id=this.id||Ext.id();this.el=new Ext.Layer({dh:{id:this.id,tag:"div",cls:"x-dd-drag-proxy "+this.dropNotAllowed,children:[{tag:"div",cls:"x-dd-drop-icon"},{tag:"div",cls:"x-dd-drag-ghost"}]},shadow:!config||config.shadow!==false});this.ghost=Ext.get(this.el.dom.childNodes[1]);this.dropStatus=this.dropNotAllowed;};Ext.dd.StatusProxy.prototype={dropAllowed:"x-dd-drop-ok",dropNotAllowed:"x-dd-drop-nodrop",setStatus:function(cssClass){cssClass=cssClass||this.dropNotAllowed;if(this.dropStatus!=cssClass){this.el.replaceClass(this.dropStatus,cssClass);this.dropStatus=cssClass;}},reset:function(clearGhost){this.el.dom.className="x-dd-drag-proxy "+this.dropNotAllowed;this.dropStatus=this.dropNotAllowed;if(clearGhost){this.ghost.update("");}},update:function(html){if(typeof html=="string"){this.ghost.update(html);}else{this.ghost.update("");html.style.margin="0";this.ghost.dom.appendChild(html);}
+var el=this.ghost.dom.firstChild;if(el){Ext.fly(el).setStyle('float','none');}},getEl:function(){return this.el;},getGhost:function(){return this.ghost;},hide:function(clear){this.el.hide();if(clear){this.reset(true);}},stop:function(){if(this.anim&&this.anim.isAnimated&&this.anim.isAnimated()){this.anim.stop();}},show:function(){this.el.show();},sync:function(){this.el.sync();},repair:function(xy,callback,scope){this.callback=callback;this.scope=scope;if(xy&&this.animRepair!==false){this.el.addClass("x-dd-drag-repair");this.el.hideUnders(true);this.anim=this.el.shift({duration:this.repairDuration||.5,easing:'easeOut',xy:xy,stopFx:true,callback:this.afterRepair,scope:this});}else{this.afterRepair();}},afterRepair:function(){this.hide(true);if(typeof this.callback=="function"){this.callback.call(this.scope||this);}
+this.callback=null;this.scope=null;},destroy:function(){Ext.destroy(this.ghost,this.el);}};Ext.dd.DragSource=function(el,config){this.el=Ext.get(el);if(!this.dragData){this.dragData={};}
+Ext.apply(this,config);if(!this.proxy){this.proxy=new Ext.dd.StatusProxy();}
+Ext.dd.DragSource.superclass.constructor.call(this,this.el.dom,this.ddGroup||this.group,{dragElId:this.proxy.id,resizeFrame:false,isTarget:false,scroll:this.scroll===true});this.dragging=false;};Ext.extend(Ext.dd.DragSource,Ext.dd.DDProxy,{dropAllowed:"x-dd-drop-ok",dropNotAllowed:"x-dd-drop-nodrop",getDragData:function(e){return this.dragData;},onDragEnter:function(e,id){var target=Ext.dd.DragDropMgr.getDDById(id);this.cachedTarget=target;if(this.beforeDragEnter(target,e,id)!==false){if(target.isNotifyTarget){var status=target.notifyEnter(this,e,this.dragData);this.proxy.setStatus(status);}else{this.proxy.setStatus(this.dropAllowed);}
+if(this.afterDragEnter){this.afterDragEnter(target,e,id);}}},beforeDragEnter:function(target,e,id){return true;},alignElWithMouse:function(){Ext.dd.DragSource.superclass.alignElWithMouse.apply(this,arguments);this.proxy.sync();},onDragOver:function(e,id){var target=this.cachedTarget||Ext.dd.DragDropMgr.getDDById(id);if(this.beforeDragOver(target,e,id)!==false){if(target.isNotifyTarget){var status=target.notifyOver(this,e,this.dragData);this.proxy.setStatus(status);}
+if(this.afterDragOver){this.afterDragOver(target,e,id);}}},beforeDragOver:function(target,e,id){return true;},onDragOut:function(e,id){var target=this.cachedTarget||Ext.dd.DragDropMgr.getDDById(id);if(this.beforeDragOut(target,e,id)!==false){if(target.isNotifyTarget){target.notifyOut(this,e,this.dragData);}
+this.proxy.reset();if(this.afterDragOut){this.afterDragOut(target,e,id);}}
+this.cachedTarget=null;},beforeDragOut:function(target,e,id){return true;},onDragDrop:function(e,id){var target=this.cachedTarget||Ext.dd.DragDropMgr.getDDById(id);if(this.beforeDragDrop(target,e,id)!==false){if(target.isNotifyTarget){if(target.notifyDrop(this,e,this.dragData)){this.onValidDrop(target,e,id);}else{this.onInvalidDrop(target,e,id);}}else{this.onValidDrop(target,e,id);}
+if(this.afterDragDrop){this.afterDragDrop(target,e,id);}}
+delete this.cachedTarget;},beforeDragDrop:function(target,e,id){return true;},onValidDrop:function(target,e,id){this.hideProxy();if(this.afterValidDrop){this.afterValidDrop(target,e,id);}},getRepairXY:function(e,data){return this.el.getXY();},onInvalidDrop:function(target,e,id){this.beforeInvalidDrop(target,e,id);if(this.cachedTarget){if(this.cachedTarget.isNotifyTarget){this.cachedTarget.notifyOut(this,e,this.dragData);}
+this.cacheTarget=null;}
+this.proxy.repair(this.getRepairXY(e,this.dragData),this.afterRepair,this);if(this.afterInvalidDrop){this.afterInvalidDrop(e,id);}},afterRepair:function(){if(Ext.enableFx){this.el.highlight(this.hlColor||"c3daf9");}
+this.dragging=false;},beforeInvalidDrop:function(target,e,id){return true;},handleMouseDown:function(e){if(this.dragging){return;}
+var data=this.getDragData(e);if(data&&this.onBeforeDrag(data,e)!==false){this.dragData=data;this.proxy.stop();Ext.dd.DragSource.superclass.handleMouseDown.apply(this,arguments);}},onBeforeDrag:function(data,e){return true;},onStartDrag:Ext.emptyFn,startDrag:function(x,y){this.proxy.reset();this.dragging=true;this.proxy.update("");this.onInitDrag(x,y);this.proxy.show();},onInitDrag:function(x,y){var clone=this.el.dom.cloneNode(true);clone.id=Ext.id();this.proxy.update(clone);this.onStartDrag(x,y);return true;},getProxy:function(){return this.proxy;},hideProxy:function(){this.proxy.hide();this.proxy.reset(true);this.dragging=false;},triggerCacheRefresh:function(){Ext.dd.DDM.refreshCache(this.groups);},b4EndDrag:function(e){},endDrag:function(e){this.onEndDrag(this.dragData,e);},onEndDrag:function(data,e){},autoOffset:function(x,y){this.setDelta(-12,-20);},destroy:function(){Ext.dd.DragSource.superclass.destroy.call(this);Ext.destroy(this.proxy);}});Ext.dd.DropTarget=Ext.extend(Ext.dd.DDTarget,{constructor:function(el,config){this.el=Ext.get(el);Ext.apply(this,config);if(this.containerScroll){Ext.dd.ScrollManager.register(this.el);}
+Ext.dd.DropTarget.superclass.constructor.call(this,this.el.dom,this.ddGroup||this.group,{isTarget:true});},dropAllowed:"x-dd-drop-ok",dropNotAllowed:"x-dd-drop-nodrop",isTarget:true,isNotifyTarget:true,notifyEnter:function(dd,e,data){if(this.overClass){this.el.addClass(this.overClass);}
+return this.dropAllowed;},notifyOver:function(dd,e,data){return this.dropAllowed;},notifyOut:function(dd,e,data){if(this.overClass){this.el.removeClass(this.overClass);}},notifyDrop:function(dd,e,data){return false;},destroy:function(){Ext.dd.DropTarget.superclass.destroy.call(this);if(this.containerScroll){Ext.dd.ScrollManager.unregister(this.el);}}});Ext.dd.DragZone=Ext.extend(Ext.dd.DragSource,{constructor:function(el,config){Ext.dd.DragZone.superclass.constructor.call(this,el,config);if(this.containerScroll){Ext.dd.ScrollManager.register(this.el);}},getDragData:function(e){return Ext.dd.Registry.getHandleFromEvent(e);},onInitDrag:function(x,y){this.proxy.update(this.dragData.ddel.cloneNode(true));this.onStartDrag(x,y);return true;},afterRepair:function(){if(Ext.enableFx){Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor||"c3daf9");}
+this.dragging=false;},getRepairXY:function(e){return Ext.Element.fly(this.dragData.ddel).getXY();},destroy:function(){Ext.dd.DragZone.superclass.destroy.call(this);if(this.containerScroll){Ext.dd.ScrollManager.unregister(this.el);}}});Ext.dd.DropZone=function(el,config){Ext.dd.DropZone.superclass.constructor.call(this,el,config);};Ext.extend(Ext.dd.DropZone,Ext.dd.DropTarget,{getTargetFromEvent:function(e){return Ext.dd.Registry.getTargetFromEvent(e);},onNodeEnter:function(n,dd,e,data){},onNodeOver:function(n,dd,e,data){return this.dropAllowed;},onNodeOut:function(n,dd,e,data){},onNodeDrop:function(n,dd,e,data){return false;},onContainerOver:function(dd,e,data){return this.dropNotAllowed;},onContainerDrop:function(dd,e,data){return false;},notifyEnter:function(dd,e,data){return this.dropNotAllowed;},notifyOver:function(dd,e,data){var n=this.getTargetFromEvent(e);if(!n){if(this.lastOverNode){this.onNodeOut(this.lastOverNode,dd,e,data);this.lastOverNode=null;}
+return this.onContainerOver(dd,e,data);}
+if(this.lastOverNode!=n){if(this.lastOverNode){this.onNodeOut(this.lastOverNode,dd,e,data);}
+this.onNodeEnter(n,dd,e,data);this.lastOverNode=n;}
+return this.onNodeOver(n,dd,e,data);},notifyOut:function(dd,e,data){if(this.lastOverNode){this.onNodeOut(this.lastOverNode,dd,e,data);this.lastOverNode=null;}},notifyDrop:function(dd,e,data){if(this.lastOverNode){this.onNodeOut(this.lastOverNode,dd,e,data);this.lastOverNode=null;}
+var n=this.getTargetFromEvent(e);return n?this.onNodeDrop(n,dd,e,data):this.onContainerDrop(dd,e,data);},triggerCacheRefresh:function(){Ext.dd.DDM.refreshCache(this.groups);}});Ext.Element.addMethods({initDD:function(group,config,overrides){var dd=new Ext.dd.DD(Ext.id(this.dom),group,config);return Ext.apply(dd,overrides);},initDDProxy:function(group,config,overrides){var dd=new Ext.dd.DDProxy(Ext.id(this.dom),group,config);return Ext.apply(dd,overrides);},initDDTarget:function(group,config,overrides){var dd=new Ext.dd.DDTarget(Ext.id(this.dom),group,config);return Ext.apply(dd,overrides);}});Ext.tree.TreePanel=Ext.extend(Ext.Panel,{rootVisible:true,animate:Ext.enableFx,lines:true,enableDD:false,hlDrop:Ext.enableFx,pathSeparator:'/',bubbleEvents:[],initComponent:function(){Ext.tree.TreePanel.superclass.initComponent.call(this);if(!this.eventModel){this.eventModel=new Ext.tree.TreeEventModel(this);}
+var l=this.loader;if(!l){l=new Ext.tree.TreeLoader({dataUrl:this.dataUrl,requestMethod:this.requestMethod});}else if(Ext.isObject(l)&&!l.load){l=new Ext.tree.TreeLoader(l);}
+this.loader=l;this.nodeHash={};if(this.root){var r=this.root;delete this.root;this.setRootNode(r);}
+this.addEvents('append','remove','movenode','insert','beforeappend','beforeremove','beforemovenode','beforeinsert','beforeload','load','textchange','beforeexpandnode','beforecollapsenode','expandnode','disabledchange','collapsenode','beforeclick','click','containerclick','checkchange','beforedblclick','dblclick','containerdblclick','contextmenu','containercontextmenu','beforechildrenrendered','startdrag','enddrag','dragdrop','beforenodedrop','nodedrop','nodedragover');if(this.singleExpand){this.on('beforeexpandnode',this.restrictExpand,this);}},proxyNodeEvent:function(ename,a1,a2,a3,a4,a5,a6){if(ename=='collapse'||ename=='expand'||ename=='beforecollapse'||ename=='beforeexpand'||ename=='move'||ename=='beforemove'){ename=ename+'node';}
+return this.fireEvent(ename,a1,a2,a3,a4,a5,a6);},getRootNode:function(){return this.root;},setRootNode:function(node){this.destroyRoot();if(!node.render){node=this.loader.createNode(node);}
+this.root=node;node.ownerTree=this;node.isRoot=true;this.registerNode(node);if(!this.rootVisible){var uiP=node.attributes.uiProvider;node.ui=uiP?new uiP(node):new Ext.tree.RootTreeNodeUI(node);}
+if(this.innerCt){this.clearInnerCt();this.renderRoot();}
+return node;},clearInnerCt:function(){this.innerCt.update('');},renderRoot:function(){this.root.render();if(!this.rootVisible){this.root.renderChildren();}},getNodeById:function(id){return this.nodeHash[id];},registerNode:function(node){this.nodeHash[node.id]=node;},unregisterNode:function(node){delete this.nodeHash[node.id];},toString:function(){return'[Tree'+(this.id?' '+this.id:'')+']';},restrictExpand:function(node){var p=node.parentNode;if(p){if(p.expandedChild&&p.expandedChild.parentNode==p){p.expandedChild.collapse();}
+p.expandedChild=node;}},getChecked:function(a,startNode){startNode=startNode||this.root;var r=[];var f=function(){if(this.attributes.checked){r.push(!a?this:(a=='id'?this.id:this.attributes[a]));}};startNode.cascade(f);return r;},getLoader:function(){return this.loader;},expandAll:function(){this.root.expand(true);},collapseAll:function(){this.root.collapse(true);},getSelectionModel:function(){if(!this.selModel){this.selModel=new Ext.tree.DefaultSelectionModel();}
+return this.selModel;},expandPath:function(path,attr,callback){if(Ext.isEmpty(path)){if(callback){callback(false,undefined);}
+return;}
+attr=attr||'id';var keys=path.split(this.pathSeparator);var curNode=this.root;if(curNode.attributes[attr]!=keys[1]){if(callback){callback(false,null);}
+return;}
+var index=1;var f=function(){if(++index==keys.length){if(callback){callback(true,curNode);}
+return;}
+var c=curNode.findChild(attr,keys[index]);if(!c){if(callback){callback(false,curNode);}
+return;}
+curNode=c;c.expand(false,false,f);};curNode.expand(false,false,f);},selectPath:function(path,attr,callback){if(Ext.isEmpty(path)){if(callback){callback(false,undefined);}
+return;}
+attr=attr||'id';var keys=path.split(this.pathSeparator),v=keys.pop();if(keys.length>1){var f=function(success,node){if(success&&node){var n=node.findChild(attr,v);if(n){n.select();if(callback){callback(true,n);}}else if(callback){callback(false,n);}}else{if(callback){callback(false,n);}}};this.expandPath(keys.join(this.pathSeparator),attr,f);}else{this.root.select();if(callback){callback(true,this.root);}}},getTreeEl:function(){return this.body;},onRender:function(ct,position){Ext.tree.TreePanel.superclass.onRender.call(this,ct,position);this.el.addClass('x-tree');this.innerCt=this.body.createChild({tag:'ul',cls:'x-tree-root-ct '+
+(this.useArrows?'x-tree-arrows':this.lines?'x-tree-lines':'x-tree-no-lines')});},initEvents:function(){Ext.tree.TreePanel.superclass.initEvents.call(this);if(this.containerScroll){Ext.dd.ScrollManager.register(this.body);}
+if((this.enableDD||this.enableDrop)&&!this.dropZone){this.dropZone=new Ext.tree.TreeDropZone(this,this.dropConfig||{ddGroup:this.ddGroup||'TreeDD',appendOnly:this.ddAppendOnly===true});}
+if((this.enableDD||this.enableDrag)&&!this.dragZone){this.dragZone=new Ext.tree.TreeDragZone(this,this.dragConfig||{ddGroup:this.ddGroup||'TreeDD',scroll:this.ddScroll});}
+this.getSelectionModel().init(this);},afterRender:function(){Ext.tree.TreePanel.superclass.afterRender.call(this);this.renderRoot();},beforeDestroy:function(){if(this.rendered){Ext.dd.ScrollManager.unregister(this.body);Ext.destroy(this.dropZone,this.dragZone);}
+this.destroyRoot();Ext.destroy(this.loader);this.nodeHash=this.root=this.loader=null;Ext.tree.TreePanel.superclass.beforeDestroy.call(this);},destroyRoot:function(){if(this.root&&this.root.destroy){this.root.destroy(true);}}});Ext.tree.TreePanel.nodeTypes={};Ext.reg('treepanel',Ext.tree.TreePanel);Ext.tree.TreeEventModel=function(tree){this.tree=tree;this.tree.on('render',this.initEvents,this);};Ext.tree.TreeEventModel.prototype={initEvents:function(){var t=this.tree;if(t.trackMouseOver!==false){t.mon(t.innerCt,{scope:this,mouseover:this.delegateOver,mouseout:this.delegateOut});}
+t.mon(t.getTreeEl(),{scope:this,click:this.delegateClick,dblclick:this.delegateDblClick,contextmenu:this.delegateContextMenu});},getNode:function(e){var t;if(t=e.getTarget('.x-tree-node-el',10)){var id=Ext.fly(t,'_treeEvents').getAttribute('tree-node-id','ext');if(id){return this.tree.getNodeById(id);}}
+return null;},getNodeTarget:function(e){var t=e.getTarget('.x-tree-node-icon',1);if(!t){t=e.getTarget('.x-tree-node-el',6);}
+return t;},delegateOut:function(e,t){if(!this.beforeEvent(e)){return;}
+if(e.getTarget('.x-tree-ec-icon',1)){var n=this.getNode(e);this.onIconOut(e,n);if(n==this.lastEcOver){delete this.lastEcOver;}}
+if((t=this.getNodeTarget(e))&&!e.within(t,true)){this.onNodeOut(e,this.getNode(e));}},delegateOver:function(e,t){if(!this.beforeEvent(e)){return;}
+if(Ext.isGecko&&!this.trackingDoc){Ext.getBody().on('mouseover',this.trackExit,this);this.trackingDoc=true;}
+if(this.lastEcOver){this.onIconOut(e,this.lastEcOver);delete this.lastEcOver;}
+if(e.getTarget('.x-tree-ec-icon',1)){this.lastEcOver=this.getNode(e);this.onIconOver(e,this.lastEcOver);}
+if(t=this.getNodeTarget(e)){this.onNodeOver(e,this.getNode(e));}},trackExit:function(e){if(this.lastOverNode){if(this.lastOverNode.ui&&!e.within(this.lastOverNode.ui.getEl())){this.onNodeOut(e,this.lastOverNode);}
+delete this.lastOverNode;Ext.getBody().un('mouseover',this.trackExit,this);this.trackingDoc=false;}},delegateClick:function(e,t){if(this.beforeEvent(e)){if(e.getTarget('input[type=checkbox]',1)){this.onCheckboxClick(e,this.getNode(e));}else if(e.getTarget('.x-tree-ec-icon',1)){this.onIconClick(e,this.getNode(e));}else if(this.getNodeTarget(e)){this.onNodeClick(e,this.getNode(e));}}else{this.checkContainerEvent(e,'click');}},delegateDblClick:function(e,t){if(this.beforeEvent(e)){if(this.getNodeTarget(e)){this.onNodeDblClick(e,this.getNode(e));}}else{this.checkContainerEvent(e,'dblclick');}},delegateContextMenu:function(e,t){if(this.beforeEvent(e)){if(this.getNodeTarget(e)){this.onNodeContextMenu(e,this.getNode(e));}}else{this.checkContainerEvent(e,'contextmenu');}},checkContainerEvent:function(e,type){if(this.disabled){e.stopEvent();return false;}
+this.onContainerEvent(e,type);},onContainerEvent:function(e,type){this.tree.fireEvent('container'+type,this.tree,e);},onNodeClick:function(e,node){node.ui.onClick(e);},onNodeOver:function(e,node){this.lastOverNode=node;node.ui.onOver(e);},onNodeOut:function(e,node){node.ui.onOut(e);},onIconOver:function(e,node){node.ui.addClass('x-tree-ec-over');},onIconOut:function(e,node){node.ui.removeClass('x-tree-ec-over');},onIconClick:function(e,node){node.ui.ecClick(e);},onCheckboxClick:function(e,node){node.ui.onCheckChange(e);},onNodeDblClick:function(e,node){node.ui.onDblClick(e);},onNodeContextMenu:function(e,node){node.ui.onContextMenu(e);},beforeEvent:function(e){var node=this.getNode(e);if(this.disabled||!node||!node.ui){e.stopEvent();return false;}
+return true;},disable:function(){this.disabled=true;},enable:function(){this.disabled=false;}};Ext.tree.DefaultSelectionModel=Ext.extend(Ext.util.Observable,{constructor:function(config){this.selNode=null;this.addEvents('selectionchange','beforeselect');Ext.apply(this,config);Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);},init:function(tree){this.tree=tree;tree.mon(tree.getTreeEl(),'keydown',this.onKeyDown,this);tree.on('click',this.onNodeClick,this);},onNodeClick:function(node,e){this.select(node);},select:function(node,selectNextNode){if(!Ext.fly(node.ui.wrap).isVisible()&&selectNextNode){return selectNextNode.call(this,node);}
+var last=this.selNode;if(node==last){node.ui.onSelectedChange(true);}else if(this.fireEvent('beforeselect',this,node,last)!==false){if(last&&last.ui){last.ui.onSelectedChange(false);}
+this.selNode=node;node.ui.onSelectedChange(true);this.fireEvent('selectionchange',this,node,last);}
+return node;},unselect:function(node,silent){if(this.selNode==node){this.clearSelections(silent);}},clearSelections:function(silent){var n=this.selNode;if(n){n.ui.onSelectedChange(false);this.selNode=null;if(silent!==true){this.fireEvent('selectionchange',this,null);}}
+return n;},getSelectedNode:function(){return this.selNode;},isSelected:function(node){return this.selNode==node;},selectPrevious:function(s){if(!(s=s||this.selNode||this.lastSelNode)){return null;}
+var ps=s.previousSibling;if(ps){if(!ps.isExpanded()||ps.childNodes.length<1){return this.select(ps,this.selectPrevious);}else{var lc=ps.lastChild;while(lc&&lc.isExpanded()&&Ext.fly(lc.ui.wrap).isVisible()&&lc.childNodes.length>0){lc=lc.lastChild;}
+return this.select(lc,this.selectPrevious);}}else if(s.parentNode&&(this.tree.rootVisible||!s.parentNode.isRoot)){return this.select(s.parentNode,this.selectPrevious);}
+return null;},selectNext:function(s){if(!(s=s||this.selNode||this.lastSelNode)){return null;}
+if(s.firstChild&&s.isExpanded()&&Ext.fly(s.ui.wrap).isVisible()){return this.select(s.firstChild,this.selectNext);}else if(s.nextSibling){return this.select(s.nextSibling,this.selectNext);}else if(s.parentNode){var newS=null;s.parentNode.bubble(function(){if(this.nextSibling){newS=this.getOwnerTree().selModel.select(this.nextSibling,this.selectNext);return false;}});return newS;}
+return null;},onKeyDown:function(e){var s=this.selNode||this.lastSelNode;var sm=this;if(!s){return;}
+var k=e.getKey();switch(k){case e.DOWN:e.stopEvent();this.selectNext();break;case e.UP:e.stopEvent();this.selectPrevious();break;case e.RIGHT:e.preventDefault();if(s.hasChildNodes()){if(!s.isExpanded()){s.expand();}else if(s.firstChild){this.select(s.firstChild,e);}}
+break;case e.LEFT:e.preventDefault();if(s.hasChildNodes()&&s.isExpanded()){s.collapse();}else if(s.parentNode&&(this.tree.rootVisible||s.parentNode!=this.tree.getRootNode())){this.select(s.parentNode,e);}
+break;};}});Ext.tree.MultiSelectionModel=Ext.extend(Ext.util.Observable,{constructor:function(config){this.selNodes=[];this.selMap={};this.addEvents('selectionchange');Ext.apply(this,config);Ext.tree.MultiSelectionModel.superclass.constructor.call(this);},init:function(tree){this.tree=tree;tree.mon(tree.getTreeEl(),'keydown',this.onKeyDown,this);tree.on('click',this.onNodeClick,this);},onNodeClick:function(node,e){if(e.ctrlKey&&this.isSelected(node)){this.unselect(node);}else{this.select(node,e,e.ctrlKey);}},select:function(node,e,keepExisting){if(keepExisting!==true){this.clearSelections(true);}
+if(this.isSelected(node)){this.lastSelNode=node;return node;}
+this.selNodes.push(node);this.selMap[node.id]=node;this.lastSelNode=node;node.ui.onSelectedChange(true);this.fireEvent('selectionchange',this,this.selNodes);return node;},unselect:function(node){if(this.selMap[node.id]){node.ui.onSelectedChange(false);var sn=this.selNodes;var index=sn.indexOf(node);if(index!=-1){this.selNodes.splice(index,1);}
+delete this.selMap[node.id];this.fireEvent('selectionchange',this,this.selNodes);}},clearSelections:function(suppressEvent){var sn=this.selNodes;if(sn.length>0){for(var i=0,len=sn.length;i<len;i++){sn[i].ui.onSelectedChange(false);}
+this.selNodes=[];this.selMap={};if(suppressEvent!==true){this.fireEvent('selectionchange',this,this.selNodes);}}},isSelected:function(node){return this.selMap[node.id]?true:false;},getSelectedNodes:function(){return this.selNodes.concat([]);},onKeyDown:Ext.tree.DefaultSelectionModel.prototype.onKeyDown,selectNext:Ext.tree.DefaultSelectionModel.prototype.selectNext,selectPrevious:Ext.tree.DefaultSelectionModel.prototype.selectPrevious});Ext.data.Tree=Ext.extend(Ext.util.Observable,{constructor:function(root){this.nodeHash={};this.root=null;if(root){this.setRootNode(root);}
+this.addEvents("append","remove","move","insert","beforeappend","beforeremove","beforemove","beforeinsert");Ext.data.Tree.superclass.constructor.call(this);},pathSeparator:"/",proxyNodeEvent:function(){return this.fireEvent.apply(this,arguments);},getRootNode:function(){return this.root;},setRootNode:function(node){this.root=node;node.ownerTree=this;node.isRoot=true;this.registerNode(node);return node;},getNodeById:function(id){return this.nodeHash[id];},registerNode:function(node){this.nodeHash[node.id]=node;},unregisterNode:function(node){delete this.nodeHash[node.id];},toString:function(){return"[Tree"+(this.id?" "+this.id:"")+"]";}});Ext.data.Node=Ext.extend(Ext.util.Observable,{constructor:function(attributes){this.attributes=attributes||{};this.leaf=this.attributes.leaf;this.id=this.attributes.id;if(!this.id){this.id=Ext.id(null,"xnode-");this.attributes.id=this.id;}
+this.childNodes=[];this.parentNode=null;this.firstChild=null;this.lastChild=null;this.previousSibling=null;this.nextSibling=null;this.addEvents({"append":true,"remove":true,"move":true,"insert":true,"beforeappend":true,"beforeremove":true,"beforemove":true,"beforeinsert":true});this.listeners=this.attributes.listeners;Ext.data.Node.superclass.constructor.call(this);},fireEvent:function(evtName){if(Ext.data.Node.superclass.fireEvent.apply(this,arguments)===false){return false;}
+var ot=this.getOwnerTree();if(ot){if(ot.proxyNodeEvent.apply(ot,arguments)===false){return false;}}
+return true;},isLeaf:function(){return this.leaf===true;},setFirstChild:function(node){this.firstChild=node;},setLastChild:function(node){this.lastChild=node;},isLast:function(){return(!this.parentNode?true:this.parentNode.lastChild==this);},isFirst:function(){return(!this.parentNode?true:this.parentNode.firstChild==this);},hasChildNodes:function(){return!this.isLeaf()&&this.childNodes.length>0;},isExpandable:function(){return this.attributes.expandable||this.hasChildNodes();},appendChild:function(node){var multi=false;if(Ext.isArray(node)){multi=node;}else if(arguments.length>1){multi=arguments;}
+if(multi){for(var i=0,len=multi.length;i<len;i++){this.appendChild(multi[i]);}}else{if(this.fireEvent("beforeappend",this.ownerTree,this,node)===false){return false;}
+var index=this.childNodes.length;var oldParent=node.parentNode;if(oldParent){if(node.fireEvent("beforemove",node.getOwnerTree(),node,oldParent,this,index)===false){return false;}
+oldParent.removeChild(node);}
+index=this.childNodes.length;if(index===0){this.setFirstChild(node);}
+this.childNodes.push(node);node.parentNode=this;var ps=this.childNodes[index-1];if(ps){node.previousSibling=ps;ps.nextSibling=node;}else{node.previousSibling=null;}
+node.nextSibling=null;this.setLastChild(node);node.setOwnerTree(this.getOwnerTree());this.fireEvent("append",this.ownerTree,this,node,index);if(oldParent){node.fireEvent("move",this.ownerTree,node,oldParent,this,index);}
+return node;}},removeChild:function(node,destroy){var index=this.childNodes.indexOf(node);if(index==-1){return false;}
+if(this.fireEvent("beforeremove",this.ownerTree,this,node)===false){return false;}
+this.childNodes.splice(index,1);if(node.previousSibling){node.previousSibling.nextSibling=node.nextSibling;}
+if(node.nextSibling){node.nextSibling.previousSibling=node.previousSibling;}
+if(this.firstChild==node){this.setFirstChild(node.nextSibling);}
+if(this.lastChild==node){this.setLastChild(node.previousSibling);}
+this.fireEvent("remove",this.ownerTree,this,node);if(destroy){node.destroy(true);}else{node.clear();}
+return node;},clear:function(destroy){this.setOwnerTree(null,destroy);this.parentNode=this.previousSibling=this.nextSibling=null;if(destroy){this.firstChild=this.lastChild=null;}},destroy:function(silent){if(silent===true){this.purgeListeners();this.clear(true);Ext.each(this.childNodes,function(n){n.destroy(true);});this.childNodes=null;}else{this.remove(true);}},insertBefore:function(node,refNode){if(!refNode){return this.appendChild(node);}
+if(node==refNode){return false;}
+if(this.fireEvent("beforeinsert",this.ownerTree,this,node,refNode)===false){return false;}
+var index=this.childNodes.indexOf(refNode);var oldParent=node.parentNode;var refIndex=index;if(oldParent==this&&this.childNodes.indexOf(node)<index){refIndex--;}
+if(oldParent){if(node.fireEvent("beforemove",node.getOwnerTree(),node,oldParent,this,index,refNode)===false){return false;}
+oldParent.removeChild(node);}
+if(refIndex===0){this.setFirstChild(node);}
+this.childNodes.splice(refIndex,0,node);node.parentNode=this;var ps=this.childNodes[refIndex-1];if(ps){node.previousSibling=ps;ps.nextSibling=node;}else{node.previousSibling=null;}
+node.nextSibling=refNode;refNode.previousSibling=node;node.setOwnerTree(this.getOwnerTree());this.fireEvent("insert",this.ownerTree,this,node,refNode);if(oldParent){node.fireEvent("move",this.ownerTree,node,oldParent,this,refIndex,refNode);}
+return node;},remove:function(destroy){if(this.parentNode){this.parentNode.removeChild(this,destroy);}
+return this;},removeAll:function(destroy){var cn=this.childNodes,n;while((n=cn[0])){this.removeChild(n,destroy);}
+return this;},item:function(index){return this.childNodes[index];},replaceChild:function(newChild,oldChild){var s=oldChild?oldChild.nextSibling:null;this.removeChild(oldChild);this.insertBefore(newChild,s);return oldChild;},indexOf:function(child){return this.childNodes.indexOf(child);},getOwnerTree:function(){if(!this.ownerTree){var p=this;while(p){if(p.ownerTree){this.ownerTree=p.ownerTree;break;}
+p=p.parentNode;}}
+return this.ownerTree;},getDepth:function(){var depth=0;var p=this;while(p.parentNode){++depth;p=p.parentNode;}
+return depth;},setOwnerTree:function(tree,destroy){if(tree!=this.ownerTree){if(this.ownerTree){this.ownerTree.unregisterNode(this);}
+this.ownerTree=tree;if(destroy!==true){Ext.each(this.childNodes,function(n){n.setOwnerTree(tree);});}
+if(tree){tree.registerNode(this);}}},setId:function(id){if(id!==this.id){var t=this.ownerTree;if(t){t.unregisterNode(this);}
+this.id=this.attributes.id=id;if(t){t.registerNode(this);}
+this.onIdChange(id);}},onIdChange:Ext.emptyFn,getPath:function(attr){attr=attr||"id";var p=this.parentNode;var b=[this.attributes[attr]];while(p){b.unshift(p.attributes[attr]);p=p.parentNode;}
+var sep=this.getOwnerTree().pathSeparator;return sep+b.join(sep);},bubble:function(fn,scope,args){var p=this;while(p){if(fn.apply(scope||p,args||[p])===false){break;}
+p=p.parentNode;}},cascade:function(fn,scope,args){if(fn.apply(scope||this,args||[this])!==false){var cs=this.childNodes;for(var i=0,len=cs.length;i<len;i++){cs[i].cascade(fn,scope,args);}}},eachChild:function(fn,scope,args){var cs=this.childNodes;for(var i=0,len=cs.length;i<len;i++){if(fn.apply(scope||cs[i],args||[cs[i]])===false){break;}}},findChild:function(attribute,value,deep){return this.findChildBy(function(){return this.attributes[attribute]==value;},null,deep);},findChildBy:function(fn,scope,deep){var cs=this.childNodes,len=cs.length,i=0,n,res;for(;i<len;i++){n=cs[i];if(fn.call(scope||n,n)===true){return n;}else if(deep){res=n.findChildBy(fn,scope,deep);if(res!=null){return res;}}}
+return null;},sort:function(fn,scope){var cs=this.childNodes;var len=cs.length;if(len>0){var sortFn=scope?function(){fn.apply(scope,arguments);}:fn;cs.sort(sortFn);for(var i=0;i<len;i++){var n=cs[i];n.previousSibling=cs[i-1];n.nextSibling=cs[i+1];if(i===0){this.setFirstChild(n);}
+if(i==len-1){this.setLastChild(n);}}}},contains:function(node){return node.isAncestor(this);},isAncestor:function(node){var p=this.parentNode;while(p){if(p==node){return true;}
+p=p.parentNode;}
+return false;},toString:function(){return"[Node"+(this.id?" "+this.id:"")+"]";}});Ext.tree.TreeNode=Ext.extend(Ext.data.Node,{constructor:function(attributes){attributes=attributes||{};if(Ext.isString(attributes)){attributes={text:attributes};}
+this.childrenRendered=false;this.rendered=false;Ext.tree.TreeNode.superclass.constructor.call(this,attributes);this.expanded=attributes.expanded===true;this.isTarget=attributes.isTarget!==false;this.draggable=attributes.draggable!==false&&attributes.allowDrag!==false;this.allowChildren=attributes.allowChildren!==false&&attributes.allowDrop!==false;this.text=attributes.text;this.disabled=attributes.disabled===true;this.hidden=attributes.hidden===true;this.addEvents('textchange','beforeexpand','beforecollapse','expand','disabledchange','collapse','beforeclick','click','checkchange','beforedblclick','dblclick','contextmenu','beforechildrenrendered');var uiClass=this.attributes.uiProvider||this.defaultUI||Ext.tree.TreeNodeUI;this.ui=new uiClass(this);},preventHScroll:true,isExpanded:function(){return this.expanded;},getUI:function(){return this.ui;},getLoader:function(){var owner;return this.loader||((owner=this.getOwnerTree())&&owner.loader?owner.loader:(this.loader=new Ext.tree.TreeLoader()));},setFirstChild:function(node){var of=this.firstChild;Ext.tree.TreeNode.superclass.setFirstChild.call(this,node);if(this.childrenRendered&&of&&node!=of){of.renderIndent(true,true);}
+if(this.rendered){this.renderIndent(true,true);}},setLastChild:function(node){var ol=this.lastChild;Ext.tree.TreeNode.superclass.setLastChild.call(this,node);if(this.childrenRendered&&ol&&node!=ol){ol.renderIndent(true,true);}
+if(this.rendered){this.renderIndent(true,true);}},appendChild:function(n){if(!n.render&&!Ext.isArray(n)){n=this.getLoader().createNode(n);}
+var node=Ext.tree.TreeNode.superclass.appendChild.call(this,n);if(node&&this.childrenRendered){node.render();}
+this.ui.updateExpandIcon();return node;},removeChild:function(node,destroy){this.ownerTree.getSelectionModel().unselect(node);Ext.tree.TreeNode.superclass.removeChild.apply(this,arguments);if(!destroy){var rendered=node.ui.rendered;if(rendered){node.ui.remove();}
+if(rendered&&this.childNodes.length<1){this.collapse(false,false);}else{this.ui.updateExpandIcon();}
+if(!this.firstChild&&!this.isHiddenRoot()){this.childrenRendered=false;}}
+return node;},insertBefore:function(node,refNode){if(!node.render){node=this.getLoader().createNode(node);}
+var newNode=Ext.tree.TreeNode.superclass.insertBefore.call(this,node,refNode);if(newNode&&refNode&&this.childrenRendered){node.render();}
+this.ui.updateExpandIcon();return newNode;},setText:function(text){var oldText=this.text;this.text=this.attributes.text=text;if(this.rendered){this.ui.onTextChange(this,text,oldText);}
+this.fireEvent('textchange',this,text,oldText);},setIconCls:function(cls){var old=this.attributes.iconCls;this.attributes.iconCls=cls;if(this.rendered){this.ui.onIconClsChange(this,cls,old);}},setTooltip:function(tip,title){this.attributes.qtip=tip;this.attributes.qtipTitle=title;if(this.rendered){this.ui.onTipChange(this,tip,title);}},setIcon:function(icon){this.attributes.icon=icon;if(this.rendered){this.ui.onIconChange(this,icon);}},setHref:function(href,target){this.attributes.href=href;this.attributes.hrefTarget=target;if(this.rendered){this.ui.onHrefChange(this,href,target);}},setCls:function(cls){var old=this.attributes.cls;this.attributes.cls=cls;if(this.rendered){this.ui.onClsChange(this,cls,old);}},select:function(){var t=this.getOwnerTree();if(t){t.getSelectionModel().select(this);}},unselect:function(silent){var t=this.getOwnerTree();if(t){t.getSelectionModel().unselect(this,silent);}},isSelected:function(){var t=this.getOwnerTree();return t?t.getSelectionModel().isSelected(this):false;},expand:function(deep,anim,callback,scope){if(!this.expanded){if(this.fireEvent('beforeexpand',this,deep,anim)===false){return;}
+if(!this.childrenRendered){this.renderChildren();}
+this.expanded=true;if(!this.isHiddenRoot()&&(this.getOwnerTree().animate&&anim!==false)||anim){this.ui.animExpand(function(){this.fireEvent('expand',this);this.runCallback(callback,scope||this,[this]);if(deep===true){this.expandChildNodes(true,true);}}.createDelegate(this));return;}else{this.ui.expand();this.fireEvent('expand',this);this.runCallback(callback,scope||this,[this]);}}else{this.runCallback(callback,scope||this,[this]);}
+if(deep===true){this.expandChildNodes(true);}},runCallback:function(cb,scope,args){if(Ext.isFunction(cb)){cb.apply(scope,args);}},isHiddenRoot:function(){return this.isRoot&&!this.getOwnerTree().rootVisible;},collapse:function(deep,anim,callback,scope){if(this.expanded&&!this.isHiddenRoot()){if(this.fireEvent('beforecollapse',this,deep,anim)===false){return;}
+this.expanded=false;if((this.getOwnerTree().animate&&anim!==false)||anim){this.ui.animCollapse(function(){this.fireEvent('collapse',this);this.runCallback(callback,scope||this,[this]);if(deep===true){this.collapseChildNodes(true);}}.createDelegate(this));return;}else{this.ui.collapse();this.fireEvent('collapse',this);this.runCallback(callback,scope||this,[this]);}}else if(!this.expanded){this.runCallback(callback,scope||this,[this]);}
+if(deep===true){var cs=this.childNodes;for(var i=0,len=cs.length;i<len;i++){cs[i].collapse(true,false);}}},delayedExpand:function(delay){if(!this.expandProcId){this.expandProcId=this.expand.defer(delay,this);}},cancelExpand:function(){if(this.expandProcId){clearTimeout(this.expandProcId);}
+this.expandProcId=false;},toggle:function(){if(this.expanded){this.collapse();}else{this.expand();}},ensureVisible:function(callback,scope){var tree=this.getOwnerTree();tree.expandPath(this.parentNode?this.parentNode.getPath():this.getPath(),false,function(){var node=tree.getNodeById(this.id);tree.getTreeEl().scrollChildIntoView(node.ui.anchor);this.runCallback(callback,scope||this,[this]);}.createDelegate(this));},expandChildNodes:function(deep,anim){var cs=this.childNodes,i,len=cs.length;for(i=0;i<len;i++){cs[i].expand(deep,anim);}},collapseChildNodes:function(deep){var cs=this.childNodes;for(var i=0,len=cs.length;i<len;i++){cs[i].collapse(deep);}},disable:function(){this.disabled=true;this.unselect();if(this.rendered&&this.ui.onDisableChange){this.ui.onDisableChange(this,true);}
+this.fireEvent('disabledchange',this,true);},enable:function(){this.disabled=false;if(this.rendered&&this.ui.onDisableChange){this.ui.onDisableChange(this,false);}
+this.fireEvent('disabledchange',this,false);},renderChildren:function(suppressEvent){if(suppressEvent!==false){this.fireEvent('beforechildrenrendered',this);}
+var cs=this.childNodes;for(var i=0,len=cs.length;i<len;i++){cs[i].render(true);}
+this.childrenRendered=true;},sort:function(fn,scope){Ext.tree.TreeNode.superclass.sort.apply(this,arguments);if(this.childrenRendered){var cs=this.childNodes;for(var i=0,len=cs.length;i<len;i++){cs[i].render(true);}}},render:function(bulkRender){this.ui.render(bulkRender);if(!this.rendered){this.getOwnerTree().registerNode(this);this.rendered=true;if(this.expanded){this.expanded=false;this.expand(false,false);}}},renderIndent:function(deep,refresh){if(refresh){this.ui.childIndent=null;}
+this.ui.renderIndent();if(deep===true&&this.childrenRendered){var cs=this.childNodes;for(var i=0,len=cs.length;i<len;i++){cs[i].renderIndent(true,refresh);}}},beginUpdate:function(){this.childrenRendered=false;},endUpdate:function(){if(this.expanded&&this.rendered){this.renderChildren();}},destroy:function(silent){if(silent===true){this.unselect(true);}
+Ext.tree.TreeNode.superclass.destroy.call(this,silent);Ext.destroy(this.ui,this.loader);this.ui=this.loader=null;},onIdChange:function(id){this.ui.onIdChange(id);}});Ext.tree.TreePanel.nodeTypes.node=Ext.tree.TreeNode;Ext.tree.AsyncTreeNode=function(config){this.loaded=config&&config.loaded===true;this.loading=false;Ext.tree.AsyncTreeNode.superclass.constructor.apply(this,arguments);this.addEvents('beforeload','load');};Ext.extend(Ext.tree.AsyncTreeNode,Ext.tree.TreeNode,{expand:function(deep,anim,callback,scope){if(this.loading){var timer;var f=function(){if(!this.loading){clearInterval(timer);this.expand(deep,anim,callback,scope);}}.createDelegate(this);timer=setInterval(f,200);return;}
+if(!this.loaded){if(this.fireEvent("beforeload",this)===false){return;}
+this.loading=true;this.ui.beforeLoad(this);var loader=this.loader||this.attributes.loader||this.getOwnerTree().getLoader();if(loader){loader.load(this,this.loadComplete.createDelegate(this,[deep,anim,callback,scope]),this);return;}}
+Ext.tree.AsyncTreeNode.superclass.expand.call(this,deep,anim,callback,scope);},isLoading:function(){return this.loading;},loadComplete:function(deep,anim,callback,scope){this.loading=false;this.loaded=true;this.ui.afterLoad(this);this.fireEvent("load",this);this.expand(deep,anim,callback,scope);},isLoaded:function(){return this.loaded;},hasChildNodes:function(){if(!this.isLeaf()&&!this.loaded){return true;}else{return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);}},reload:function(callback,scope){this.collapse(false,false);while(this.firstChild){this.removeChild(this.firstChild).destroy();}
+this.childrenRendered=false;this.loaded=false;if(this.isHiddenRoot()){this.expanded=false;}
+this.expand(false,false,callback,scope);}});Ext.tree.TreePanel.nodeTypes.async=Ext.tree.AsyncTreeNode;Ext.tree.TreeNodeUI=Ext.extend(Object,{constructor:function(node){Ext.apply(this,{node:node,rendered:false,animating:false,wasLeaf:true,ecc:'x-tree-ec-icon x-tree-elbow',emptyIcon:Ext.BLANK_IMAGE_URL});},removeChild:function(node){if(this.rendered){this.ctNode.removeChild(node.ui.getEl());}},beforeLoad:function(){this.addClass("x-tree-node-loading");},afterLoad:function(){this.removeClass("x-tree-node-loading");},onTextChange:function(node,text,oldText){if(this.rendered){this.textNode.innerHTML=text;}},onIconClsChange:function(node,cls,oldCls){if(this.rendered){Ext.fly(this.iconNode).replaceClass(oldCls,cls);}},onIconChange:function(node,icon){if(this.rendered){var empty=Ext.isEmpty(icon);this.iconNode.src=empty?this.emptyIcon:icon;Ext.fly(this.iconNode)[empty?'removeClass':'addClass']('x-tree-node-inline-icon');}},onTipChange:function(node,tip,title){if(this.rendered){var hasTitle=Ext.isDefined(title);if(this.textNode.setAttributeNS){this.textNode.setAttributeNS("ext","qtip",tip);if(hasTitle){this.textNode.setAttributeNS("ext","qtitle",title);}}else{this.textNode.setAttribute("ext:qtip",tip);if(hasTitle){this.textNode.setAttribute("ext:qtitle",title);}}}},onHrefChange:function(node,href,target){if(this.rendered){this.anchor.href=this.getHref(href);if(Ext.isDefined(target)){this.anchor.target=target;}}},onClsChange:function(node,cls,oldCls){if(this.rendered){Ext.fly(this.elNode).replaceClass(oldCls,cls);}},onDisableChange:function(node,state){this.disabled=state;if(this.checkbox){this.checkbox.disabled=state;}
+this[state?'addClass':'removeClass']('x-tree-node-disabled');},onSelectedChange:function(state){if(state){this.focus();this.addClass("x-tree-selected");}else{this.removeClass("x-tree-selected");}},onMove:function(tree,node,oldParent,newParent,index,refNode){this.childIndent=null;if(this.rendered){var targetNode=newParent.ui.getContainer();if(!targetNode){this.holder=document.createElement("div");this.holder.appendChild(this.wrap);return;}
+var insertBefore=refNode?refNode.ui.getEl():null;if(insertBefore){targetNode.insertBefore(this.wrap,insertBefore);}else{targetNode.appendChild(this.wrap);}
+this.node.renderIndent(true,oldParent!=newParent);}},addClass:function(cls){if(this.elNode){Ext.fly(this.elNode).addClass(cls);}},removeClass:function(cls){if(this.elNode){Ext.fly(this.elNode).removeClass(cls);}},remove:function(){if(this.rendered){this.holder=document.createElement("div");this.holder.appendChild(this.wrap);}},fireEvent:function(){return this.node.fireEvent.apply(this.node,arguments);},initEvents:function(){this.node.on("move",this.onMove,this);if(this.node.disabled){this.onDisableChange(this.node,true);}
+if(this.node.hidden){this.hide();}
+var ot=this.node.getOwnerTree();var dd=ot.enableDD||ot.enableDrag||ot.enableDrop;if(dd&&(!this.node.isRoot||ot.rootVisible)){Ext.dd.Registry.register(this.elNode,{node:this.node,handles:this.getDDHandles(),isHandle:false});}},getDDHandles:function(){return[this.iconNode,this.textNode,this.elNode];},hide:function(){this.node.hidden=true;if(this.wrap){this.wrap.style.display="none";}},show:function(){this.node.hidden=false;if(this.wrap){this.wrap.style.display="";}},onContextMenu:function(e){if(this.node.hasListener("contextmenu")||this.node.getOwnerTree().hasListener("contextmenu")){e.preventDefault();this.focus();this.fireEvent("contextmenu",this.node,e);}},onClick:function(e){if(this.dropping){e.stopEvent();return;}
+if(this.fireEvent("beforeclick",this.node,e)!==false){var a=e.getTarget('a');if(!this.disabled&&this.node.attributes.href&&a){this.fireEvent("click",this.node,e);return;}else if(a&&e.ctrlKey){e.stopEvent();}
+e.preventDefault();if(this.disabled){return;}
+if(this.node.attributes.singleClickExpand&&!this.animating&&this.node.isExpandable()){this.node.toggle();}
+this.fireEvent("click",this.node,e);}else{e.stopEvent();}},onDblClick:function(e){e.preventDefault();if(this.disabled){return;}
+if(this.fireEvent("beforedblclick",this.node,e)!==false){if(this.checkbox){this.toggleCheck();}
+if(!this.animating&&this.node.isExpandable()){this.node.toggle();}
+this.fireEvent("dblclick",this.node,e);}},onOver:function(e){this.addClass('x-tree-node-over');},onOut:function(e){this.removeClass('x-tree-node-over');},onCheckChange:function(){var checked=this.checkbox.checked;this.checkbox.defaultChecked=checked;this.node.attributes.checked=checked;this.fireEvent('checkchange',this.node,checked);},ecClick:function(e){if(!this.animating&&this.node.isExpandable()){this.node.toggle();}},startDrop:function(){this.dropping=true;},endDrop:function(){setTimeout(function(){this.dropping=false;}.createDelegate(this),50);},expand:function(){this.updateExpandIcon();this.ctNode.style.display="";},focus:function(){if(!this.node.preventHScroll){try{this.anchor.focus();}catch(e){}}else{try{var noscroll=this.node.getOwnerTree().getTreeEl().dom;var l=noscroll.scrollLeft;this.anchor.focus();noscroll.scrollLeft=l;}catch(e){}}},toggleCheck:function(value){var cb=this.checkbox;if(cb){cb.checked=(value===undefined?!cb.checked:value);this.onCheckChange();}},blur:function(){try{this.anchor.blur();}catch(e){}},animExpand:function(callback){var ct=Ext.get(this.ctNode);ct.stopFx();if(!this.node.isExpandable()){this.updateExpandIcon();this.ctNode.style.display="";Ext.callback(callback);return;}
+this.animating=true;this.updateExpandIcon();ct.slideIn('t',{callback:function(){this.animating=false;Ext.callback(callback);},scope:this,duration:this.node.ownerTree.duration||.25});},highlight:function(){var tree=this.node.getOwnerTree();Ext.fly(this.wrap).highlight(tree.hlColor||"C3DAF9",{endColor:tree.hlBaseColor});},collapse:function(){this.updateExpandIcon();this.ctNode.style.display="none";},animCollapse:function(callback){var ct=Ext.get(this.ctNode);ct.enableDisplayMode('block');ct.stopFx();this.animating=true;this.updateExpandIcon();ct.slideOut('t',{callback:function(){this.animating=false;Ext.callback(callback);},scope:this,duration:this.node.ownerTree.duration||.25});},getContainer:function(){return this.ctNode;},getEl:function(){return this.wrap;},appendDDGhost:function(ghostNode){ghostNode.appendChild(this.elNode.cloneNode(true));},getDDRepairXY:function(){return Ext.lib.Dom.getXY(this.iconNode);},onRender:function(){this.render();},render:function(bulkRender){var n=this.node,a=n.attributes;var targetNode=n.parentNode?n.parentNode.ui.getContainer():n.ownerTree.innerCt.dom;if(!this.rendered){this.rendered=true;this.renderElements(n,a,targetNode,bulkRender);if(a.qtip){this.onTipChange(n,a.qtip,a.qtipTitle);}else if(a.qtipCfg){a.qtipCfg.target=Ext.id(this.textNode);Ext.QuickTips.register(a.qtipCfg);}
+this.initEvents();if(!this.node.expanded){this.updateExpandIcon(true);}}else{if(bulkRender===true){targetNode.appendChild(this.wrap);}}},renderElements:function(n,a,targetNode,bulkRender){this.indentMarkup=n.parentNode?n.parentNode.ui.getChildIndent():'';var cb=Ext.isBoolean(a.checked),nel,href=this.getHref(a.href),buf=['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ',a.cls,'" unselectable="on">','<span class="x-tree-node-indent">',this.indentMarkup,"</span>",'<img alt="" src="',this.emptyIcon,'" class="x-tree-ec-icon x-tree-elbow" />','<img alt="" src="',a.icon||this.emptyIcon,'" class="x-tree-node-icon',(a.icon?" x-tree-node-inline-icon":""),(a.iconCls?" "+a.iconCls:""),'" unselectable="on" />',cb?('<input class="x-tree-node-cb" type="checkbox" '+(a.checked?'checked="checked" />':'/>')):'','<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',a.hrefTarget?' target="'+a.hrefTarget+'"':"",'><span unselectable="on">',n.text,"</span></a></div>",'<ul class="x-tree-node-ct" style="display:none;"></ul>',"</li>"].join('');if(bulkRender!==true&&n.nextSibling&&(nel=n.nextSibling.ui.getEl())){this.wrap=Ext.DomHelper.insertHtml("beforeBegin",nel,buf);}else{this.wrap=Ext.DomHelper.insertHtml("beforeEnd",targetNode,buf);}
+this.elNode=this.wrap.childNodes[0];this.ctNode=this.wrap.childNodes[1];var cs=this.elNode.childNodes;this.indentNode=cs[0];this.ecNode=cs[1];this.iconNode=cs[2];var index=3;if(cb){this.checkbox=cs[3];this.checkbox.defaultChecked=this.checkbox.checked;index++;}
+this.anchor=cs[index];this.textNode=cs[index].firstChild;},getHref:function(href){return Ext.isEmpty(href)?(Ext.isGecko?'':'#'):href;},getAnchor:function(){return this.anchor;},getTextEl:function(){return this.textNode;},getIconEl:function(){return this.iconNode;},isChecked:function(){return this.checkbox?this.checkbox.checked:false;},updateExpandIcon:function(){if(this.rendered){var n=this.node,c1,c2,cls=n.isLast()?"x-tree-elbow-end":"x-tree-elbow",hasChild=n.hasChildNodes();if(hasChild||n.attributes.expandable){if(n.expanded){cls+="-minus";c1="x-tree-node-collapsed";c2="x-tree-node-expanded";}else{cls+="-plus";c1="x-tree-node-expanded";c2="x-tree-node-collapsed";}
+if(this.wasLeaf){this.removeClass("x-tree-node-leaf");this.wasLeaf=false;}
+if(this.c1!=c1||this.c2!=c2){Ext.fly(this.elNode).replaceClass(c1,c2);this.c1=c1;this.c2=c2;}}else{if(!this.wasLeaf){Ext.fly(this.elNode).replaceClass("x-tree-node-expanded","x-tree-node-collapsed");delete this.c1;delete this.c2;this.wasLeaf=true;}}
+var ecc="x-tree-ec-icon "+cls;if(this.ecc!=ecc){this.ecNode.className=ecc;this.ecc=ecc;}}},onIdChange:function(id){if(this.rendered){this.elNode.setAttribute('ext:tree-node-id',id);}},getChildIndent:function(){if(!this.childIndent){var buf=[],p=this.node;while(p){if(!p.isRoot||(p.isRoot&&p.ownerTree.rootVisible)){if(!p.isLast()){buf.unshift('<img alt="" src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');}else{buf.unshift('<img alt="" src="'+this.emptyIcon+'" class="x-tree-icon" />');}}
+p=p.parentNode;}
+this.childIndent=buf.join("");}
+return this.childIndent;},renderIndent:function(){if(this.rendered){var indent="",p=this.node.parentNode;if(p){indent=p.ui.getChildIndent();}
+if(this.indentMarkup!=indent){this.indentNode.innerHTML=indent;this.indentMarkup=indent;}
+this.updateExpandIcon();}},destroy:function(){if(this.elNode){Ext.dd.Registry.unregister(this.elNode.id);}
+Ext.each(['textnode','anchor','checkbox','indentNode','ecNode','iconNode','elNode','ctNode','wrap','holder'],function(el){if(this[el]){Ext.fly(this[el]).remove();delete this[el];}},this);delete this.node;}});Ext.tree.RootTreeNodeUI=Ext.extend(Ext.tree.TreeNodeUI,{render:function(){if(!this.rendered){var targetNode=this.node.ownerTree.innerCt.dom;this.node.expanded=true;targetNode.innerHTML='<div class="x-tree-root-node"></div>';this.wrap=this.ctNode=targetNode.firstChild;}},collapse:Ext.emptyFn,expand:Ext.emptyFn});Ext.tree.TreeLoader=function(config){this.baseParams={};Ext.apply(this,config);this.addEvents("beforeload","load","loadexception");Ext.tree.TreeLoader.superclass.constructor.call(this);if(Ext.isString(this.paramOrder)){this.paramOrder=this.paramOrder.split(/[\s,|]/);}};Ext.extend(Ext.tree.TreeLoader,Ext.util.Observable,{uiProviders:{},clearOnLoad:true,paramOrder:undefined,paramsAsHash:false,nodeParameter:'node',directFn:undefined,load:function(node,callback,scope){if(this.clearOnLoad){while(node.firstChild){node.removeChild(node.firstChild);}}
+if(this.doPreload(node)){this.runCallback(callback,scope||node,[node]);}else if(this.directFn||this.dataUrl||this.url){this.requestData(node,callback,scope||node);}},doPreload:function(node){if(node.attributes.children){if(node.childNodes.length<1){var cs=node.attributes.children;node.beginUpdate();for(var i=0,len=cs.length;i<len;i++){var cn=node.appendChild(this.createNode(cs[i]));if(this.preloadChildren){this.doPreload(cn);}}
+node.endUpdate();}
+return true;}
+return false;},getParams:function(node){var bp=Ext.apply({},this.baseParams),np=this.nodeParameter,po=this.paramOrder;np&&(bp[np]=node.id);if(this.directFn){var buf=[node.id];if(po){if(np&&po.indexOf(np)>-1){buf=[];}
+for(var i=0,len=po.length;i<len;i++){buf.push(bp[po[i]]);}}else if(this.paramsAsHash){buf=[bp];}
+return buf;}else{return bp;}},requestData:function(node,callback,scope){if(this.fireEvent("beforeload",this,node,callback)!==false){if(this.directFn){var args=this.getParams(node);args.push(this.processDirectResponse.createDelegate(this,[{callback:callback,node:node,scope:scope}],true));this.directFn.apply(window,args);}else{this.transId=Ext.Ajax.request({method:this.requestMethod,url:this.dataUrl||this.url,success:this.handleResponse,failure:this.handleFailure,scope:this,argument:{callback:callback,node:node,scope:scope},params:this.getParams(node)});}}else{this.runCallback(callback,scope||node,[]);}},processDirectResponse:function(result,response,args){if(response.status){this.handleResponse({responseData:Ext.isArray(result)?result:null,responseText:result,argument:args});}else{this.handleFailure({argument:args});}},runCallback:function(cb,scope,args){if(Ext.isFunction(cb)){cb.apply(scope,args);}},isLoading:function(){return!!this.transId;},abort:function(){if(this.isLoading()){Ext.Ajax.abort(this.transId);}},createNode:function(attr){if(this.baseAttrs){Ext.applyIf(attr,this.baseAttrs);}
+if(this.applyLoader!==false&&!attr.loader){attr.loader=this;}
+if(Ext.isString(attr.uiProvider)){attr.uiProvider=this.uiProviders[attr.uiProvider]||eval(attr.uiProvider);}
+if(attr.nodeType){return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);}else{return attr.leaf?new Ext.tree.TreeNode(attr):new Ext.tree.AsyncTreeNode(attr);}},processResponse:function(response,node,callback,scope){var json=response.responseText;try{var o=response.responseData||Ext.decode(json);node.beginUpdate();for(var i=0,len=o.length;i<len;i++){var n=this.createNode(o[i]);if(n){node.appendChild(n);}}
+node.endUpdate();this.runCallback(callback,scope||node,[node]);}catch(e){this.handleFailure(response);}},handleResponse:function(response){this.transId=false;var a=response.argument;this.processResponse(response,a.node,a.callback,a.scope);this.fireEvent("load",this,a.node,response);},handleFailure:function(response){this.transId=false;var a=response.argument;this.fireEvent("loadexception",this,a.node,response);this.runCallback(a.callback,a.scope||a.node,[a.node]);},destroy:function(){this.abort();this.purgeListeners();}});Ext.tree.TreeFilter=function(tree,config){this.tree=tree;this.filtered={};Ext.apply(this,config);};Ext.tree.TreeFilter.prototype={clearBlank:false,reverse:false,autoClear:false,remove:false,filter:function(value,attr,startNode){attr=attr||"text";var f;if(typeof value=="string"){var vlen=value.length;if(vlen==0&&this.clearBlank){this.clear();return;}
+value=value.toLowerCase();f=function(n){return n.attributes[attr].substr(0,vlen).toLowerCase()==value;};}else if(value.exec){f=function(n){return value.test(n.attributes[attr]);};}else{throw'Illegal filter type, must be string or regex';}
+this.filterBy(f,null,startNode);},filterBy:function(fn,scope,startNode){startNode=startNode||this.tree.root;if(this.autoClear){this.clear();}
+var af=this.filtered,rv=this.reverse;var f=function(n){if(n==startNode){return true;}
+if(af[n.id]){return false;}
+var m=fn.call(scope||n,n);if(!m||rv){af[n.id]=n;n.ui.hide();return false;}
+return true;};startNode.cascade(f);if(this.remove){for(var id in af){if(typeof id!="function"){var n=af[id];if(n&&n.parentNode){n.parentNode.removeChild(n);}}}}},clear:function(){var t=this.tree;var af=this.filtered;for(var id in af){if(typeof id!="function"){var n=af[id];if(n){n.ui.show();}}}
+this.filtered={};}};Ext.tree.TreeSorter=Ext.extend(Object,{constructor:function(tree,config){Ext.apply(this,config);tree.on({scope:this,beforechildrenrendered:this.doSort,append:this.updateSort,insert:this.updateSort,textchange:this.updateSortParent});var desc=this.dir&&this.dir.toLowerCase()=='desc',prop=this.property||'text';sortType=this.sortType;folderSort=this.folderSort;caseSensitive=this.caseSensitive===true;leafAttr=this.leafAttr||'leaf';if(Ext.isString(sortType)){sortType=Ext.data.SortTypes[sortType];}
+this.sortFn=function(n1,n2){var attr1=n1.attributes,attr2=n2.attributes;if(folderSort){if(attr1[leafAttr]&&!attr2[leafAttr]){return 1;}
+if(!attr1[leafAttr]&&attr2[leafAttr]){return-1;}}
+var prop1=attr1[prop],prop2=attr2[prop],v1=sortType?sortType(prop1):(caseSensitive?prop1:prop1.toUpperCase());v2=sortType?sortType(prop2):(caseSensitive?prop2:prop2.toUpperCase());if(v1<v2){return desc?1:-1;}else if(v1>v2){return desc?-1:1;}
+return 0;};},doSort:function(node){node.sort(this.sortFn);},updateSort:function(tree,node){if(node.childrenRendered){this.doSort.defer(1,this,[node]);}},updateSortParent:function(node){var p=node.parentNode;if(p&&p.childrenRendered){this.doSort.defer(1,this,[p]);}}});if(Ext.dd.DropZone){Ext.tree.TreeDropZone=function(tree,config){this.allowParentInsert=config.allowParentInsert||false;this.allowContainerDrop=config.allowContainerDrop||false;this.appendOnly=config.appendOnly||false;Ext.tree.TreeDropZone.superclass.constructor.call(this,tree.getTreeEl(),config);this.tree=tree;this.dragOverData={};this.lastInsertClass="x-tree-no-status";};Ext.extend(Ext.tree.TreeDropZone,Ext.dd.DropZone,{ddGroup:"TreeDD",expandDelay:1000,expandNode:function(node){if(node.hasChildNodes()&&!node.isExpanded()){node.expand(false,null,this.triggerCacheRefresh.createDelegate(this));}},queueExpand:function(node){this.expandProcId=this.expandNode.defer(this.expandDelay,this,[node]);},cancelExpand:function(){if(this.expandProcId){clearTimeout(this.expandProcId);this.expandProcId=false;}},isValidDropPoint:function(n,pt,dd,e,data){if(!n||!data){return false;}
+var targetNode=n.node;var dropNode=data.node;if(!(targetNode&&targetNode.isTarget&&pt)){return false;}
+if(pt=="append"&&targetNode.allowChildren===false){return false;}
+if((pt=="above"||pt=="below")&&(targetNode.parentNode&&targetNode.parentNode.allowChildren===false)){return false;}
+if(dropNode&&(targetNode==dropNode||dropNode.contains(targetNode))){return false;}
+var overEvent=this.dragOverData;overEvent.tree=this.tree;overEvent.target=targetNode;overEvent.data=data;overEvent.point=pt;overEvent.source=dd;overEvent.rawEvent=e;overEvent.dropNode=dropNode;overEvent.cancel=false;var result=this.tree.fireEvent("nodedragover",overEvent);return overEvent.cancel===false&&result!==false;},getDropPoint:function(e,n,dd){var tn=n.node;if(tn.isRoot){return tn.allowChildren!==false?"append":false;}
+var dragEl=n.ddel;var t=Ext.lib.Dom.getY(dragEl),b=t+dragEl.offsetHeight;var y=Ext.lib.Event.getPageY(e);var noAppend=tn.allowChildren===false||tn.isLeaf();if(this.appendOnly||tn.parentNode.allowChildren===false){return noAppend?false:"append";}
+var noBelow=false;if(!this.allowParentInsert){noBelow=tn.hasChildNodes()&&tn.isExpanded();}
+var q=(b-t)/(noAppend?2:3);if(y>=t&&y<(t+q)){return"above";}else if(!noBelow&&(noAppend||y>=b-q&&y<=b)){return"below";}else{return"append";}},onNodeEnter:function(n,dd,e,data){this.cancelExpand();},onContainerOver:function(dd,e,data){if(this.allowContainerDrop&&this.isValidDropPoint({ddel:this.tree.getRootNode().ui.elNode,node:this.tree.getRootNode()},"append",dd,e,data)){return this.dropAllowed;}
+return this.dropNotAllowed;},onNodeOver:function(n,dd,e,data){var pt=this.getDropPoint(e,n,dd);var node=n.node;if(!this.expandProcId&&pt=="append"&&node.hasChildNodes()&&!n.node.isExpanded()){this.queueExpand(node);}else if(pt!="append"){this.cancelExpand();}
+var returnCls=this.dropNotAllowed;if(this.isValidDropPoint(n,pt,dd,e,data)){if(pt){var el=n.ddel;var cls;if(pt=="above"){returnCls=n.node.isFirst()?"x-tree-drop-ok-above":"x-tree-drop-ok-between";cls="x-tree-drag-insert-above";}else if(pt=="below"){returnCls=n.node.isLast()?"x-tree-drop-ok-below":"x-tree-drop-ok-between";cls="x-tree-drag-insert-below";}else{returnCls="x-tree-drop-ok-append";cls="x-tree-drag-append";}
+if(this.lastInsertClass!=cls){Ext.fly(el).replaceClass(this.lastInsertClass,cls);this.lastInsertClass=cls;}}}
+return returnCls;},onNodeOut:function(n,dd,e,data){this.cancelExpand();this.removeDropIndicators(n);},onNodeDrop:function(n,dd,e,data){var point=this.getDropPoint(e,n,dd);var targetNode=n.node;targetNode.ui.startDrop();if(!this.isValidDropPoint(n,point,dd,e,data)){targetNode.ui.endDrop();return false;}
+var dropNode=data.node||(dd.getTreeNode?dd.getTreeNode(data,targetNode,point,e):null);return this.processDrop(targetNode,data,point,dd,e,dropNode);},onContainerDrop:function(dd,e,data){if(this.allowContainerDrop&&this.isValidDropPoint({ddel:this.tree.getRootNode().ui.elNode,node:this.tree.getRootNode()},"append",dd,e,data)){var targetNode=this.tree.getRootNode();targetNode.ui.startDrop();var dropNode=data.node||(dd.getTreeNode?dd.getTreeNode(data,targetNode,'append',e):null);return this.processDrop(targetNode,data,'append',dd,e,dropNode);}
+return false;},processDrop:function(target,data,point,dd,e,dropNode){var dropEvent={tree:this.tree,target:target,data:data,point:point,source:dd,rawEvent:e,dropNode:dropNode,cancel:!dropNode,dropStatus:false};var retval=this.tree.fireEvent("beforenodedrop",dropEvent);if(retval===false||dropEvent.cancel===true||!dropEvent.dropNode){target.ui.endDrop();return dropEvent.dropStatus;}
+target=dropEvent.target;if(point=='append'&&!target.isExpanded()){target.expand(false,null,function(){this.completeDrop(dropEvent);}.createDelegate(this));}else{this.completeDrop(dropEvent);}
+return true;},completeDrop:function(de){var ns=de.dropNode,p=de.point,t=de.target;if(!Ext.isArray(ns)){ns=[ns];}
+var n;for(var i=0,len=ns.length;i<len;i++){n=ns[i];if(p=="above"){t.parentNode.insertBefore(n,t);}else if(p=="below"){t.parentNode.insertBefore(n,t.nextSibling);}else{t.appendChild(n);}}
+n.ui.focus();if(Ext.enableFx&&this.tree.hlDrop){n.ui.highlight();}
+t.ui.endDrop();this.tree.fireEvent("nodedrop",de);},afterNodeMoved:function(dd,data,e,targetNode,dropNode){if(Ext.enableFx&&this.tree.hlDrop){dropNode.ui.focus();dropNode.ui.highlight();}
+this.tree.fireEvent("nodedrop",this.tree,targetNode,data,dd,e);},getTree:function(){return this.tree;},removeDropIndicators:function(n){if(n&&n.ddel){var el=n.ddel;Ext.fly(el).removeClass(["x-tree-drag-insert-above","x-tree-drag-insert-below","x-tree-drag-append"]);this.lastInsertClass="_noclass";}},beforeDragDrop:function(target,e,id){this.cancelExpand();return true;},afterRepair:function(data){if(data&&Ext.enableFx){data.node.ui.highlight();}
+this.hideProxy();}});}
+if(Ext.dd.DragZone){Ext.tree.TreeDragZone=function(tree,config){Ext.tree.TreeDragZone.superclass.constructor.call(this,tree.innerCt,config);this.tree=tree;};Ext.extend(Ext.tree.TreeDragZone,Ext.dd.DragZone,{ddGroup:"TreeDD",onBeforeDrag:function(data,e){var n=data.node;return n&&n.draggable&&!n.disabled;},onInitDrag:function(e){var data=this.dragData;this.tree.getSelectionModel().select(data.node);this.tree.eventModel.disable();this.proxy.update("");data.node.ui.appendDDGhost(this.proxy.ghost.dom);this.tree.fireEvent("startdrag",this.tree,data.node,e);},getRepairXY:function(e,data){return data.node.ui.getDDRepairXY();},onEndDrag:function(data,e){this.tree.eventModel.enable.defer(100,this.tree.eventModel);this.tree.fireEvent("enddrag",this.tree,data.node,e);},onValidDrop:function(dd,e,id){this.tree.fireEvent("dragdrop",this.tree,this.dragData.node,dd,e);this.hideProxy();},beforeInvalidDrop:function(e,id){var sm=this.tree.getSelectionModel();sm.clearSelections();sm.select(this.dragData.node);},afterRepair:function(){if(Ext.enableFx&&this.tree.hlDrop){Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor||"c3daf9");}
+this.dragging=false;}});}
+Ext.tree.TreeEditor=function(tree,fc,config){fc=fc||{};var field=fc.events?fc:new Ext.form.TextField(fc);Ext.tree.TreeEditor.superclass.constructor.call(this,field,config);this.tree=tree;if(!tree.rendered){tree.on('render',this.initEditor,this);}else{this.initEditor(tree);}};Ext.extend(Ext.tree.TreeEditor,Ext.Editor,{alignment:"l-l",autoSize:false,hideEl:false,cls:"x-small-editor x-tree-editor",shim:false,shadow:"frame",maxWidth:250,editDelay:350,initEditor:function(tree){tree.on({scope:this,beforeclick:this.beforeNodeClick,dblclick:this.onNodeDblClick});this.on({scope:this,complete:this.updateNode,beforestartedit:this.fitToTree,specialkey:this.onSpecialKey});this.on('startedit',this.bindScroll,this,{delay:10});},fitToTree:function(ed,el){var td=this.tree.getTreeEl().dom,nd=el.dom;if(td.scrollLeft>nd.offsetLeft){td.scrollLeft=nd.offsetLeft;}
+var w=Math.min(this.maxWidth,(td.clientWidth>20?td.clientWidth:td.offsetWidth)-Math.max(0,nd.offsetLeft-td.scrollLeft)-5);this.setSize(w,'');},triggerEdit:function(node,defer){this.completeEdit();if(node.attributes.editable!==false){this.editNode=node;if(this.tree.autoScroll){Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);}
+var value=node.text||'';if(!Ext.isGecko&&Ext.isEmpty(node.text)){node.setText('&#160;');}
+this.autoEditTimer=this.startEdit.defer(this.editDelay,this,[node.ui.textNode,value]);return false;}},bindScroll:function(){this.tree.getTreeEl().on('scroll',this.cancelEdit,this);},beforeNodeClick:function(node,e){clearTimeout(this.autoEditTimer);if(this.tree.getSelectionModel().isSelected(node)){e.stopEvent();return this.triggerEdit(node);}},onNodeDblClick:function(node,e){clearTimeout(this.autoEditTimer);},updateNode:function(ed,value){this.tree.getTreeEl().un('scroll',this.cancelEdit,this);this.editNode.setText(value);},onHide:function(){Ext.tree.TreeEditor.superclass.onHide.call(this);if(this.editNode){this.editNode.ui.focus.defer(50,this.editNode.ui);}},onSpecialKey:function(field,e){var k=e.getKey();if(k==e.ESC){e.stopEvent();this.cancelEdit();}else if(k==e.ENTER&&!e.hasModifier()){e.stopEvent();this.completeEdit();}},onDestroy:function(){clearTimeout(this.autoEditTimer);Ext.tree.TreeEditor.superclass.onDestroy.call(this);var tree=this.tree;tree.un('beforeclick',this.beforeNodeClick,this);tree.un('dblclick',this.onNodeDblClick,this);}});Ext.Window=Ext.extend(Ext.Panel,{baseCls:'x-window',resizable:true,draggable:true,closable:true,closeAction:'close',constrain:false,constrainHeader:false,plain:false,minimizable:false,maximizable:false,minHeight:100,minWidth:200,expandOnShow:true,showAnimDuration:0.25,hideAnimDuration:0.25,collapsible:false,initHidden:undefined,hidden:true,elements:'header,body',frame:true,floating:true,initComponent:function(){this.initTools();Ext.Window.superclass.initComponent.call(this);this.addEvents('resize','maximize','minimize','restore');if(Ext.isDefined(this.initHidden)){this.hidden=this.initHidden;}
+if(this.hidden===false){this.hidden=true;this.show();}},getState:function(){return Ext.apply(Ext.Window.superclass.getState.call(this)||{},this.getBox(true));},onRender:function(ct,position){Ext.Window.superclass.onRender.call(this,ct,position);if(this.plain){this.el.addClass('x-window-plain');}
+this.focusEl=this.el.createChild({tag:'a',href:'#',cls:'x-dlg-focus',tabIndex:'-1',html:'&#160;'});this.focusEl.swallowEvent('click',true);this.proxy=this.el.createProxy('x-window-proxy');this.proxy.enableDisplayMode('block');if(this.modal){this.mask=this.container.createChild({cls:'ext-el-mask'},this.el.dom);this.mask.enableDisplayMode('block');this.mask.hide();this.mon(this.mask,'click',this.focus,this);}
+if(this.maximizable){this.mon(this.header,'dblclick',this.toggleMaximize,this);}},initEvents:function(){Ext.Window.superclass.initEvents.call(this);if(this.animateTarget){this.setAnimateTarget(this.animateTarget);}
+if(this.resizable){this.resizer=new Ext.Resizable(this.el,{minWidth:this.minWidth,minHeight:this.minHeight,handles:this.resizeHandles||'all',pinned:true,resizeElement:this.resizerAction,handleCls:'x-window-handle'});this.resizer.window=this;this.mon(this.resizer,'beforeresize',this.beforeResize,this);}
+if(this.draggable){this.header.addClass('x-window-draggable');}
+this.mon(this.el,'mousedown',this.toFront,this);this.manager=this.manager||Ext.WindowMgr;this.manager.register(this);if(this.maximized){this.maximized=false;this.maximize();}
+if(this.closable){var km=this.getKeyMap();km.on(27,this.onEsc,this);km.disable();}},initDraggable:function(){this.dd=new Ext.Window.DD(this);},onEsc:function(k,e){e.stopEvent();this[this.closeAction]();},beforeDestroy:function(){if(this.rendered){this.hide();this.clearAnchor();Ext.destroy(this.focusEl,this.resizer,this.dd,this.proxy,this.mask);}
+Ext.Window.superclass.beforeDestroy.call(this);},onDestroy:function(){if(this.manager){this.manager.unregister(this);}
+Ext.Window.superclass.onDestroy.call(this);},initTools:function(){if(this.minimizable){this.addTool({id:'minimize',handler:this.minimize.createDelegate(this,[])});}
+if(this.maximizable){this.addTool({id:'maximize',handler:this.maximize.createDelegate(this,[])});this.addTool({id:'restore',handler:this.restore.createDelegate(this,[]),hidden:true});}
+if(this.closable){this.addTool({id:'close',handler:this[this.closeAction].createDelegate(this,[])});}},resizerAction:function(){var box=this.proxy.getBox();this.proxy.hide();this.window.handleResize(box);return box;},beforeResize:function(){this.resizer.minHeight=Math.max(this.minHeight,this.getFrameHeight()+40);this.resizer.minWidth=Math.max(this.minWidth,this.getFrameWidth()+40);this.resizeBox=this.el.getBox();},updateHandles:function(){if(Ext.isIE&&this.resizer){this.resizer.syncHandleHeight();this.el.repaint();}},handleResize:function(box){var rz=this.resizeBox;if(rz.x!=box.x||rz.y!=box.y){this.updateBox(box);}else{this.setSize(box);if(Ext.isIE6&&Ext.isStrict){this.doLayout();}}
+this.focus();this.updateHandles();this.saveState();},focus:function(){var f=this.focusEl,db=this.defaultButton,t=typeof db,el,ct;if(Ext.isDefined(db)){if(Ext.isNumber(db)&&this.fbar){f=this.fbar.items.get(db);}else if(Ext.isString(db)){f=Ext.getCmp(db);}else{f=db;}
+el=f.getEl();ct=Ext.getDom(this.container);if(el&&ct){if(ct!=document.body&&!Ext.lib.Region.getRegion(ct).contains(Ext.lib.Region.getRegion(el.dom))){return;}}}
+f=f||this.focusEl;f.focus.defer(10,f);},setAnimateTarget:function(el){el=Ext.get(el);this.animateTarget=el;},beforeShow:function(){delete this.el.lastXY;delete this.el.lastLT;if(this.x===undefined||this.y===undefined){var xy=this.el.getAlignToXY(this.container,'c-c');var pos=this.el.translatePoints(xy[0],xy[1]);this.x=this.x===undefined?pos.left:this.x;this.y=this.y===undefined?pos.top:this.y;}
+this.el.setLeftTop(this.x,this.y);if(this.expandOnShow){this.expand(false);}
+if(this.modal){Ext.getBody().addClass('x-body-masked');this.mask.setSize(Ext.lib.Dom.getViewWidth(true),Ext.lib.Dom.getViewHeight(true));this.mask.show();}},show:function(animateTarget,cb,scope){if(!this.rendered){this.render(Ext.getBody());}
+if(this.hidden===false){this.toFront();return this;}
+if(this.fireEvent('beforeshow',this)===false){return this;}
+if(cb){this.on('show',cb,scope,{single:true});}
+this.hidden=false;if(Ext.isDefined(animateTarget)){this.setAnimateTarget(animateTarget);}
+this.beforeShow();if(this.animateTarget){this.animShow();}else{this.afterShow();}
+return this;},afterShow:function(isAnim){if(this.isDestroyed){return false;}
+this.proxy.hide();this.el.setStyle('display','block');this.el.show();if(this.maximized){this.fitContainer();}
+if(Ext.isMac&&Ext.isGecko2){this.cascade(this.setAutoScroll);}
+if(this.monitorResize||this.modal||this.constrain||this.constrainHeader){Ext.EventManager.onWindowResize(this.onWindowResize,this);}
+this.doConstrain();this.doLayout();if(this.keyMap){this.keyMap.enable();}
+this.toFront();this.updateHandles();if(isAnim&&(Ext.isIE||Ext.isWebKit)){var sz=this.getSize();this.onResize(sz.width,sz.height);}
+this.onShow();this.fireEvent('show',this);},animShow:function(){this.proxy.show();this.proxy.setBox(this.animateTarget.getBox());this.proxy.setOpacity(0);var b=this.getBox();this.el.setStyle('display','none');this.proxy.shift(Ext.apply(b,{callback:this.afterShow.createDelegate(this,[true],false),scope:this,easing:'easeNone',duration:this.showAnimDuration,opacity:0.5}));},hide:function(animateTarget,cb,scope){if(this.hidden||this.fireEvent('beforehide',this)===false){return this;}
+if(cb){this.on('hide',cb,scope,{single:true});}
+this.hidden=true;if(animateTarget!==undefined){this.setAnimateTarget(animateTarget);}
+if(this.modal){this.mask.hide();Ext.getBody().removeClass('x-body-masked');}
+if(this.animateTarget){this.animHide();}else{this.el.hide();this.afterHide();}
+return this;},afterHide:function(){this.proxy.hide();if(this.monitorResize||this.modal||this.constrain||this.constrainHeader){Ext.EventManager.removeResizeListener(this.onWindowResize,this);}
+if(this.keyMap){this.keyMap.disable();}
+this.onHide();this.fireEvent('hide',this);},animHide:function(){this.proxy.setOpacity(0.5);this.proxy.show();var tb=this.getBox(false);this.proxy.setBox(tb);this.el.hide();this.proxy.shift(Ext.apply(this.animateTarget.getBox(),{callback:this.afterHide,scope:this,duration:this.hideAnimDuration,easing:'easeNone',opacity:0}));},onShow:Ext.emptyFn,onHide:Ext.emptyFn,onWindowResize:function(){if(this.maximized){this.fitContainer();}
+if(this.modal){this.mask.setSize('100%','100%');var force=this.mask.dom.offsetHeight;this.mask.setSize(Ext.lib.Dom.getViewWidth(true),Ext.lib.Dom.getViewHeight(true));}
+this.doConstrain();},doConstrain:function(){if(this.constrain||this.constrainHeader){var offsets;if(this.constrain){offsets={right:this.el.shadowOffset,left:this.el.shadowOffset,bottom:this.el.shadowOffset};}else{var s=this.getSize();offsets={right:-(s.width-100),bottom:-(s.height-25)};}
+var xy=this.el.getConstrainToXY(this.container,true,offsets);if(xy){this.setPosition(xy[0],xy[1]);}}},ghost:function(cls){var ghost=this.createGhost(cls);var box=this.getBox(true);ghost.setLeftTop(box.x,box.y);ghost.setWidth(box.width);this.el.hide();this.activeGhost=ghost;return ghost;},unghost:function(show,matchPosition){if(!this.activeGhost){return;}
+if(show!==false){this.el.show();this.focus.defer(10,this);if(Ext.isMac&&Ext.isGecko2){this.cascade(this.setAutoScroll);}}
+if(matchPosition!==false){this.setPosition(this.activeGhost.getLeft(true),this.activeGhost.getTop(true));}
+this.activeGhost.hide();this.activeGhost.remove();delete this.activeGhost;},minimize:function(){this.fireEvent('minimize',this);return this;},close:function(){if(this.fireEvent('beforeclose',this)!==false){if(this.hidden){this.doClose();}else{this.hide(null,this.doClose,this);}}},doClose:function(){this.fireEvent('close',this);this.destroy();},maximize:function(){if(!this.maximized){this.expand(false);this.restoreSize=this.getSize();this.restorePos=this.getPosition(true);if(this.maximizable){this.tools.maximize.hide();this.tools.restore.show();}
+this.maximized=true;this.el.disableShadow();if(this.dd){this.dd.lock();}
+if(this.collapsible){this.tools.toggle.hide();}
+this.el.addClass('x-window-maximized');this.container.addClass('x-window-maximized-ct');this.setPosition(0,0);this.fitContainer();this.fireEvent('maximize',this);}
+return this;},restore:function(){if(this.maximized){var t=this.tools;this.el.removeClass('x-window-maximized');if(t.restore){t.restore.hide();}
+if(t.maximize){t.maximize.show();}
+this.setPosition(this.restorePos[0],this.restorePos[1]);this.setSize(this.restoreSize.width,this.restoreSize.height);delete this.restorePos;delete this.restoreSize;this.maximized=false;this.el.enableShadow(true);if(this.dd){this.dd.unlock();}
+if(this.collapsible&&t.toggle){t.toggle.show();}
+this.container.removeClass('x-window-maximized-ct');this.doConstrain();this.fireEvent('restore',this);}
+return this;},toggleMaximize:function(){return this[this.maximized?'restore':'maximize']();},fitContainer:function(){var vs=this.container.getViewSize(false);this.setSize(vs.width,vs.height);},setZIndex:function(index){if(this.modal){this.mask.setStyle('z-index',index);}
+this.el.setZIndex(++index);index+=5;if(this.resizer){this.resizer.proxy.setStyle('z-index',++index);}
+this.lastZIndex=index;},alignTo:function(element,position,offsets){var xy=this.el.getAlignToXY(element,position,offsets);this.setPagePosition(xy[0],xy[1]);return this;},anchorTo:function(el,alignment,offsets,monitorScroll){this.clearAnchor();this.anchorTarget={el:el,alignment:alignment,offsets:offsets};Ext.EventManager.onWindowResize(this.doAnchor,this);var tm=typeof monitorScroll;if(tm!='undefined'){Ext.EventManager.on(window,'scroll',this.doAnchor,this,{buffer:tm=='number'?monitorScroll:50});}
+return this.doAnchor();},doAnchor:function(){var o=this.anchorTarget;this.alignTo(o.el,o.alignment,o.offsets);return this;},clearAnchor:function(){if(this.anchorTarget){Ext.EventManager.removeResizeListener(this.doAnchor,this);Ext.EventManager.un(window,'scroll',this.doAnchor,this);delete this.anchorTarget;}
+return this;},toFront:function(e){if(this.manager.bringToFront(this)){if(!e||!e.getTarget().focus){this.focus();}}
+return this;},setActive:function(active){if(active){if(!this.maximized){this.el.enableShadow(true);}
+this.fireEvent('activate',this);}else{this.el.disableShadow();this.fireEvent('deactivate',this);}},toBack:function(){this.manager.sendToBack(this);return this;},center:function(){var xy=this.el.getAlignToXY(this.container,'c-c');this.setPagePosition(xy[0],xy[1]);return this;}});Ext.reg('window',Ext.Window);Ext.Window.DD=Ext.extend(Ext.dd.DD,{constructor:function(win){this.win=win;Ext.Window.DD.superclass.constructor.call(this,win.el.id,'WindowDD-'+win.id);this.setHandleElId(win.header.id);this.scroll=false;},moveOnly:true,headerOffsets:[100,25],startDrag:function(){var w=this.win;this.proxy=w.ghost(w.initialConfig.cls);if(w.constrain!==false){var so=w.el.shadowOffset;this.constrainTo(w.container,{right:so,left:so,bottom:so});}else if(w.constrainHeader!==false){var s=this.proxy.getSize();this.constrainTo(w.container,{right:-(s.width-this.headerOffsets[0]),bottom:-(s.height-this.headerOffsets[1])});}},b4Drag:Ext.emptyFn,onDrag:function(e){this.alignElWithMouse(this.proxy,e.getPageX(),e.getPageY());},endDrag:function(e){this.win.unghost();this.win.saveState();}});Ext.WindowGroup=function(){var list={};var accessList=[];var front=null;var sortWindows=function(d1,d2){return(!d1._lastAccess||d1._lastAccess<d2._lastAccess)?-1:1;};var orderWindows=function(){var a=accessList,len=a.length;if(len>0){a.sort(sortWindows);var seed=a[0].manager.zseed;for(var i=0;i<len;i++){var win=a[i];if(win&&!win.hidden){win.setZIndex(seed+(i*10));}}}
+activateLast();};var setActiveWin=function(win){if(win!=front){if(front){front.setActive(false);}
+front=win;if(win){win.setActive(true);}}};var activateLast=function(){for(var i=accessList.length-1;i>=0;--i){if(!accessList[i].hidden){setActiveWin(accessList[i]);return;}}
+setActiveWin(null);};return{zseed:9000,register:function(win){if(win.manager){win.manager.unregister(win);}
+win.manager=this;list[win.id]=win;accessList.push(win);win.on('hide',activateLast);},unregister:function(win){delete win.manager;delete list[win.id];win.un('hide',activateLast);accessList.remove(win);},get:function(id){return typeof id=="object"?id:list[id];},bringToFront:function(win){win=this.get(win);if(win!=front){win._lastAccess=new Date().getTime();orderWindows();return true;}
+return false;},sendToBack:function(win){win=this.get(win);win._lastAccess=-(new Date().getTime());orderWindows();return win;},hideAll:function(){for(var id in list){if(list[id]&&typeof list[id]!="function"&&list[id].isVisible()){list[id].hide();}}},getActive:function(){return front;},getBy:function(fn,scope){var r=[];for(var i=accessList.length-1;i>=0;--i){var win=accessList[i];if(fn.call(scope||win,win)!==false){r.push(win);}}
+return r;},each:function(fn,scope){for(var id in list){if(list[id]&&typeof list[id]!="function"){if(fn.call(scope||list[id],list[id])===false){return;}}}}};};Ext.WindowMgr=new Ext.WindowGroup();Ext.MessageBox=function(){var dlg,opt,mask,waitTimer,bodyEl,msgEl,textboxEl,textareaEl,progressBar,pp,iconEl,spacerEl,buttons,activeTextEl,bwidth,bufferIcon='',iconCls='',buttonNames=['ok','yes','no','cancel'];var handleButton=function(button){buttons[button].blur();if(dlg.isVisible()){dlg.hide();handleHide();Ext.callback(opt.fn,opt.scope||window,[button,activeTextEl.dom.value,opt],1);}};var handleHide=function(){if(opt&&opt.cls){dlg.el.removeClass(opt.cls);}
+progressBar.reset();};var handleEsc=function(d,k,e){if(opt&&opt.closable!==false){dlg.hide();handleHide();}
+if(e){e.stopEvent();}};var updateButtons=function(b){var width=0,cfg;if(!b){Ext.each(buttonNames,function(name){buttons[name].hide();});return width;}
+dlg.footer.dom.style.display='';Ext.iterate(buttons,function(name,btn){cfg=b[name];if(cfg){btn.show();btn.setText(Ext.isString(cfg)?cfg:Ext.MessageBox.buttonText[name]);width+=btn.getEl().getWidth()+15;}else{btn.hide();}});return width;};return{getDialog:function(titleText){if(!dlg){var btns=[];buttons={};Ext.each(buttonNames,function(name){btns.push(buttons[name]=new Ext.Button({text:this.buttonText[name],handler:handleButton.createCallback(name),hideMode:'offsets'}));},this);dlg=new Ext.Window({autoCreate:true,title:titleText,resizable:false,constrain:true,constrainHeader:true,minimizable:false,maximizable:false,stateful:false,modal:true,shim:true,buttonAlign:"center",width:400,height:100,minHeight:80,plain:true,footer:true,closable:true,close:function(){if(opt&&opt.buttons&&opt.buttons.no&&!opt.buttons.cancel){handleButton("no");}else{handleButton("cancel");}},fbar:new Ext.Toolbar({items:btns,enableOverflow:false})});dlg.render(document.body);dlg.getEl().addClass('x-window-dlg');mask=dlg.mask;bodyEl=dlg.body.createChild({html:'<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><div class="ext-mb-fix-cursor"><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div></div>'});iconEl=Ext.get(bodyEl.dom.firstChild);var contentEl=bodyEl.dom.childNodes[1];msgEl=Ext.get(contentEl.firstChild);textboxEl=Ext.get(contentEl.childNodes[2].firstChild);textboxEl.enableDisplayMode();textboxEl.addKeyListener([10,13],function(){if(dlg.isVisible()&&opt&&opt.buttons){if(opt.buttons.ok){handleButton("ok");}else if(opt.buttons.yes){handleButton("yes");}}});textareaEl=Ext.get(contentEl.childNodes[2].childNodes[1]);textareaEl.enableDisplayMode();progressBar=new Ext.ProgressBar({renderTo:bodyEl});bodyEl.createChild({cls:'x-clear'});}
+return dlg;},updateText:function(text){if(!dlg.isVisible()&&!opt.width){dlg.setSize(this.maxWidth,100);}
+msgEl.update(text?text+' ':'&#160;');var iw=iconCls!=''?(iconEl.getWidth()+iconEl.getMargins('lr')):0,mw=msgEl.getWidth()+msgEl.getMargins('lr'),fw=dlg.getFrameWidth('lr'),bw=dlg.body.getFrameWidth('lr'),w;w=Math.max(Math.min(opt.width||iw+mw+fw+bw,opt.maxWidth||this.maxWidth),Math.max(opt.minWidth||this.minWidth,bwidth||0));if(opt.prompt===true){activeTextEl.setWidth(w-iw-fw-bw);}
+if(opt.progress===true||opt.wait===true){progressBar.setSize(w-iw-fw-bw);}
+if(Ext.isIE&&w==bwidth){w+=4;}
+msgEl.update(text||'&#160;');dlg.setSize(w,'auto').center();return this;},updateProgress:function(value,progressText,msg){progressBar.updateProgress(value,progressText);if(msg){this.updateText(msg);}
+return this;},isVisible:function(){return dlg&&dlg.isVisible();},hide:function(){var proxy=dlg?dlg.activeGhost:null;if(this.isVisible()||proxy){dlg.hide();handleHide();if(proxy){dlg.unghost(false,false);}}
+return this;},show:function(options){if(this.isVisible()){this.hide();}
+opt=options;var d=this.getDialog(opt.title||"&#160;");d.setTitle(opt.title||"&#160;");var allowClose=(opt.closable!==false&&opt.progress!==true&&opt.wait!==true);d.tools.close.setDisplayed(allowClose);activeTextEl=textboxEl;opt.prompt=opt.prompt||(opt.multiline?true:false);if(opt.prompt){if(opt.multiline){textboxEl.hide();textareaEl.show();textareaEl.setHeight(Ext.isNumber(opt.multiline)?opt.multiline:this.defaultTextHeight);activeTextEl=textareaEl;}else{textboxEl.show();textareaEl.hide();}}else{textboxEl.hide();textareaEl.hide();}
+activeTextEl.dom.value=opt.value||"";if(opt.prompt){d.focusEl=activeTextEl;}else{var bs=opt.buttons;var db=null;if(bs&&bs.ok){db=buttons["ok"];}else if(bs&&bs.yes){db=buttons["yes"];}
+if(db){d.focusEl=db;}}
+if(Ext.isDefined(opt.iconCls)){d.setIconClass(opt.iconCls);}
+this.setIcon(Ext.isDefined(opt.icon)?opt.icon:bufferIcon);bwidth=updateButtons(opt.buttons);progressBar.setVisible(opt.progress===true||opt.wait===true);this.updateProgress(0,opt.progressText);this.updateText(opt.msg);if(opt.cls){d.el.addClass(opt.cls);}
+d.proxyDrag=opt.proxyDrag===true;d.modal=opt.modal!==false;d.mask=opt.modal!==false?mask:false;if(!d.isVisible()){document.body.appendChild(dlg.el.dom);d.setAnimateTarget(opt.animEl);d.on('show',function(){if(allowClose===true){d.keyMap.enable();}else{d.keyMap.disable();}},this,{single:true});d.show(opt.animEl);}
+if(opt.wait===true){progressBar.wait(opt.waitConfig);}
+return this;},setIcon:function(icon){if(!dlg){bufferIcon=icon;return;}
+bufferIcon=undefined;if(icon&&icon!=''){iconEl.removeClass('x-hidden');iconEl.replaceClass(iconCls,icon);bodyEl.addClass('x-dlg-icon');iconCls=icon;}else{iconEl.replaceClass(iconCls,'x-hidden');bodyEl.removeClass('x-dlg-icon');iconCls='';}
+return this;},progress:function(title,msg,progressText){this.show({title:title,msg:msg,buttons:false,progress:true,closable:false,minWidth:this.minProgressWidth,progressText:progressText});return this;},wait:function(msg,title,config){this.show({title:title,msg:msg,buttons:false,closable:false,wait:true,modal:true,minWidth:this.minProgressWidth,waitConfig:config});return this;},alert:function(title,msg,fn,scope){this.show({title:title,msg:msg,buttons:this.OK,fn:fn,scope:scope,minWidth:this.minWidth});return this;},confirm:function(title,msg,fn,scope){this.show({title:title,msg:msg,buttons:this.YESNO,fn:fn,scope:scope,icon:this.QUESTION,minWidth:this.minWidth});return this;},prompt:function(title,msg,fn,scope,multiline,value){this.show({title:title,msg:msg,buttons:this.OKCANCEL,fn:fn,minWidth:this.minPromptWidth,scope:scope,prompt:true,multiline:multiline,value:value});return this;},OK:{ok:true},CANCEL:{cancel:true},OKCANCEL:{ok:true,cancel:true},YESNO:{yes:true,no:true},YESNOCANCEL:{yes:true,no:true,cancel:true},INFO:'ext-mb-info',WARNING:'ext-mb-warning',QUESTION:'ext-mb-question',ERROR:'ext-mb-error',defaultTextHeight:75,maxWidth:600,minWidth:100,minProgressWidth:250,minPromptWidth:250,buttonText:{ok:"OK",cancel:"Cancel",yes:"Yes",no:"No"}};}();Ext.Msg=Ext.MessageBox;Ext.dd.PanelProxy=Ext.extend(Object,{constructor:function(panel,config){this.panel=panel;this.id=this.panel.id+'-ddproxy';Ext.apply(this,config);},insertProxy:true,setStatus:Ext.emptyFn,reset:Ext.emptyFn,update:Ext.emptyFn,stop:Ext.emptyFn,sync:Ext.emptyFn,getEl:function(){return this.ghost;},getGhost:function(){return this.ghost;},getProxy:function(){return this.proxy;},hide:function(){if(this.ghost){if(this.proxy){this.proxy.remove();delete this.proxy;}
+this.panel.el.dom.style.display='';this.ghost.remove();delete this.ghost;}},show:function(){if(!this.ghost){this.ghost=this.panel.createGhost(this.panel.initialConfig.cls,undefined,Ext.getBody());this.ghost.setXY(this.panel.el.getXY());if(this.insertProxy){this.proxy=this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});this.proxy.setSize(this.panel.getSize());}
+this.panel.el.dom.style.display='none';}},repair:function(xy,callback,scope){this.hide();if(typeof callback=="function"){callback.call(scope||this);}},moveProxy:function(parentNode,before){if(this.proxy){parentNode.insertBefore(this.proxy.dom,before);}}});Ext.Panel.DD=Ext.extend(Ext.dd.DragSource,{constructor:function(panel,cfg){this.panel=panel;this.dragData={panel:panel};this.proxy=new Ext.dd.PanelProxy(panel,cfg);Ext.Panel.DD.superclass.constructor.call(this,panel.el,cfg);var h=panel.header,el=panel.body;if(h){this.setHandleElId(h.id);el=panel.header;}
+el.setStyle('cursor','move');this.scroll=false;},showFrame:Ext.emptyFn,startDrag:Ext.emptyFn,b4StartDrag:function(x,y){this.proxy.show();},b4MouseDown:function(e){var x=e.getPageX(),y=e.getPageY();this.autoOffset(x,y);},onInitDrag:function(x,y){this.onStartDrag(x,y);return true;},createFrame:Ext.emptyFn,getDragEl:function(e){return this.proxy.ghost.dom;},endDrag:function(e){this.proxy.hide();this.panel.saveState();},autoOffset:function(x,y){x-=this.startPageX;y-=this.startPageY;this.setDelta(x,y);}});Ext.Toolbar=function(config){if(Ext.isArray(config)){config={items:config,layout:'toolbar'};}else{config=Ext.apply({layout:'toolbar'},config);if(config.buttons){config.items=config.buttons;}}
+Ext.Toolbar.superclass.constructor.call(this,config);};(function(){var T=Ext.Toolbar;Ext.extend(T,Ext.Container,{defaultType:'button',enableOverflow:false,trackMenus:true,internalDefaults:{removeMode:'container',hideParent:true},toolbarCls:'x-toolbar',initComponent:function(){T.superclass.initComponent.call(this);this.addEvents('overflowchange');},onRender:function(ct,position){if(!this.el){if(!this.autoCreate){this.autoCreate={cls:this.toolbarCls+' x-small-editor'};}
+this.el=ct.createChild(Ext.apply({id:this.id},this.autoCreate),position);Ext.Toolbar.superclass.onRender.apply(this,arguments);}},lookupComponent:function(c){if(Ext.isString(c)){if(c=='-'){c=new T.Separator();}else if(c==' '){c=new T.Spacer();}else if(c=='->'){c=new T.Fill();}else{c=new T.TextItem(c);}
+this.applyDefaults(c);}else{if(c.isFormField||c.render){c=this.createComponent(c);}else if(c.tag){c=new T.Item({autoEl:c});}else if(c.tagName){c=new T.Item({el:c});}else if(Ext.isObject(c)){c=c.xtype?this.createComponent(c):this.constructButton(c);}}
+return c;},applyDefaults:function(c){if(!Ext.isString(c)){c=Ext.Toolbar.superclass.applyDefaults.call(this,c);var d=this.internalDefaults;if(c.events){Ext.applyIf(c.initialConfig,d);Ext.apply(c,d);}else{Ext.applyIf(c,d);}}
+return c;},addSeparator:function(){return this.add(new T.Separator());},addSpacer:function(){return this.add(new T.Spacer());},addFill:function(){this.add(new T.Fill());},addElement:function(el){return this.addItem(new T.Item({el:el}));},addItem:function(item){return this.add.apply(this,arguments);},addButton:function(config){if(Ext.isArray(config)){var buttons=[];for(var i=0,len=config.length;i<len;i++){buttons.push(this.addButton(config[i]));}
+return buttons;}
+return this.add(this.constructButton(config));},addText:function(text){return this.addItem(new T.TextItem(text));},addDom:function(config){return this.add(new T.Item({autoEl:config}));},addField:function(field){return this.add(field);},insertButton:function(index,item){if(Ext.isArray(item)){var buttons=[];for(var i=0,len=item.length;i<len;i++){buttons.push(this.insertButton(index+i,item[i]));}
+return buttons;}
+return Ext.Toolbar.superclass.insert.call(this,index,item);},trackMenu:function(item,remove){if(this.trackMenus&&item.menu){var method=remove?'mun':'mon';this[method](item,'menutriggerover',this.onButtonTriggerOver,this);this[method](item,'menushow',this.onButtonMenuShow,this);this[method](item,'menuhide',this.onButtonMenuHide,this);}},constructButton:function(item){var b=item.events?item:this.createComponent(item,item.split?'splitbutton':this.defaultType);return b;},onAdd:function(c){Ext.Toolbar.superclass.onAdd.call(this);this.trackMenu(c);if(this.disabled){c.disable();}},onRemove:function(c){Ext.Toolbar.superclass.onRemove.call(this);if(c==this.activeMenuBtn){delete this.activeMenuBtn;}
+this.trackMenu(c,true);},onDisable:function(){this.items.each(function(item){if(item.disable){item.disable();}});},onEnable:function(){this.items.each(function(item){if(item.enable){item.enable();}});},onButtonTriggerOver:function(btn){if(this.activeMenuBtn&&this.activeMenuBtn!=btn){this.activeMenuBtn.hideMenu();btn.showMenu();this.activeMenuBtn=btn;}},onButtonMenuShow:function(btn){this.activeMenuBtn=btn;},onButtonMenuHide:function(btn){delete this.activeMenuBtn;}});Ext.reg('toolbar',Ext.Toolbar);T.Item=Ext.extend(Ext.BoxComponent,{hideParent:true,enable:Ext.emptyFn,disable:Ext.emptyFn,focus:Ext.emptyFn});Ext.reg('tbitem',T.Item);T.Separator=Ext.extend(T.Item,{onRender:function(ct,position){this.el=ct.createChild({tag:'span',cls:'xtb-sep'},position);}});Ext.reg('tbseparator',T.Separator);T.Spacer=Ext.extend(T.Item,{onRender:function(ct,position){this.el=ct.createChild({tag:'div',cls:'xtb-spacer',style:this.width?'width:'+this.width+'px':''},position);}});Ext.reg('tbspacer',T.Spacer);T.Fill=Ext.extend(T.Item,{render:Ext.emptyFn,isFill:true});Ext.reg('tbfill',T.Fill);T.TextItem=Ext.extend(T.Item,{constructor:function(config){T.TextItem.superclass.constructor.call(this,Ext.isString(config)?{text:config}:config);},onRender:function(ct,position){this.autoEl={cls:'xtb-text',html:this.text||''};T.TextItem.superclass.onRender.call(this,ct,position);},setText:function(t){if(this.rendered){this.el.update(t);}else{this.text=t;}}});Ext.reg('tbtext',T.TextItem);T.Button=Ext.extend(Ext.Button,{});T.SplitButton=Ext.extend(Ext.SplitButton,{});Ext.reg('tbbutton',T.Button);Ext.reg('tbsplit',T.SplitButton);})();Ext.ButtonGroup=Ext.extend(Ext.Panel,{baseCls:'x-btn-group',layout:'table',defaultType:'button',frame:true,internalDefaults:{removeMode:'container',hideParent:true},initComponent:function(){this.layoutConfig=this.layoutConfig||{};Ext.applyIf(this.layoutConfig,{columns:this.columns});if(!this.title){this.addClass('x-btn-group-notitle');}
+this.on('afterlayout',this.onAfterLayout,this);Ext.ButtonGroup.superclass.initComponent.call(this);},applyDefaults:function(c){c=Ext.ButtonGroup.superclass.applyDefaults.call(this,c);var d=this.internalDefaults;if(c.events){Ext.applyIf(c.initialConfig,d);Ext.apply(c,d);}else{Ext.applyIf(c,d);}
+return c;},onAfterLayout:function(){var bodyWidth=this.body.getFrameWidth('lr')+this.body.dom.firstChild.offsetWidth;this.body.setWidth(bodyWidth);this.el.setWidth(bodyWidth+this.getFrameWidth());}});Ext.reg('buttongroup',Ext.ButtonGroup);(function(){var T=Ext.Toolbar;Ext.PagingToolbar=Ext.extend(Ext.Toolbar,{pageSize:20,displayMsg:'Displaying {0} - {1} of {2}',emptyMsg:'No data to display',beforePageText:'Page',afterPageText:'of {0}',firstText:'First Page',prevText:'Previous Page',nextText:'Next Page',lastText:'Last Page',refreshText:'Refresh',initComponent:function(){var pagingItems=[this.first=new T.Button({tooltip:this.firstText,overflowText:this.firstText,iconCls:'x-tbar-page-first',disabled:true,handler:this.moveFirst,scope:this}),this.prev=new T.Button({tooltip:this.prevText,overflowText:this.prevText,iconCls:'x-tbar-page-prev',disabled:true,handler:this.movePrevious,scope:this}),'-',this.beforePageText,this.inputItem=new Ext.form.NumberField({cls:'x-tbar-page-number',allowDecimals:false,allowNegative:false,enableKeyEvents:true,selectOnFocus:true,submitValue:false,listeners:{scope:this,keydown:this.onPagingKeyDown,blur:this.onPagingBlur}}),this.afterTextItem=new T.TextItem({text:String.format(this.afterPageText,1)}),'-',this.next=new T.Button({tooltip:this.nextText,overflowText:this.nextText,iconCls:'x-tbar-page-next',disabled:true,handler:this.moveNext,scope:this}),this.last=new T.Button({tooltip:this.lastText,overflowText:this.lastText,iconCls:'x-tbar-page-last',disabled:true,handler:this.moveLast,scope:this}),'-',this.refresh=new T.Button({tooltip:this.refreshText,overflowText:this.refreshText,iconCls:'x-tbar-loading',handler:this.doRefresh,scope:this})];var userItems=this.items||this.buttons||[];if(this.prependButtons){this.items=userItems.concat(pagingItems);}else{this.items=pagingItems.concat(userItems);}
+delete this.buttons;if(this.displayInfo){this.items.push('->');this.items.push(this.displayItem=new T.TextItem({}));}
+Ext.PagingToolbar.superclass.initComponent.call(this);this.addEvents('change','beforechange');this.on('afterlayout',this.onFirstLayout,this,{single:true});this.cursor=0;this.bindStore(this.store,true);},onFirstLayout:function(){if(this.dsLoaded){this.onLoad.apply(this,this.dsLoaded);}},updateInfo:function(){if(this.displayItem){var count=this.store.getCount();var msg=count==0?this.emptyMsg:String.format(this.displayMsg,this.cursor+1,this.cursor+count,this.store.getTotalCount());this.displayItem.setText(msg);}},onLoad:function(store,r,o){if(!this.rendered){this.dsLoaded=[store,r,o];return;}
+var p=this.getParams();this.cursor=(o.params&&o.params[p.start])?o.params[p.start]:0;var d=this.getPageData(),ap=d.activePage,ps=d.pages;this.afterTextItem.setText(String.format(this.afterPageText,d.pages));this.inputItem.setValue(ap);this.first.setDisabled(ap==1);this.prev.setDisabled(ap==1);this.next.setDisabled(ap==ps);this.last.setDisabled(ap==ps);this.refresh.enable();this.updateInfo();this.fireEvent('change',this,d);},getPageData:function(){var total=this.store.getTotalCount();return{total:total,activePage:Math.ceil((this.cursor+this.pageSize)/this.pageSize),pages:total<this.pageSize?1:Math.ceil(total/this.pageSize)};},changePage:function(page){this.doLoad(((page-1)*this.pageSize).constrain(0,this.store.getTotalCount()));},onLoadError:function(){if(!this.rendered){return;}
+this.refresh.enable();},readPage:function(d){var v=this.inputItem.getValue(),pageNum;if(!v||isNaN(pageNum=parseInt(v,10))){this.inputItem.setValue(d.activePage);return false;}
+return pageNum;},onPagingFocus:function(){this.inputItem.select();},onPagingBlur:function(e){this.inputItem.setValue(this.getPageData().activePage);},onPagingKeyDown:function(field,e){var k=e.getKey(),d=this.getPageData(),pageNum;if(k==e.RETURN){e.stopEvent();pageNum=this.readPage(d);if(pageNum!==false){pageNum=Math.min(Math.max(1,pageNum),d.pages)-1;this.doLoad(pageNum*this.pageSize);}}else if(k==e.HOME||k==e.END){e.stopEvent();pageNum=k==e.HOME?1:d.pages;field.setValue(pageNum);}else if(k==e.UP||k==e.PAGEUP||k==e.DOWN||k==e.PAGEDOWN){e.stopEvent();if((pageNum=this.readPage(d))){var increment=e.shiftKey?10:1;if(k==e.DOWN||k==e.PAGEDOWN){increment*=-1;}
+pageNum+=increment;if(pageNum>=1&pageNum<=d.pages){field.setValue(pageNum);}}}},getParams:function(){return this.paramNames||this.store.paramNames;},beforeLoad:function(){if(this.rendered&&this.refresh){this.refresh.disable();}},doLoad:function(start){var o={},pn=this.getParams();o[pn.start]=start;o[pn.limit]=this.pageSize;if(this.fireEvent('beforechange',this,o)!==false){this.store.load({params:o});}},moveFirst:function(){this.doLoad(0);},movePrevious:function(){this.doLoad(Math.max(0,this.cursor-this.pageSize));},moveNext:function(){this.doLoad(this.cursor+this.pageSize);},moveLast:function(){var total=this.store.getTotalCount(),extra=total%this.pageSize;this.doLoad(extra?(total-extra):total-this.pageSize);},doRefresh:function(){this.doLoad(this.cursor);},bindStore:function(store,initial){var doLoad;if(!initial&&this.store){if(store!==this.store&&this.store.autoDestroy){this.store.destroy();}else{this.store.un('beforeload',this.beforeLoad,this);this.store.un('load',this.onLoad,this);this.store.un('exception',this.onLoadError,this);}
+if(!store){this.store=null;}}
+if(store){store=Ext.StoreMgr.lookup(store);store.on({scope:this,beforeload:this.beforeLoad,load:this.onLoad,exception:this.onLoadError});doLoad=true;}
+this.store=store;if(doLoad){this.onLoad(store,null,{});}},unbind:function(store){this.bindStore(null);},bind:function(store){this.bindStore(store);},onDestroy:function(){this.bindStore(null);Ext.PagingToolbar.superclass.onDestroy.call(this);}});})();Ext.reg('paging',Ext.PagingToolbar);
\ No newline at end of file
diff --git a/modules/organize/views/organize_dialog.html.php b/modules/organize/views/organize_dialog.html.php
new file mode 100644
index 0000000..9ea4d92
--- /dev/null
+++ b/modules/organize/views/organize_dialog.html.php
@@ -0,0 +1,23 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<link rel="stylesheet" type="text/css" href="<?= url::file("modules/organize/css/organize_dialog.css") ?>" />
+<script type="text/javascript">
+  var ORGANIZE_TITLE =
+    <?= t("Organize :: %album_title", array("album_title" => "__TITLE__"))->for_js() ?>;
+  var done_organizing = function(album_id) {
+    $("#g-dialog").dialog("close");
+    window.location = '<?= url::site("items/__ID__") ?>'.replace("__ID__", album_id);
+  }
+
+  var set_title = function(title) {
+    $("#g-dialog").dialog("option", "title", ORGANIZE_TITLE.replace("__TITLE__", title));
+  }
+  set_title("<?= html::clean($album->title) ?>");
+
+  var done_loading = function() {
+    $("#g-organize-app-loading").hide();
+  }
+</script>
+<div id="g-organize-app-loading">&nbsp;</div>
+<iframe id="g-organize-frame" src="<?= url::site("organize/frame/{$album->id}") ?>">
+</iframe>
+
diff --git a/modules/organize/views/organize_frame.html.php b/modules/organize/views/organize_frame.html.php
new file mode 100644
index 0000000..3a70ccf
--- /dev/null
+++ b/modules/organize/views/organize_frame.html.php
@@ -0,0 +1,604 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<link rel="stylesheet" type="text/css" href="<?= url::file("modules/organize/vendor/ext/css/ext-all.css") ?>" />
+<link rel="stylesheet" type="text/css" href="<?= url::file("modules/organize/vendor/ext/css/ux-all.css") ?>" />
+<link rel="stylesheet" type="text/css" href="<?= url::file("modules/organize/css/organize_frame.css") ?>" />
+<style type="text/css">
+  .g-organize div.thumb-album div.icon {
+    background-image: url(<?= url::file("modules/organize/vendor/ext/images/default/tree/folder.gif") ?>);
+  }
+</style>
+<script type="text/javascript" src="<?= url::file("modules/organize/vendor/ext/js/ext-organize-bundle.js") ?>"></script>
+<script type="text/javascript">
+  Ext.BLANK_IMAGE_URL = "<?= url::file("modules/organize/vendor/ext/images/default/s.gif") ?>";
+  Ext.Ajax.timeout = 1000000;  // something really large
+  // I18N for dialog boxes.
+  Ext.Msg.buttonText = {
+    ok: <?= t("OK")->for_js() ?>,
+    cancel: <?= t("Cancel")->for_js() ?>,
+    yes: <?= t("Yes")->for_js() ?>,
+    no: <?= t("No")->for_js() ?>
+  };
+
+  Ext.onReady(function() {
+    /*
+     * ********************************************************************************
+     * Utility functions for loading data and making changes
+     * ********************************************************************************
+     */
+    var start_busy = function(msg) {
+      thumb_data_view.el.mask(msg, "loading");
+    }
+
+    var stop_busy = function() {
+      thumb_data_view.el.unmask();
+    }
+
+    // Notify the parent dialog that the ExtJS app is loaded
+    if (parent.done_loading) {
+      parent.done_loading();
+    }
+
+    var show_generic_error = function() {
+      stop_busy();
+      Ext.Msg.alert(
+        <?= t("An error occurred.  Consult your system administrator.")->for_js() ?>);
+    }
+
+    var current_album_id = null;
+    var current_album_editable = null;
+    var load_album_data = function(id) {
+      if (current_album_id) {
+        // Don't show the loading message on the initial load, it
+        // feels a little jarring.
+        start_busy(<?= t("Loading...")->for_js() ?>);
+      }
+      Ext.Ajax.request({
+        url: '<?= url::site("organize/album_info/__ID__") ?>'.replace("__ID__", id),
+        success: function(xhr, opts) {
+          stop_busy();
+          var album_info = Ext.util.JSON.decode(xhr.responseText);
+          var store = new Ext.data.JsonStore({
+            autoDestroy: true,
+            fields: ["id", "thumb_url", "width", "height", "type", "title"],
+            idProperty: "id",
+            root: "children",
+            data: album_info
+          });
+          current_album_id = id;
+          thumb_data_view.bindStore(store);
+          sort_column_combobox.setValue(album_info.sort_column);
+          sort_order_combobox.setValue(album_info.sort_order);
+
+          current_album_editable = album_info.editable;
+          if (current_album_editable) {
+            thumb_data_view.dragZone.unlock();
+          } else {
+            thumb_data_view.dragZone.lock();
+          }
+          if (parent.set_title) {
+            parent.set_title(album_info.title);
+          }
+        },
+        failure: show_generic_error
+      });
+    };
+
+    var reload_album_data = function() {
+      if (current_album_id) {
+        load_album_data(current_album_id);
+      }
+    };
+
+    var set_album_sort = function(params) {
+      start_busy(<?= t("Changing sort...")->for_js() ?>);
+      params["csrf"] = '<?= access::csrf_token() ?>';
+      Ext.Ajax.request({
+        url: '<?= url::site("organize/set_sort/__ID__") ?>'.replace("__ID__", current_album_id),
+        method: "post",
+        success: function() {
+          stop_busy();
+          reload_album_data();
+        },
+        failure: show_generic_error,
+        params: params
+      });
+    }
+
+    var tag_selected_items = function(tag) {
+      var nodes = thumb_data_view.getSelectedNodes();
+      var item_ids = [];
+      for (var i = 0; i != nodes.length; i++) {
+        var node = Ext.fly(nodes[i]);
+        item_ids.push(get_id_from_node(node));
+      }
+      start_busy(<?= t("Tagging...")->for_js() ?>);
+      Ext.Ajax.request({
+        url: '<?= url::site("organize/tag") ?>',
+        method: "post",
+        success: function() {
+          stop_busy();
+          reload_album_data();
+        },
+        failure: show_generic_error,
+        params: {
+          item_ids: item_ids.join(","),
+          tag_names: tag,
+          csrf: '<?= access::csrf_token() ?>'
+        }
+      });
+    };
+
+    var delete_selected_items = function() {
+      var nodes = thumb_data_view.getSelectedNodes();
+      var item_ids = [];
+      for (var i = 0; i != nodes.length; i++) {
+        var node = Ext.fly(nodes[i]);
+        item_ids.push(get_id_from_node(node));
+      }
+      start_busy(<?= t("Deleting...")->for_js() ?>);
+      Ext.Ajax.request({
+        url: '<?= url::site("organize/delete") ?>',
+        method: "post",
+        success: function() {
+          stop_busy();
+          reload_album_data();
+        },
+        failure: show_generic_error,
+        params: {
+          item_ids: item_ids.join(","),
+          csrf: '<?= access::csrf_token() ?>'
+        }
+      });
+    };
+
+    var get_id_from_node = function(node) {
+      var id = node.getAttribute("rel");
+      if (id) {
+        return id;
+      }
+
+      // IE9 has a bug which causes it to be unable to read the "rel" attr
+      // so hack it by extracting the id the CSS class id.  This is fragile.
+      // ref: https://sourceforge.net/apps/trac/gallery/ticket/1790
+      return node.getAttribute("id").replace("thumb-", "");
+    }
+
+    /*
+     * ********************************************************************************
+     * JsonStore, DataView and Panel for viewing albums
+     * ********************************************************************************
+     */
+    var thumb_data_view = new Ext.DataView({
+      autoScroll: true,
+      enableDragDrop: true,
+      itemSelector: "div.thumb",
+      plugins: [
+        new Ext.DataView.DragSelector({dragSafe: true})
+      ],
+      listeners: {
+        "dblclick": function(v, index, node, e) {
+          node = Ext.get(node);
+          if (node.hasClass("thumb-album")) {
+            var id = get_id_from_node(node);
+            tree_panel.fireEvent("click", tree_panel.getNodeById(id))
+          }
+        },
+        "render": function(v) {
+          v.dragZone = new Ext.dd.DragZone(v.getEl(), {
+            ddGroup: "organizeDD",
+            containerScroll: true,
+            getDragData: function(e) {
+              var target = e.getTarget(v.itemSelector, 10);
+              if (target) {
+                if (e.ctrlKey == false) {
+                  if (!v.isSelected(target)) {
+                    v.onClick(e);
+                  }
+                }
+                var selected_nodes = v.getSelectedNodes();
+                var drag_data = {
+                  nodes: selected_nodes,
+                  repair_xy: Ext.fly(target).getXY()
+                };
+                if (selected_nodes.length == 1) {
+                  drag_data.ddel = target;
+                } else {
+                  var drag_ghost = document.createElement("div");
+                  drag_ghost.className = "drag-ghost";
+                  for (var i = 0; i != selected_nodes.length; i++) {
+                    var inner = document.createElement("div");
+                    drag_ghost.appendChild(inner);
+
+                    var img = Ext.get(selected_nodes[i]).dom.firstChild;
+                    var child = inner.appendChild(img.cloneNode(true));
+                    Ext.get(child).setWidth(Ext.fly(img).getWidth() / 2);
+                    Ext.get(child).setHeight(Ext.fly(img).getHeight() / 2);
+                  }
+                  // The contents of the ghost float, and the ghost is wide enough for
+                  // 4 images across so make sure that the ghost is tall enough.  Thumbnails
+                  // are max 120px high max, and ghost thumbs are half of that, but leave some
+                  // padding because IE is unpredictable.
+                  drag_ghost.style.height = Math.ceil(i/4) * 72 + "px";
+                  drag_data.ddel = drag_ghost;
+                }
+                return drag_data;
+              }
+            },
+            getRepairXY: function() {
+              return this.dragData.repair_xy;
+            }
+          });
+
+          v.dropZone = new Ext.dd.DropZone(v.getEl(), {
+            ddGroup: "organizeDD",
+            getTargetFromEvent: function(e) {
+              return e.getTarget("div.thumb", 10);
+            },
+            onNodeOut: function(target, dd, e, data) {
+              Ext.fly(target).removeClass("active-left");
+              Ext.fly(target).removeClass("active-right");
+            },
+            onNodeOver: function(target, dd, e, data) {
+              var target_x = Ext.lib.Dom.getX(target);
+              var target_center = target_x + (target.offsetWidth / 2);
+              if (Ext.lib.Event.getPageX(e) < target_center) {
+                Ext.fly(target).addClass("active-left");
+                Ext.fly(target).removeClass("active-right");
+                this.drop_side = "before";
+              } else {
+                Ext.fly(target).removeClass("active-left");
+                Ext.fly(target).addClass("active-right");
+                this.drop_side = "after";
+              }
+              return Ext.dd.DropZone.prototype.dropAllowed;
+            },
+            onNodeDrop: function(target, dd, e, data) {
+              var nodes = data.nodes;
+              source_ids = [];
+              for (var i = 0; i != nodes.length; i++) {
+                source_ids.push(get_id_from_node(Ext.fly(nodes[i])));
+              }
+              start_busy(<?= t("Rearranging...")->for_js() ?>);
+              target = Ext.fly(target);
+              Ext.Ajax.request({
+                url: '<?= url::site("organize/rearrange") ?>',
+                method: "post",
+                success: function() {
+                  stop_busy();
+                  reload_album_data();
+                },
+                failure: show_generic_error,
+                params: {
+                  source_ids: source_ids.join(","),
+                  target_id: get_id_from_node(target),
+                  relative: this.drop_side, // calculated in onNodeOver
+                  csrf: '<?= access::csrf_token() ?>'
+                }
+              });
+              return true;
+            }
+          });
+        },
+        "selectionchange": function(v, selections) {
+          tag_button.setDisabled(!selections.length || !current_album_editable || !tag_textfield.getValue());
+          delete_button.setDisabled(!selections.length || !current_album_editable);
+        }
+      },
+      multiSelect: true,
+      selectedClass: "selected",
+      tpl: new Ext.XTemplate(
+        '<tpl for=".">',
+        '<tpl if="thumb_url">',
+        '<div class="thumb thumb-{type}" id="thumb-{id}" rel="{id}">',
+        '<img src="{thumb_url}" width="{width}" height="{height}" title="{title}">',
+        '<div class="icon"></div>',
+        '</div>',
+        '</tpl>',
+        '<tpl if="!thumb_url">',
+        '<div class="thumb thumb-missing thumb-{type}" id="thumb-{id}" rel="{id}">',
+        '<span>' + <?= t("No thumbnail")->for_js() ?> + '</span>',
+        '<div class="icon"></div>',
+        '</div>',
+        '</tpl>',
+        '</tpl>')
+    });
+
+    /*
+     * ********************************************************************************
+     * Toolbar with sort column, sort order, delete and close buttons.
+     * ********************************************************************************
+     */
+
+    sort_order_data = [];
+    <? foreach (album::get_sort_order_options() as $key => $value): ?>
+    sort_order_data.push(["<?= $key ?>", <?= $value->for_js() ?>]);
+    <? endforeach ?>
+    var sort_column_combobox = new Ext.form.ComboBox({
+      mode: "local",
+      editable: false,
+      allowBlank: false,
+      forceSelection: true,
+      triggerAction: "all",
+      flex: 3,
+      store: new Ext.data.ArrayStore({
+        id: 0,
+        fields: ["key", "value"],
+        data: sort_order_data
+      }),
+      listeners: {
+        "select": function(combo, record, index) {
+          set_album_sort({sort_column: record.id});
+        }
+      },
+      valueField: "key",
+      displayField: "value"
+    });
+
+    var sort_order_combobox = new Ext.form.ComboBox({
+      mode: "local",
+      editable: false,
+      allowBlank: false,
+      forceSelection: true,
+      triggerAction: "all",
+      flex: 2,
+      store: new Ext.data.ArrayStore({
+        id: 0,
+        fields: ["key", "value"],
+        data: [
+          ["ASC", <?= t("Ascending")->for_js() ?>],
+          ["DESC", <?= t("Descending")->for_js() ?>]]
+      }),
+      listeners: {
+        "select": function(combo, record, index) {
+          set_album_sort({sort_order: record.id});
+        }
+      },
+      valueField: "key",
+      displayField: "value"
+    });
+
+    var tag_textfield = new Ext.form.TextField({
+      flex: 4,
+      enableKeyEvents: true,
+      listeners: {
+        "keyup": function(v, e) {
+          var nodes = thumb_data_view.getSelectedNodes();
+          tag_button.setDisabled(!nodes.length || !current_album_editable || !tag_textfield.getValue());
+        }
+      }
+    });
+
+    var tag_button = new Ext.Button({
+      flex: 2,
+        text: <?= t("Tag")->for_js() ?>,
+        cls: "x-btn-text-icon",
+        id: "tag-button",
+        disabled: true,
+        listeners: {
+          "click": function() {
+            tag_selected_items(tag_textfield.getValue());
+            return true;
+          }
+        }
+    });
+
+    var delete_button = new Ext.Button({
+      flex: 2,
+      text: <?= t("Delete")->for_js() ?>,
+      cls: "x-btn-text-icon",
+      iconCls: "delete",
+      id: "delete-button",
+      disabled: true,
+      listeners: {
+        "click": function() {
+          Ext.Msg.show({
+            title: <?= t("Are you sure you want to delete the selected items?")->for_js() ?>,
+            buttons: Ext.Msg.YESNO,
+            fn: function(buttonId) {
+              if (buttonId == "yes") {
+                delete_selected_items();
+              }
+            }
+          });
+          return true;
+        }
+      }
+    });
+
+    var button_panel = new Ext.Panel({
+      layout: "hbox",
+      region: "south",
+      height: 24,
+      layoutConfig: {
+        align: "stretch"
+      },
+      items: [
+        {
+          xtype: "panel",
+          layout: "hbox",
+          width: 300,
+          items: [
+            {
+              xtype: "label",
+              cls: "sort",
+              flex: 2,
+              text: <?= t("Sort order: ")->for_js() ?>
+            },
+            sort_column_combobox,
+            sort_order_combobox
+          ]
+        },
+<? if (module::is_active("tag")): ?>
+        {
+          xtype: "spacer",
+          flex: 3
+        },
+        tag_textfield,
+        tag_button,
+        {
+          xtype: "spacer",
+          flex: 1
+        },
+<? else: ?>
+        {
+          xtype: "spacer",
+          flex: 10
+        },
+<? endif ?>
+        delete_button,
+        {
+          xtype: "button",
+          flex: 2,
+          text: <?= t("Close")->for_js() ?>,
+          listeners: {
+            "click": function() {
+              parent.done_organizing(current_album_id);
+            }
+          }
+        }
+      ]
+    });
+
+    var album_panel = new Ext.Panel({
+      layout: "fit",
+      region: "center",
+      title: <?= t("Drag and drop photos to re-order or move between albums")->for_js() ?>,
+      items: [thumb_data_view],
+      bbar: button_panel
+    });
+
+    /*
+     * ********************************************************************************
+     *  TreeLoader and TreePanel
+     * ********************************************************************************
+     */
+    var tree_loader = new Ext.tree.TreeLoader({
+      dataUrl: '<?= url::site("organize/tree/{$album->id}") ?>',
+      nodeParameter: "root_id",
+      requestMethod: "post"
+    });
+
+    var tree_panel = new Ext.tree.TreePanel({
+      useArrows: true,
+      autoScroll: true,
+      animate: true,
+      border: false,
+      containerScroll: true,
+      enableDD: true,
+      dropConfig: {
+        appendOnly: true,
+        ddGroup: "organizeDD"
+      },
+      listeners: {
+        "click": function(node) {
+          load_album_data(node.id);
+          if (node.isExpandable() && !node.isExpanded()) {
+            node.expand();
+          }
+        },
+        "afterrender": function(v) {
+          // Override Ext.tree.TreeDropZone.onNodeOver to change the
+          // x-tree-drop-ok-append CSS class to be x-dd-drop-ok since
+          // that connotes "ok" instead of "adding something new" and we're
+          // moving the item, not adding it.
+          //
+          // There's probably a better way of overriding the parent method, but
+          // my JavaScript-fu is weak.
+          v.dropZone.super_onNodeOver = v.dropZone.onNodeOver;
+          v.dropZone.onNodeOver = function(target, dd, e, data) {
+            var returnCls = this.super_onNodeOver(target, dd, e, data);
+            if (returnCls == "x-tree-drop-ok-append") {
+              return "x-dd-drop-ok";
+            }
+            return returnCls;
+          }
+
+          // Override Ext.tree.TreeDropZone.getDropPoint so that it allows dropping
+          // on any node.  The standard function won't let you drop on leaves, but
+          // in our model we consider an album without sub-albums a leaf.
+          v.dropZone.getDropPoint = function(e, n, dd) {
+            return "append";
+          }
+
+          v.dropZone.onNodeDrop = function(target, dd, e, data) {
+            var nodes = data.nodes;
+            source_ids = [];
+            var moving_albums = 0;
+            for (var i = 0; i != nodes.length; i++) {
+              var node = Ext.fly(nodes[i]);
+              source_ids.push(get_id_from_node(node));
+              moving_albums |= node.hasClass("thumb-album");
+            }
+            start_busy(<?= t("Moving...")->for_js() ?>);
+            Ext.Ajax.request({
+              url: '<?= url::site("organize/reparent") ?>',
+              method: "post",
+              success: function() {
+                stop_busy();
+                reload_album_data();
+
+                // If we're moving albums around then we need to refresh the tree when we're done
+                if (moving_albums) {
+                  target.node.reload();
+
+                  // If the target node contains the selected node, then the selected
+                  // node just got strafed by the target's reload and no longer exists,
+                  // so we can't reload it.
+                  var selected_node = v.getNodeById(current_album_id);
+                  if (selected_node) {
+                    selected_node.reload();
+                  }
+                }
+              },
+              failure: show_generic_error,
+              params: {
+                source_ids: source_ids.join(","),
+                target_id: target.node.id,
+                csrf: '<?= access::csrf_token() ?>'
+              }
+            });
+            return true;
+          }
+        }
+      },
+      loader: tree_loader,
+
+      region: "west",
+      split: true,
+      minSize: 200,
+      maxSize: 350,
+      width: 200,
+
+      root: {
+        allowDrop: Boolean(<?= access::can("edit", item::root()) ?>),
+        nodeType: "async",
+        text: "<?= html::clean(item::root()->title) ?>",
+        draggable: false,
+        id: "<?= item::root()->id ?>",
+        expanded: true
+      }
+    });
+
+    var first_organize_load = true;
+    tree_loader.addListener("load", function() {
+      if (first_organize_load) {
+        tree_panel.getNodeById(<?= $album->id ?>).select();
+        load_album_data(<?= $album->id ?>);
+        first_organize_load = false;
+
+        // This is a hack that allows us to reload tree nodes asynchronously
+        // even though they came with preloaded hierarchical data from the
+        // initial tree load.  Without this, any nodes that were preloaded
+        // initially won't refresh if you call node.reload() on them.
+        tree_loader.doPreload = function() { return false; }
+      }
+    });
+    tree_panel.getRootNode().expand();
+
+    var outer = new Ext.Viewport({
+      layout: "border",
+      cls: "g-organize",
+      items: [tree_panel, album_panel]
+    });
+  });
+</script>
diff --git a/modules/recaptcha/controllers/admin_recaptcha.php b/modules/recaptcha/controllers/admin_recaptcha.php
new file mode 100644
index 0000000..8ba43bb
--- /dev/null
+++ b/modules/recaptcha/controllers/admin_recaptcha.php
@@ -0,0 +1,61 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Recaptcha_Controller extends Admin_Controller {
+  public function index() {
+    $form = recaptcha::get_configure_form();
+    if (request::method() == "post") {
+      // @todo move the "save" part of this into a separate controller function
+      access::verify_csrf();
+      $old_public_key = module::get_var("recaptcha", "public_key");
+      $old_private_key = module::get_var("recaptcha", "private_key");
+      if ($form->validate()) {
+        $public_key = $form->configure_recaptcha->public_key->value;
+        $private_key = $form->configure_recaptcha->private_key->value;
+
+        if ($public_key && $private_key) {
+          module::set_var("recaptcha", "public_key", $public_key);
+          module::set_var("recaptcha", "private_key", $private_key);
+          message::success(t("reCAPTCHA configured!"));
+          log::success("recaptcha", t("reCAPTCHA public and private keys set"));
+          url::redirect("admin/recaptcha");
+        } else if ($public_key && !$private_key) {
+          $form->configure_recaptcha->private_key->add_error("invalid");
+        } else if ($private_key && !$public_key) {
+          $form->configure_recaptcha->public_key->add_error("invalid");
+        } else {
+          module::set_var("recaptcha", "public_key", "");
+          module::set_var("recaptcha", "private_key", "");
+          message::success(t("No keys provided.  reCAPTCHA is disabled!"));
+          log::success("recaptcha", t("reCAPTCHA public and private keys cleared"));
+          url::redirect("admin/recaptcha");
+        }
+      }
+    }
+
+    recaptcha::check_config();
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("reCAPTCHA");
+    $view->content = new View("admin_recaptcha.html");
+    $view->content->public_key = module::get_var("recaptcha", "public_key");
+    $view->content->private_key = module::get_var("recaptcha", "private_key");
+    $view->content->form = $form;
+    print $view;
+  }
+}
diff --git a/modules/recaptcha/css/recaptcha.css b/modules/recaptcha/css/recaptcha.css
new file mode 100644
index 0000000..27117a5
--- /dev/null
+++ b/modules/recaptcha/css/recaptcha.css
@@ -0,0 +1,7 @@
+#g-content #g-comments ul li #g-recaptcha {
+  padding: 0;
+}
+
+#g-content #g-comments ul li #g-recaptcha div {
+  padding: 0;
+}
diff --git a/modules/recaptcha/helpers/recaptcha.php b/modules/recaptcha/helpers/recaptcha.php
new file mode 100644
index 0000000..cc50d72
--- /dev/null
+++ b/modules/recaptcha/helpers/recaptcha.php
@@ -0,0 +1,152 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class recaptcha_Core {
+  static function get_configure_form() {
+    $form = new Forge("admin/recaptcha", "", "post", array("id" => "g-configure-recaptcha-form"));
+    $group = $form->group("configure_recaptcha")
+      ->label(t("Configure reCAPTCHA"));
+    $group->input("public_key")
+      ->label(t("Public Key"))
+      ->value(module::get_var("recaptcha", "public_key"))
+      ->rules("required")
+      ->error_messages("required", t("You must enter a public key"))
+      ->error_messages("invalid", t("This public key is invalid"));
+    $group->input("private_key")
+      ->label(t("Private Key"))
+      ->value(module::get_var("recaptcha", "private_key"))
+      ->callback("recaptcha::verify_key")
+      ->error_messages("required", t("You must enter a private key"))
+      ->error_messages("invalid", t("This private key is invalid"));
+
+    $group->submit("")->value(t("Save"));
+    $site_domain = urlencode(stripslashes($_SERVER["HTTP_HOST"]));
+    $form->get_key_url = "http://www.google.com/recaptcha/admin/create?domains=$site_domain&app=Gallery3";
+    return $form;
+  }
+
+  static function check_config() {
+    $public_key = module::get_var("recaptcha", "public_key");
+    $private_key = module::get_var("recaptcha", "private_key");
+    if (empty($public_key) || empty($private_key)) {
+      site_status::warning(
+        t("reCAPTCHA is not quite ready!  Please configure the <a href=\"%url\">reCAPTCHA Keys</a>",
+          array("url" => html::mark_clean(url::site("admin/recaptcha")))),
+        "recaptcha_config");
+    } else {
+      site_status::clear("recaptcha_config");
+    }
+  }
+
+  /**
+   * Verify that the recaptcha key is valid.
+   * @param string $private_key
+   * @return boolean
+   */
+  static function verify_key($private_key_input) {
+    if (!$private_key_input->value) {
+      $private_key_input->add_error("required", 1);
+      return;
+    }
+
+    $remote_ip = Input::instance()->server("REMOTE_ADDR");
+    $response = self::_http_post("api-verify.recaptcha.net", "/verify",
+                                 array("privatekey" => $private_key_input->value,
+                                       "remoteip" => $remote_ip,
+                                       "challenge" => "right",
+                                       "response" => "wrong"));
+
+    if ($response[1] == "false\ninvalid-site-private-key") {
+      // This is the only thing I can figure out how to verify.
+      // See http://recaptcha.net/apidocs/captcha for possible return values
+      $private_key_input->add_error("invalid", 1);
+    }
+  }
+
+  /**
+   * Form validation call back for captcha validation
+   * @param string $form
+   * @return string error message or null
+   */
+  static function is_recaptcha_valid($challenge, $response, $private_key) {
+    $input = Input::instance();
+    $remote_ip = $input->server("REMOTE_ADDR");
+
+    // discard spam submissions
+    if (empty($challenge) || empty($response)) {
+      return  "incorrect-captcha-sol";
+    }
+
+    $response = self::_http_post("api-verify.recaptcha.net", "/verify",
+                              array("privatekey" => $private_key,
+                                    "remoteip" => $remote_ip,
+                                    "challenge" => $challenge,
+                                    "response" => $response));
+
+    $answers = explode ("\n", $response [1]);
+    if (trim ($answers [0]) == "true") {
+      return null;
+    } else {
+      return $answers[1];
+    }
+  }
+
+  /**
+   * Encodes the given data into a query string format
+   * @param $data - array of string elements to be encoded
+   * @return string - encoded request
+   */
+  private static function _encode(array $data){
+    $req = array();
+    foreach ($data as $key => $value){
+      $req[] = "$key=" . urlencode(stripslashes($value));
+    }
+    return implode("&", $req);
+  }
+
+  /**
+   * Submits an HTTP POST to a reCAPTCHA server
+   * @param string $host
+   * @param string $path
+   * @param array $data
+   * @param int port
+   * @return array response
+   */
+  private static function _http_post($host, $path, $data, $port = 80) {
+    $req = self::_encode($data);
+    $http_request  = "POST $path HTTP/1.0\r\n";
+    $http_request .= "Host: $host\r\n";
+    $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
+    $http_request .= "Content-Length: " . strlen($req) . "\r\n";
+    $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
+    $http_request .= "\r\n";
+    $http_request .= $req;
+    $response = "";
+    if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
+      throw new Exception("@todo COULD NOT OPEN SOCKET");
+    }
+    fwrite($fs, $http_request);
+    while (!feof($fs)) {
+      $response .= fgets($fs, 1160); // One TCP-IP packet
+    }
+    fclose($fs);
+    $response = explode("\r\n\r\n", $response, 2);
+    return $response;
+  }
+}
diff --git a/modules/recaptcha/helpers/recaptcha_event.php b/modules/recaptcha/helpers/recaptcha_event.php
new file mode 100644
index 0000000..4ccacc7
--- /dev/null
+++ b/modules/recaptcha/helpers/recaptcha_event.php
@@ -0,0 +1,42 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class recaptcha_event_Core {
+  static function captcha_protect_form($form) {
+    if (module::get_var("recaptcha", "public_key")) {
+      foreach ($form->inputs as $input) {
+        if ($input instanceof Form_Group) {
+          $input->recaptcha("recaptcha")->label("")->id("g-recaptcha");
+          return;
+        }
+      }
+
+      // If we haven't returned yet, then add the captcha at the end of the form
+      $form->recaptcha("recaptcha")->label("")->id("g-recaptcha");
+    }
+  }
+
+  static function admin_menu($menu, $theme) {
+    $menu->get("settings_menu")
+      ->append(Menu::factory("link")
+               ->id("recaptcha")
+               ->label(t("reCAPTCHA"))
+               ->url(url::site("admin/recaptcha")));
+  }
+}
diff --git a/modules/recaptcha/helpers/recaptcha_installer.php b/modules/recaptcha/helpers/recaptcha_installer.php
new file mode 100644
index 0000000..1b526e5
--- /dev/null
+++ b/modules/recaptcha/helpers/recaptcha_installer.php
@@ -0,0 +1,28 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class recaptcha_installer {
+  static function activate() {
+    recaptcha::check_config();
+  }
+
+  static function deactivate() {
+    site_status::clear("recaptcha_config");
+  }
+}
diff --git a/modules/recaptcha/helpers/recaptcha_theme.php b/modules/recaptcha/helpers/recaptcha_theme.php
new file mode 100644
index 0000000..36087ff
--- /dev/null
+++ b/modules/recaptcha/helpers/recaptcha_theme.php
@@ -0,0 +1,28 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class recaptcha_theme_Core {
+  static function head($theme) {
+    return $theme->css("recaptcha.css");
+  }
+
+  static function admin_head($theme) {
+    return $theme->css("recaptcha.css");
+  }
+}
\ No newline at end of file
diff --git a/modules/recaptcha/libraries/Form_Recaptcha.php b/modules/recaptcha/libraries/Form_Recaptcha.php
new file mode 100644
index 0000000..8a9e63a
--- /dev/null
+++ b/modules/recaptcha/libraries/Form_Recaptcha.php
@@ -0,0 +1,67 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Form_Recaptcha_Core extends Form_Input {
+  private $_error = null;
+
+  protected $data = array(
+    'name'  => '',
+    'value' => '',
+  );
+
+  public function __construct($name) {
+    parent::__construct($name);
+    $this->error_messages("incorrect-captcha-sol",
+                          t("The values supplied to reCAPTCHA are incorrect."));
+    $this->error_messages("invalid-site-private-key", t("The site private key is incorrect."));
+  }
+
+  public function render() {
+    $public_key = module::get_var("recaptcha", "public_key");
+    if (empty($public_key)) {
+      throw new Exception("@todo NEED KEY <a href=\"http://recaptcha.net/api/getkey\">" .
+                          "http://recaptcha.net/api/getkey</a>");
+    }
+
+    $view = new View("form_recaptcha.html");
+    $view->public_key = $public_key;
+    return $view;
+  }
+
+  /**
+   * Validate this input based on the set rules.
+   *
+   * @return  bool
+   */
+  public function validate() {
+    $input = Input::instance();
+    $challenge = $input->post("recaptcha_challenge_field", "", true);
+    $response = $input->post("recaptcha_response_field", "", true);
+    if (!empty($challenge)) {
+      $this->_error = recaptcha::is_recaptcha_valid(
+        $challenge, $response, module::get_var("recaptcha", "private_key"));
+      if (!empty($this->_error)) {
+        $this->add_error($this->_error, 1);
+      }
+    }
+    $this->is_valid = empty($this->_error);
+    return empty($this->_error);
+  }
+
+}
\ No newline at end of file
diff --git a/modules/recaptcha/module.info b/modules/recaptcha/module.info
new file mode 100644
index 0000000..6806bb9
--- /dev/null
+++ b/modules/recaptcha/module.info
@@ -0,0 +1,7 @@
+name = "reCAPTCHA"
+description = "reCAPTCHA displays a graphical verification that protects the input form from abuse from 'bots,' or automated programs usually written to generate spam (http://recaptcha.net)."
+version = 1
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:recaptcha"
+discuss_url = "http://galleryproject.org/forum_module_recaptcha"
diff --git a/modules/recaptcha/views/admin_recaptcha.html.php b/modules/recaptcha/views/admin_recaptcha.html.php
new file mode 100644
index 0000000..4f07fef
--- /dev/null
+++ b/modules/recaptcha/views/admin_recaptcha.html.php
@@ -0,0 +1,35 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="g-block">
+  <h1> <?= t("reCAPTCHA challenge filtering") ?> </h1>
+  <p>
+    <?= t("reCAPTCHA is a free CAPTCHA service that helps to digitize books, newspapers and old time radio shows.  In order to use it, you need to sign up for a <a href=\"%domain_url\">reCAPTCHA Public/Private Key pair</a>, which is also free.  Once registered, the challenge and response strings are evaluated at <a href=\"%recaptcha_url\">recaptcha.net</a> to determine if the form content has been entered by a bot.",
+          array("domain_url" => $form->get_key_url,
+                "recaptcha_url" => html::mark_clean("http://recaptcha.net"))) ?>
+  </p>
+
+  <div class="g-block-content">
+    <?= $form ?>
+
+    <? if ($public_key && $private_key): ?>
+    <div id="g-admin-recaptcha-test">
+      <h2> <?= t("reCAPTCHA test") ?> </h2>
+      <p>
+        <?= t("If you see a CAPTCHA form below, then reCAPTCHA is functioning properly.") ?>
+      </p>
+
+      <div id="g-recaptcha">
+      <script type="text/javascript" src="http://api.recaptcha.net/js/recaptcha_ajax.js"></script>
+      <script type="text/javascript">
+        Recaptcha.create("<?= $public_key ?>", "g-recaptcha", {
+          callback: Recaptcha.focus_response_field,
+          lang: "en",
+          custom_translations : { instructions_visual : <?= t("Type words to check:")->for_js() ?>},
+          theme: "white"
+        });
+      </script>
+      </div>
+    </div>
+    <? endif ?>
+
+  </div>
+</div>
diff --git a/modules/recaptcha/views/form_recaptcha.html.php b/modules/recaptcha/views/form_recaptcha.html.php
new file mode 100644
index 0000000..7481d00
--- /dev/null
+++ b/modules/recaptcha/views/form_recaptcha.html.php
@@ -0,0 +1,18 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-recaptcha"></div>
+<script type="text/javascript" src="<?= request::protocol() ?>://www.google.com/recaptcha/api/js/recaptcha_ajax.js">
+</script>
+<script type="text/javascript">
+  setTimeout(function() {
+    Recaptcha.create(
+      "<?= $public_key ?>",
+      "g-recaptcha",
+      {
+        theme: "white",
+        custom_translations : { instructions_visual : <?= t("Type words to check:")->for_js() ?>},
+        callback: Recaptcha.focus_response_field
+      }
+    );
+  }, 500);
+</script>
+
diff --git a/modules/rest/controllers/rest.php b/modules/rest/controllers/rest.php
new file mode 100644
index 0000000..b3d59e0
--- /dev/null
+++ b/modules/rest/controllers/rest.php
@@ -0,0 +1,121 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Rest_Controller extends Controller {
+  const ALLOW_PRIVATE_GALLERY = true;
+
+  public function index() {
+    $username = Input::instance()->post("user");
+    $password = Input::instance()->post("password");
+
+    if (empty($username) || auth::too_many_failures($username)) {
+      throw new Rest_Exception("Forbidden", 403);
+    }
+
+    $user = identity::lookup_user_by_name($username);
+    if (empty($user) || !identity::is_correct_password($user, $password)) {
+      module::event("user_login_failed", $username);
+      throw new Rest_Exception("Forbidden", 403);
+    }
+
+    auth::login($user);
+
+    rest::reply(rest::access_key());
+  }
+
+  public function reset_api_key_confirm() {
+    $form = new Forge("rest/reset_api_key", "", "post", array("id" => "g-reset-api-key"));
+    $group = $form->group("confirm_reset")->label(t("Confirm resetting your REST API key"));
+    $group->submit("")->value(t("Reset"));
+    $v = new View("reset_api_key_confirm.html");
+    $v->form = $form;
+    print $v;
+  }
+
+  public function reset_api_key() {
+    access::verify_csrf();
+    rest::reset_access_key();
+    message::success(t("Your REST API key has been reset."));
+    json::reply(array("result" => "success"));
+  }
+
+  public function __call($function, $args) {
+    try {
+      $input = Input::instance();
+      $request = new stdClass();
+
+      switch ($method = strtolower($input->server("REQUEST_METHOD"))) {
+      case "get":
+        $request->params = (object) $input->get();
+        break;
+
+      default:
+        $request->params = (object) $input->post();
+        if (isset($_FILES["file"])) {
+          $request->file = upload::save("file");
+          system::delete_later($request->file);
+        }
+        break;
+      }
+
+      if (isset($request->params->entity)) {
+        $request->params->entity = json_decode($request->params->entity);
+      }
+      if (isset($request->params->members)) {
+        $request->params->members = json_decode($request->params->members);
+      }
+
+      $request->method = strtolower($input->server("HTTP_X_GALLERY_REQUEST_METHOD", $method));
+      $request->access_key = $input->server("HTTP_X_GALLERY_REQUEST_KEY");
+
+      if (empty($request->access_key) && !empty($request->params->access_key)) {
+        $request->access_key = $request->params->access_key;
+      }
+
+      $request->url = url::abs_current(true);
+      if ($suffix = Kohana::config('core.url_suffix')) {
+        $request->url = substr($request->url, 0, strlen($request->url) - strlen($suffix));
+      }
+
+      rest::set_active_user($request->access_key);
+
+      $handler_class = "{$function}_rest";
+      $handler_method = $request->method;
+
+      if (!class_exists($handler_class) || !method_exists($handler_class, $handler_method)) {
+        throw new Rest_Exception("Bad Request", 400);
+      }
+
+      $response = call_user_func(array($handler_class, $handler_method), $request);
+      if ($handler_method == "post") {
+        // post methods must return a response containing a URI.
+        header("HTTP/1.1 201 Created");
+        header("Location: {$response['url']}");
+      }
+      rest::reply($response);
+    } catch (ORM_Validation_Exception $e) {
+      // Note: this is totally insufficient because it doesn't take into account localization.  We
+      // either need to map the result values to localized strings in the application code, or every
+      // client needs its own l10n string set.
+      throw new Rest_Exception("Bad Request", 400, $e->validation->errors());
+    } catch (Kohana_404_Exception $e) {
+      throw new Rest_Exception("Not Found", 404);
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/rest/helpers/registry_rest.php b/modules/rest/helpers/registry_rest.php
new file mode 100644
index 0000000..2b4087a
--- /dev/null
+++ b/modules/rest/helpers/registry_rest.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class registry_rest_Core {
+  static function get($request) {
+    $results = array();
+    foreach (module::active() as $module) {
+      foreach (glob(MODPATH . "{$module->name}/helpers/*_rest.php") as $filename) {
+        $results[] = str_replace("_rest.php", "", basename($filename));
+      }
+    }
+    return array_unique($results);
+  }
+}
diff --git a/modules/rest/helpers/rest.php b/modules/rest/helpers/rest.php
new file mode 100644
index 0000000..c6be1e1
--- /dev/null
+++ b/modules/rest/helpers/rest.php
@@ -0,0 +1,191 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class rest_Core {
+  const API_VERSION = "3.0";
+
+  static function reply($data=array()) {
+    Session::instance()->abort_save();
+
+    header("X-Gallery-API-Version: " . rest::API_VERSION);
+    switch (Input::instance()->get("output", "json")) {
+    case "json":
+      json::reply($data);
+      break;
+
+    case "jsonp":
+      if (!($callback = Input::instance()->get("callback", ""))) {
+        throw new Rest_Exception(
+          "Bad Request", 400, array("errors" => array("callback" => "missing")));
+      }
+
+      if (preg_match('/^[$A-Za-z_][0-9A-Za-z_]*$/', $callback) == 1) {
+        header("Content-type: application/javascript; charset=UTF-8");
+        print "$callback(" . json_encode($data) . ")";
+      } else {
+        throw new Rest_Exception(
+          "Bad Request", 400, array("errors" => array("callback" => "invalid")));
+      }
+      break;
+
+    case "html":
+      header("Content-type: text/html; charset=UTF-8");
+      if ($data) {
+        $html = preg_replace(
+          "#([\w]+?://[\w]+[^ \'\"\n\r\t<]*)#ise", "'<a href=\"\\1\" >\\1</a>'",
+          var_export($data, 1));
+      } else {
+        $html = t("Empty response");
+      }
+      print "<pre>$html</pre>";
+      if (gallery::show_profiler()) {
+        Profiler::enable();
+        $profiler = new Profiler();
+        $profiler->render();
+      }
+      break;
+
+    default:
+      throw new Rest_Exception("Bad Request", 400);
+    }
+  }
+
+  static function set_active_user($access_key) {
+    if (empty($access_key)) {
+      if (module::get_var("rest", "allow_guest_access")) {
+        identity::set_active_user(identity::guest());
+        return;
+      } else {
+        throw new Rest_Exception("Forbidden", 403);
+      }
+    }
+
+    $key = ORM::factory("user_access_key")
+      ->where("access_key", "=", $access_key)
+      ->find();
+
+    if (!$key->loaded()) {
+      throw new Rest_Exception("Forbidden", 403);
+    }
+
+    $user = identity::lookup_user($key->user_id);
+    if (empty($user)) {
+      throw new Rest_Exception("Forbidden", 403);
+    }
+
+    identity::set_active_user($user);
+  }
+
+  static function reset_access_key() {
+    $key = ORM::factory("user_access_key")
+      ->where("user_id", "=", identity::active_user()->id)
+      ->find();
+    if ($key->loaded()) {
+      $key->delete();
+    }
+    return rest::access_key();
+  }
+
+  static function access_key() {
+    $key = ORM::factory("user_access_key")
+      ->where("user_id", "=", identity::active_user()->id)
+      ->find();
+
+    if (!$key->loaded()) {
+      $key->user_id = identity::active_user()->id;
+      $key->access_key = md5(random::hash() . access::private_key());
+      $key->save();
+    }
+
+    return $key->access_key;
+  }
+
+  /**
+   * Convert a REST url into an object.
+   * Eg:
+   *   http://example.com/gallery3/index.php/rest/item/35          -> Item_Model
+   *   http://example.com/gallery3/index.php/rest/tag/16           -> Tag_Model
+   *   http://example.com/gallery3/index.php/rest/tagged_item/1,16 -> [Tag_Model, Item_Model]
+   *
+   * @param string  the fully qualified REST url
+   * @return mixed  the corresponding object (usually a model of some kind)
+   */
+  static function resolve($url) {
+    if ($suffix = Kohana::config('core.url_suffix')) {
+      $relative_url = substr($url, strlen(url::abs_site("rest")) - strlen($suffix));
+    } else {
+      $relative_url = substr($url, strlen(url::abs_site("rest")));
+    }
+
+    $path = parse_url($relative_url, PHP_URL_PATH);
+    $components = explode("/", $path, 3);
+
+    if (count($components) != 3) {
+      throw new Kohana_404_Exception($url);
+    }
+
+    $class = "$components[1]_rest";
+    if (!class_exists($class) || !method_exists($class, "resolve")) {
+      throw new Kohana_404_Exception($url);
+    }
+
+    return call_user_func(array($class, "resolve"), !empty($components[2]) ? $components[2] : null);
+  }
+
+  /**
+   * Return an absolute url used for REST resource location.
+   * @param  string  resource type (eg, "item", "tag")
+   * @param  object  resource
+   */
+  static function url() {
+    $args = func_get_args();
+    $resource_type = array_shift($args);
+
+    $class = "{$resource_type}_rest";
+    if (!class_exists($class) || !method_exists($class, "url")) {
+      throw new Rest_Exception("Bad Request", 400);
+    }
+
+    $url = call_user_func_array(array($class, "url"), $args);
+    if (Input::instance()->get("output") == "html") {
+      if (strpos($url, "?") === false) {
+        $url .= "?output=html";
+      } else {
+        $url .= "&output=html";
+      }
+    }
+    return $url;
+  }
+
+  static function relationships($resource_type, $resource) {
+    $results = array();
+    foreach (module::active() as $module) {
+      foreach (glob(MODPATH . "{$module->name}/helpers/*_rest.php") as $filename) {
+        $class = str_replace(".php", "", basename($filename));
+        if (class_exists($class) && method_exists($class, "relationships")) {
+          if ($tmp = call_user_func(array($class, "relationships"), $resource_type, $resource)) {
+            $results = array_merge($results, $tmp);
+          }
+        }
+      }
+    }
+
+    return $results;
+  }
+}
diff --git a/modules/rest/helpers/rest_event.php b/modules/rest/helpers/rest_event.php
new file mode 100644
index 0000000..991e2b6
--- /dev/null
+++ b/modules/rest/helpers/rest_event.php
@@ -0,0 +1,102 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class rest_event {
+  /**
+   * Called just before a user is deleted. This will remove the user from
+   * the user_homes directory.
+   */
+  static function user_before_delete($user) {
+    db::build()
+      ->delete("user_access_keys")
+       ->where("id", "=", $user->id)
+       ->execute();
+  }
+
+
+  static function change_provider($new_provider) {
+    db::build()
+      ->delete("user_access_keys")
+      ->execute();
+  }
+
+  /**
+   * Called after a user has been added.  Just add a remote access key
+   * on every add.
+   */
+  static function user_add_form_admin_completed($user, $form) {
+    $key = ORM::factory("user_access_key");
+    $key->user_id = $user->id;
+    $key->access_key = random::hash();
+    $key->save();
+  }
+
+  /**
+   * Called when admin is editing a user
+   */
+  static function user_edit_form_admin($user, $form) {
+    self::_get_access_key_form($user, $form);
+  }
+
+  /**
+   * Get the form fields for user edit
+   */
+  static function _get_access_key_form($user, $form) {
+    $key = ORM::factory("user_access_key")
+      ->where("user_id", "=", $user->id)
+      ->find();
+
+    if (!$key->loaded()) {
+      $key->user_id = $user->id;
+      $key->access_key = random::hash();
+      $key->save();
+    }
+
+    $form->edit_user->input("user_access_key")
+      ->value($key->access_key)
+      ->readonly("readonly")
+      ->class("g-form-static")
+      ->label(t("Remote access key"));
+  }
+
+  static function show_user_profile($data) {
+    // Guests can't see a REST key
+    if (identity::active_user()->guest) {
+      return;
+    }
+
+    // Only logged in users can see their own REST key
+    if (identity::active_user()->id != $data->user->id) {
+      return;
+    }
+
+    $view = new View("user_profile_rest.html");
+    $key = ORM::factory("user_access_key")
+      ->where("user_id", "=", $data->user->id)
+      ->find();
+
+    if (!$key->loaded()) {
+      $key->user_id = $data->user->id;
+      $key->access_key = random::hash();
+      $key->save();
+    }
+    $view->rest_key = $key->access_key;
+    $data->content[] = (object)array("title" => t("REST API"), "view" => $view);
+  }
+}
diff --git a/modules/rest/helpers/rest_installer.php b/modules/rest/helpers/rest_installer.php
new file mode 100644
index 0000000..96f8acf
--- /dev/null
+++ b/modules/rest/helpers/rest_installer.php
@@ -0,0 +1,52 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class rest_installer {
+  static function install() {
+    Database::instance()
+      ->query("CREATE TABLE {user_access_keys} (
+                `id` int(9) NOT NULL auto_increment,
+                `user_id` int(9) NOT NULL,
+                `access_key` char(32) NOT NULL,
+                PRIMARY KEY (`id`),
+                UNIQUE KEY(`access_key`),
+                UNIQUE KEY(`user_id`))
+              DEFAULT CHARSET=utf8;");
+    module::set_var("rest", "allow_guest_access", false);
+  }
+
+  static function upgrade($version) {
+    $db = Database::instance();
+    if ($version == 1) {
+      if (in_array("user_access_tokens", Database::instance()->list_tables())) {
+        $db->query("RENAME TABLE {user_access_tokens} TO {user_access_keys}");
+      }
+      module::set_version("rest", $version = 2);
+    }
+
+    if ($version == 2) {
+      module::set_var("rest", "allow_guest_access", false);
+      module::set_version("rest", $version = 3);
+    }
+  }
+
+  static function uninstall() {
+    Database::instance()->query("DROP TABLE IF EXISTS {user_access_keys}");
+  }
+}
diff --git a/modules/rest/libraries/Rest_Exception.php b/modules/rest/libraries/Rest_Exception.php
new file mode 100644
index 0000000..bd08aa8
--- /dev/null
+++ b/modules/rest/libraries/Rest_Exception.php
@@ -0,0 +1,37 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Rest_Exception_Core extends Kohana_Exception {
+  var $response = array();
+
+  public function __construct($message, $code, $response=array()) {
+    parent::__construct($message, null, $code);
+    $this->response = $response;
+  }
+
+  public function sendHeaders() {
+    if (!headers_sent()) {
+      header("HTTP/1.1 " . $this->getCode() . " " . $this->getMessage());
+    }
+  }
+
+  public function getTemplate() {
+    return "error_rest.json";
+  }
+}
\ No newline at end of file
diff --git a/modules/rest/models/user_access_key.php b/modules/rest/models/user_access_key.php
new file mode 100644
index 0000000..d464380
--- /dev/null
+++ b/modules/rest/models/user_access_key.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class User_Access_Key_Model_Core extends ORM {
+}
diff --git a/modules/rest/module.info b/modules/rest/module.info
new file mode 100644
index 0000000..93a7873
--- /dev/null
+++ b/modules/rest/module.info
@@ -0,0 +1,8 @@
+name = "REST API Module"
+description = "A REST-based API that allows desktop clients and other apps to interact with Gallery 3"
+
+version = 3
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:rest"
+discuss_url = "http://galleryproject.org/forum_module_rest"
diff --git a/modules/rest/views/error_rest.json.php b/modules/rest/views/error_rest.json.php
new file mode 100644
index 0000000..8c99ef4
--- /dev/null
+++ b/modules/rest/views/error_rest.json.php
@@ -0,0 +1,6 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?
+// Log error response to ease debugging
+Kohana_Log::add("error", "Rest error details: " . print_r($e->response, 1));
+?>
+<?= json_encode($e->response);
\ No newline at end of file
diff --git a/modules/rest/views/reset_api_key_confirm.html.php b/modules/rest/views/reset_api_key_confirm.html.php
new file mode 100644
index 0000000..3aae2a9
--- /dev/null
+++ b/modules/rest/views/reset_api_key_confirm.html.php
@@ -0,0 +1,7 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-rest-reset-api-key" class="ui-helper-clearfix">
+  <p>
+    <?= t("Do you really want to reset your REST API key?  Any clients that use this key will need to be updated with the new value.") ?>
+  </p>
+  <?= $form ?>
+</div>
diff --git a/modules/rest/views/user_profile_rest.html.php b/modules/rest/views/user_profile_rest.html.php
new file mode 100644
index 0000000..3e5d3db
--- /dev/null
+++ b/modules/rest/views/user_profile_rest.html.php
@@ -0,0 +1,13 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-rest-detail">
+  <ul>
+    <li id="g-rest-key">
+      <p>
+        <?= t("<b>Key</b>: %key", array("key" => $rest_key)) ?>
+        <a class="g-button ui-state-default ui-corner-all g-dialog-link" href="<?= url::site("rest/reset_api_key_confirm") ?>">
+          <?= t("reset") ?>
+        </a>
+      </p>
+    </li>
+  </ul>
+</div>
diff --git a/modules/rss/controllers/rss.php b/modules/rss/controllers/rss.php
new file mode 100644
index 0000000..571995b
--- /dev/null
+++ b/modules/rss/controllers/rss.php
@@ -0,0 +1,66 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Rss_Controller extends Controller {
+  public static $page_size = 20;
+
+  public function feed($module_id, $feed_id, $id=null) {
+    $page = (int) Input::instance()->get("page", 1);
+    if ($page < 1) {
+      url::redirect(url::merge(array("page" => 1)));
+    }
+
+    // Configurable page size between 1 and 100, default 20
+    $page_size = max(1, min(100, (int) Input::instance()->get("page_size", self::$page_size)));
+
+    // Run the appropriate feed callback
+    if (module::is_active($module_id)) {
+      $class_name = "{$module_id}_rss";
+      if (class_exists($class_name) && method_exists($class_name, "feed")) {
+        $feed = call_user_func(
+          array($class_name, "feed"), $feed_id,
+          ($page - 1) * $page_size, $page_size, $id);
+      }
+    }
+    if (empty($feed)) {
+      throw new Kohana_404_Exception();
+    }
+
+    if ($feed->max_pages && $page > $feed->max_pages) {
+      url::redirect(url::merge(array("page" => $feed->max_pages)));
+    }
+
+    $view = new View(empty($feed->view) ? "feed.mrss" : $feed->view);
+    unset($feed->view);
+
+    $view->feed = $feed;
+    $view->pub_date = date("D, d M Y H:i:s O");
+
+    $feed->uri = url::abs_site(url::merge($_GET));
+    if ($page > 1) {
+      $feed->previous_page_uri = url::abs_site(url::merge(array("page" => $page - 1)));
+    }
+    if ($page < $feed->max_pages) {
+      $feed->next_page_uri = url::abs_site(url::merge(array("page" => $page + 1)));
+    }
+
+    header("Content-Type: application/rss+xml");
+    print $view;
+  }
+}
\ No newline at end of file
diff --git a/modules/rss/helpers/rss.php b/modules/rss/helpers/rss.php
new file mode 100644
index 0000000..d6e60f1
--- /dev/null
+++ b/modules/rss/helpers/rss.php
@@ -0,0 +1,36 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class rss_Core {
+  /**
+   * Convert a rss feed id into a rss feed url.
+   */
+  static function url($uri) {
+    return url::site("rss/feed/$uri");
+  }
+
+  /**
+   * Return a <link> element for a given rss feed id.
+   */
+  static function feed_link($uri) {
+    $url = url::site("rss/feed/$uri");
+    return "<link rel=\"alternate\" type=\"application/rss+xml\" href=\"$url\" />";
+  }
+}
\ No newline at end of file
diff --git a/modules/rss/helpers/rss_block.php b/modules/rss/helpers/rss_block.php
new file mode 100644
index 0000000..9a77b05
--- /dev/null
+++ b/modules/rss/helpers/rss_block.php
@@ -0,0 +1,49 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class rss_block_Core {
+  static function get_site_list() {
+    return array("rss_feeds" => t("Available RSS feeds"));
+  }
+
+  static function get($block_id, $theme) {
+    $block = "";
+    switch ($block_id) {
+    case "rss_feeds":
+      $feeds = array();
+      foreach (module::active() as $module) {
+        $class_name = "{$module->name}_rss";
+        if (class_exists($class_name) && method_exists($class_name, "available_feeds")) {
+          $feeds = array_merge($feeds,
+            call_user_func(array($class_name, "available_feeds"), $theme->item(), $theme->tag()));
+        }
+      }
+      if (!empty($feeds)) {
+        $block = new Block();
+        $block->css_id = "g-rss";
+        $block->title = t("Available RSS feeds");
+        $block->content = new View("rss_block.html");
+        $block->content->feeds = $feeds;
+      }
+      break;
+    }
+
+    return $block;
+  }
+}
diff --git a/modules/rss/module.info b/modules/rss/module.info
new file mode 100644
index 0000000..5f32387
--- /dev/null
+++ b/modules/rss/module.info
@@ -0,0 +1,7 @@
+name = "RSS"
+description = "Provides RSS feeds"
+version = 1
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:rss"
+discuss_url = "http://galleryproject.org/forum_module_rss"
diff --git a/modules/rss/views/feed.mrss.php b/modules/rss/views/feed.mrss.php
new file mode 100644
index 0000000..b609a54
--- /dev/null
+++ b/modules/rss/views/feed.mrss.php
@@ -0,0 +1,79 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? echo '<?xml version="1.0" ?>' ?>
+<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"
+   xmlns:atom="http://www.w3.org/2005/Atom"
+   xmlns:content="http://purl.org/rss/1.0/modules/content/"
+   xmlns:fh="http://purl.org/syndication/history/1.0">
+  <channel>
+    <generator>gallery3</generator>
+    <title><?= html::clean($feed->title) ?></title>
+    <link><?= $feed->uri ?></link>
+    <description><?= html::clean($feed->description) ?></description>
+    <language>en-us</language>
+    <atom:link rel="self" href="<?= $feed->uri ?>" type="application/rss+xml" />
+    <fh:complete/>
+    <? if (!empty($feed->previous_page_uri)): ?>
+    <atom:link rel="previous" href="<?= $feed->previous_page_uri ?>" type="application/rss+xml" />
+    <? endif ?>
+    <? if (!empty($feed->next_page_uri)): ?>
+    <atom:link rel="next" href="<?= $feed->next_page_uri ?>" type="application/rss+xml" />
+    <? endif ?>
+    <pubDate><?= $pub_date ?></pubDate>
+    <lastBuildDate><?= $pub_date ?></lastBuildDate>
+    <? foreach ($feed->items as $item): ?>
+    <item>
+      <title><?= html::purify($item->title) ?></title>
+      <link><?= url::abs_site("{$item->type}s/{$item->id}") ?></link>
+      <guid isPermaLink="true"><?= url::abs_site("{$item->type}s/{$item->id}") ?></guid>
+      <pubDate><?= date("D, d M Y H:i:s O", $item->created); ?></pubDate>
+      <description><?= html::purify($item->description) ?></description>
+      <content:encoded>
+        <![CDATA[
+          <span><?= html::purify($item->description) ?></span>
+          <p>
+          <? if ($item->type == "photo"): ?>
+            <img alt="" src="<?= $item->resize_url(true) ?>"
+                 title="<?= html::purify($item->title)->for_html_attr() ?>"
+                 height="<?= $item->resize_height ?>" width="<?= $item->resize_width ?>" /><br />
+          <? else: ?>
+            <a href="<?= url::abs_site("{$item->type}s/{$item->id}") ?>">
+            <img alt="" src="<?= $item->thumb_url(true) ?>"
+                 title="<?= html::purify($item->title)->for_html_attr() ?>"
+                 height="<?= $item->thumb_height ?>" width="<?= $item->thumb_width ?>" /></a><br />
+          <? endif ?>
+            <?= html::purify($item->description) ?>
+          </p>
+        ]]>
+      </content:encoded>
+      <media:thumbnail url="<?= $item->thumb_url(true) ?>"
+                       height="<?= $item->thumb_height ?>"
+                       width="<?= $item->thumb_width ?>"
+                       />
+    <? $view_full = access::can("view_full", $item); ?>
+    <? if ($item->type == "photo" && $view_full): ?>
+      <media:group>
+    <? endif ?>
+      <? if ($item->type == "photo"): ?>
+        <media:content url="<?= $item->resize_url(true) ?>"
+                       fileSize="<?= @filesize($item->resize_path()) ?>"
+                       type="<?= $item->mime_type ?>"
+                       height="<?= $item->resize_height ?>"
+                       width="<?= $item->resize_width ?>"
+                       />
+      <? endif ?>
+      <? if ($view_full): ?>
+        <media:content url="<?= $item->file_url(true) ?>"
+                       fileSize="<?= @filesize($item->file_path()) ?>"
+                       type="<?= $item->mime_type ?>"
+                       height="<?= $item->height ?>"
+                       width="<?= $item->width ?>"
+                       isDefault="true"
+                       />
+      <? endif ?>
+    <? if ($item->type == "photo" && $view_full): ?>
+      </media:group>
+    <? endif ?>
+    </item>
+    <? endforeach ?>
+  </channel>
+</rss>
diff --git a/modules/rss/views/rss_block.html.php b/modules/rss/views/rss_block.html.php
new file mode 100644
index 0000000..210c72a
--- /dev/null
+++ b/modules/rss/views/rss_block.html.php
@@ -0,0 +1,13 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul id="g-feeds">
+<? foreach($feeds as $url => $title): ?>
+  <li style="clear: both;">
+    <span class="ui-icon-left">
+    <a href="<?= rss::url($url) ?>">
+      <span class="ui-icon ui-icon-signal-diag"></span>
+      <?= html::purify($title) ?>
+    </a>
+    </span>
+  </li>
+<? endforeach ?>
+</ul>
diff --git a/modules/search/controllers/search.php b/modules/search/controllers/search.php
new file mode 100644
index 0000000..753d9b6
--- /dev/null
+++ b/modules/search/controllers/search.php
@@ -0,0 +1,123 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Search_Controller extends Controller {
+  public function index() {
+    $page_size = module::get_var("gallery", "page_size", 9);
+    $q = Input::instance()->get("q");
+    $q_with_more_terms = search::add_query_terms($q);
+    $show = Input::instance()->get("show");
+
+    $album_id = Input::instance()->get("album", item::root()->id);
+    $album = ORM::factory("item", $album_id);
+    if (!access::can("view", $album) || !$album->is_album()) {
+      $album = item::root();
+    }
+
+    if ($show) {
+      $child = ORM::factory("item", $show);
+      $index = search::get_position_within_album($child, $q_with_more_terms, $album);
+      if ($index) {
+        $page = ceil($index / $page_size);
+        url::redirect(url::abs_site("search" .
+          "?q=" . urlencode($q) .
+          "&album=" . urlencode($album->id) .
+          ($page == 1 ? "" : "&page=$page")));
+      }
+    }
+
+    $page = Input::instance()->get("page", 1);
+
+    // Make sure that the page references a valid offset
+    if ($page < 1) {
+      $page = 1;
+    }
+
+    $offset = ($page - 1) * $page_size;
+
+    list ($count, $result) =
+      search::search_within_album($q_with_more_terms, $album, $page_size, $offset);
+
+    $max_pages = max(ceil($count / $page_size), 1);
+
+    $template = new Theme_View("page.html", "collection", "search");
+    $root = item::root();
+    $template->set_global(
+      array("page" => $page,
+            "max_pages" => $max_pages,
+            "page_size" => $page_size,
+            "breadcrumbs" => array(
+              Breadcrumb::instance($root->title, $root->url())->set_first(),
+              Breadcrumb::instance($q, url::abs_site("search?q=" . urlencode($q)))->set_last(),
+            ),
+            "children_count" => $count));
+
+    $template->content = new View("search.html");
+    $template->content->album = $album;
+    $template->content->items = $result;
+    $template->content->q = $q;
+
+    print $template;
+
+    item::set_display_context_callback("Search_Controller::get_display_context", $album, $q);
+  }
+
+  static function get_display_context($item, $album, $q) {
+    $q_with_more_terms = search::add_query_terms($q);
+    $position = search::get_position_within_album($item, $q_with_more_terms, $album);
+
+    if ($position > 1) {
+      list ($count, $result_data) =
+        search::search_within_album($q_with_more_terms, $album, 3, $position - 2);
+      list ($previous_item, $ignore, $next_item) = $result_data;
+    } else {
+      $previous_item = null;
+      list ($count, $result_data) =
+        search::search_within_album($q_with_more_terms, $album, 1, $position);
+      list ($next_item) = $result_data;
+    }
+
+    $search_url = url::abs_site("search" .
+      "?q=" . urlencode($q) .
+      "&album=" . urlencode($album->id) .
+      "&show={$item->id}");
+    $root = item::root();
+
+    return array("position" => $position,
+                 "previous_item" => $previous_item,
+                 "next_item" => $next_item,
+                 "sibling_count" => $count,
+                 "siblings_callback" => array("Search_Controller::get_siblings", array($q, $album)),
+                 "breadcrumbs" => array(
+                   Breadcrumb::instance($root->title, $root->url())->set_first(),
+                   Breadcrumb::instance(t("Search: %q", array("q" => $q)), $search_url),
+                   Breadcrumb::instance($item->title, $item->url())->set_last()));
+  }
+
+  static function get_siblings($q, $album, $limit, $offset) {
+    if (!isset($limit)) {
+      $limit = 100;
+    }
+    if (!isset($offset)) {
+      $offset = 1;
+    }
+    $result = search::search_within_album(search::add_query_terms($q), $album, $limit, $offset);
+    return $result[1];
+  }
+}
diff --git a/modules/search/helpers/search.php b/modules/search/helpers/search.php
new file mode 100644
index 0000000..c84b70b
--- /dev/null
+++ b/modules/search/helpers/search.php
@@ -0,0 +1,163 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class search_Core {
+  /**
+   * Add more terms to the query by wildcarding the stem value of the first
+   * few terms in the query.
+   */
+  static function add_query_terms($q) {
+    $MAX_TERMS = 5;
+    $terms = explode(" ", $q, $MAX_TERMS);
+    for ($i = 0; $i < min(count($terms), $MAX_TERMS - 1); $i++) {
+      // Don't wildcard quoted or already wildcarded terms
+      if ((substr($terms[$i], 0, 1) != '"') && (substr($terms[$i], -1, 1) != "*")) {
+        $terms[] = rtrim($terms[$i], "s") . "*";
+      }
+    }
+    return implode(" ", $terms);
+  }
+
+  static function search($q, $limit, $offset) {
+    return search::search_within_album($q, item::root(), $limit, $offset);
+  }
+
+  static function search_within_album($q, $album, $limit, $offset) {
+    $db = Database::instance();
+
+    $query = self::_build_query_base($q, $album) .
+      " ORDER BY `score` DESC" .
+      " LIMIT $limit OFFSET " . (int)$offset;
+
+    $data = $db->query($query);
+    $count = $db->query("SELECT FOUND_ROWS() as c")->current()->c;
+
+    return array($count, new ORM_Iterator(ORM::factory("item"), $data));
+  }
+
+  private static function _build_query_base($q, $album, $where=array()) {
+    $db = Database::instance();
+    $q = $db->escape($q);
+
+    if (!identity::active_user()->admin) {
+      foreach (identity::group_ids_for_active_user() as $id) {
+        $fields[] = "`view_$id` = TRUE"; // access::ALLOW
+      }
+      $access_sql = " AND (" . join(" OR ", $fields) . ")";
+    } else {
+      $access_sql = "";
+    }
+
+    if ($album->id == item::root()->id) {
+      $album_sql = "";
+    } else {
+      $album_sql =
+        " AND {items}.left_ptr > " . $db->escape($album->left_ptr) .
+        " AND {items}.right_ptr <= " . $db->escape($album->right_ptr);
+    }
+
+    return
+      "SELECT SQL_CALC_FOUND_ROWS {items}.*, " .
+      "  MATCH({search_records}.`data`) AGAINST ('$q') AS `score` " .
+      "FROM {items} JOIN {search_records} ON ({items}.`id` = {search_records}.`item_id`) " .
+      "WHERE MATCH({search_records}.`data`) AGAINST ('$q' IN BOOLEAN MODE)" .
+      $album_sql .
+      (empty($where) ? "" : " AND " . join(" AND ", $where)) .
+      $access_sql;
+  }
+
+  /**
+   * @return string An error message suitable for inclusion in the task log
+   */
+  static function check_index() {
+    list ($remaining) = search::stats();
+    if ($remaining) {
+      site_status::warning(
+        t('Your search index needs to be updated.  <a href="%url" class="g-dialog-link">Fix this now</a>',
+          array("url" => html::mark_clean(url::site("admin/maintenance/start/search_task::update_index?csrf=__CSRF__")))),
+        "search_index_out_of_date");
+    }
+  }
+
+  static function update($item) {
+    $data = new ArrayObject();
+    $record = ORM::factory("search_record")->where("item_id", "=", $item->id)->find();
+    if (!$record->loaded()) {
+      $record->item_id = $item->id;
+    }
+
+    $item = $record->item();
+    module::event("item_index_data", $item, $data);
+    $record->data = join(" ", (array)$data);
+    $record->dirty = 0;
+    $record->save();
+  }
+
+  static function stats() {
+    $remaining = db::build()
+      ->from("items")
+      ->join("search_records", "items.id", "search_records.item_id", "left")
+      ->and_open()
+      ->where("search_records.item_id", "IS", null)
+      ->or_where("search_records.dirty", "=", 1)
+      ->close()
+      ->count_records();
+
+    $total = ORM::factory("item")->count_all();
+    $percent = round(100 * ($total - $remaining) / $total);
+
+    return array($remaining, $total, $percent);
+  }
+
+  static function get_position($item, $q) {
+    return search::get_position_within_album($item, $q, item::root());
+  }
+
+  static function get_position_within_album($item, $q, $album) {
+    $page_size = module::get_var("gallery", "page_size", 9);
+    $query = self::_build_query_base($q, $album, array("{items}.id = " . $item->id)) .
+      " ORDER BY `score` DESC";
+    $db = Database::instance();
+
+    // Truncate the score by two decimal places as this resolves the issues
+    // that arise due to inexact numeric conversions.
+    $current = $db->query($query)->current();
+    if (!$current) {
+      // We can't find this result in our result set - perhaps we've fallen out of context?  Clear
+      // the context and try again.
+      item::clear_display_context_callback();
+      url::redirect(url::current());
+    }
+    $score = $current->score;
+    if (strlen($score) > 7) {
+      $score = substr($score, 0, strlen($score) - 2);
+    }
+
+    // Redo the query but only look for results greater than or equal to our current location
+    // then seek backwards until we find our item.
+    $data = $db->query(self::_build_query_base($q, $album) . " HAVING `score` >= " . $score .
+                       " ORDER BY `score` DESC");
+    $data->seek($data->count() - 1);
+
+    while ($data->get("id") != $item->id && $data->prev()->valid()) {
+    }
+
+    return $data->key() + 1;
+  }
+}
diff --git a/modules/search/helpers/search_event.php b/modules/search/helpers/search_event.php
new file mode 100644
index 0000000..a20935b
--- /dev/null
+++ b/modules/search/helpers/search_event.php
@@ -0,0 +1,39 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class search_event_Core {
+  static function item_created($item) {
+    search::update($item);
+  }
+
+  static function item_updated($original, $new) {
+    search::update($new);
+  }
+
+  static function item_deleted($item) {
+    db::build()
+      ->delete("search_records")
+      ->where("item_id", "=", $item->id)
+      ->execute();
+  }
+
+  static function item_related_update($item) {
+    search::update($item);
+  }
+}
diff --git a/modules/search/helpers/search_installer.php b/modules/search/helpers/search_installer.php
new file mode 100644
index 0000000..c9e8f26
--- /dev/null
+++ b/modules/search/helpers/search_installer.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class search_installer {
+  static function install() {
+    $db = Database::instance();
+    $db->query("CREATE TABLE {search_records} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `item_id` int(9),
+                 `dirty` boolean default 1,
+                 `data` LONGTEXT default NULL,
+                 PRIMARY KEY (`id`),
+                 KEY(`item_id`),
+                 FULLTEXT INDEX (`data`))
+               ENGINE=MyISAM
+               DEFAULT CHARSET=utf8;");
+  }
+
+  static function activate() {
+    // Update the root item.  This is a quick hack because the search module is activated as part
+    // of the official install, so this way we don't start off with a "your index is out of date"
+    // banner.
+    search::update(model_cache::get("item", 1));
+    search::check_index();
+  }
+
+  static function deactivate() {
+    site_status::clear("search_index_out_of_date");
+  }
+
+  static function uninstall() {
+    Database::instance()->query("DROP TABLE {search_records}");
+  }
+}
diff --git a/modules/search/helpers/search_task.php b/modules/search/helpers/search_task.php
new file mode 100644
index 0000000..18348a2
--- /dev/null
+++ b/modules/search/helpers/search_task.php
@@ -0,0 +1,84 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class search_task_Core {
+  static function available_tasks() {
+    // Delete extra search_records
+    db::build()
+      ->delete("search_records")
+      ->where("item_id", "NOT IN", db::build()->select("id")->from("items"))
+      ->execute();
+
+    list ($remaining, $total, $percent) = search::stats();
+    return array(Task_Definition::factory()
+                 ->callback("search_task::update_index")
+                 ->name(t("Update Search Index"))
+                 ->description(
+                   $remaining
+                   ? t2("1 photo or album needs to be scanned",
+                        "%count (%percent%) of your photos and albums need to be scanned",
+                        $remaining, array("percent" => (100 - $percent)))
+                   : t("Search data is up-to-date"))
+                 ->severity($remaining ? log::WARNING : log::SUCCESS));
+  }
+
+  static function update_index($task) {
+    try {
+      $completed = $task->get("completed", 0);
+
+      $start = microtime(true);
+      foreach (ORM::factory("item")
+               ->join("search_records", "items.id", "search_records.item_id", "left")
+               ->where("search_records.item_id", "IS", null)
+               ->or_where("search_records.dirty", "=", 1)
+               ->find_all(100) as $item) {
+        // The query above can take a long time, so start the timer after its done
+        // to give ourselves a little time to actually process rows.
+        if (!isset($start)) {
+          $start = microtime(true);
+        }
+
+        search::update($item);
+        $completed++;
+
+        if (microtime(true) - $start > .75) {
+          break;
+        }
+      }
+
+      list ($remaining, $total, $percent) = search::stats();
+      $task->set("completed", $completed);
+      if ($remaining == 0 || !($remaining + $completed)) {
+        $task->done = true;
+        $task->state = "success";
+        site_status::clear("search_index_out_of_date");
+        $task->percent_complete = 100;
+      } else {
+        $task->percent_complete = round(100 * $completed / ($remaining + $completed));
+      }
+      $task->status = t2("one record updated, index is %percent% up-to-date",
+                         "%count records updated, index is %percent% up-to-date",
+                         $completed, array("percent" => $percent));
+    } catch (Exception $e) {
+      $task->done = true;
+      $task->state = "error";
+      $task->status = $e->getMessage();
+    }
+  }
+}
diff --git a/modules/search/helpers/search_theme.php b/modules/search/helpers/search_theme.php
new file mode 100644
index 0000000..e8735d1
--- /dev/null
+++ b/modules/search/helpers/search_theme.php
@@ -0,0 +1,29 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class search_theme_Core {
+  static function header_top($theme) {
+    if ($theme->page_subtype() != "login") {
+      $view = new View("search_link.html");
+      return $view->render();
+    } else {
+      return "";
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/search/models/search_record.php b/modules/search/models/search_record.php
new file mode 100644
index 0000000..be68e72
--- /dev/null
+++ b/modules/search/models/search_record.php
@@ -0,0 +1,24 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Search_Record_Model_Core extends ORM {
+  function item() {
+    return model_cache::get("item", $this->item_id);
+  }
+}
diff --git a/modules/search/module.info b/modules/search/module.info
new file mode 100644
index 0000000..f1bb1fa
--- /dev/null
+++ b/modules/search/module.info
@@ -0,0 +1,7 @@
+name = "Search"
+description = "Allows users to search their Gallery"
+version = 1
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:search"
+discuss_url = "http://galleryproject.org/forum_module_search"
diff --git a/modules/search/views/search.html.php b/modules/search/views/search.html.php
new file mode 100644
index 0000000..a42c31d
--- /dev/null
+++ b/modules/search/views/search.html.php
@@ -0,0 +1,65 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? // @todo Set hover on AlbumGrid list items ?>
+<form action="<?= url::site("/search") ?>" id="g-search-form" class="g-short-form">
+  <fieldset>
+    <legend>
+      <?= t("Search") ?>
+    </legend>
+    <ul>
+      <li>
+        <? if ($album->id == item::root()->id): ?>
+          <label for="q"><?= t("Search the gallery") ?></label>
+        <? else: ?>
+          <label for="q"><?= t("Search this album") ?></label>
+        <? endif; ?>
+        <input name="album" type="hidden" value="<?= html::clean_attribute($album->id) ?>" />
+        <input name="q" id="q" type="text" value="<?= html::clean_attribute($q) ?>" class="text" />
+      </li>
+      <li>
+        <input type="submit" value="<?= t("Search")->for_html_attr() ?>" class="submit" />
+      </li>
+    </ul>
+  </fieldset>
+</form>
+
+<div id="g-search-results">
+  <h1><?= t("Search results") ?></h1>
+
+  <? if ($album->id == item::root()->id): ?>
+    <div>
+      <?= t("Searched the whole gallery.") ?>
+    </div>
+  <? else: ?>
+    <div>
+      <?= t("Searched within album <b>%album</b>.", array("album" => html::purify($album->title))) ?>
+      <a href="<?= url::site(url::merge(array("album" => item::root()->id))) ?>"><?= t("Search whole gallery") ?></a>
+    </div>
+  <? endif; ?>
+
+  <? if (count($items)): ?>
+  <ul id="g-album-grid" class="ui-helper-clearfix">
+    <? foreach ($items as $item): ?>
+    <? $item_class = $item->is_album() ? "g-album" : "g-photo" ?>
+    <li class="g-item <?= $item_class ?>">
+      <a href="<?= $item->url() ?>">
+        <?= $item->thumb_img(array("class" => "g-thumbnail")) ?>
+        <p>
+          <span class="<?= $item_class ?>"></span>
+          <?= html::purify(text::limit_chars($item->title, 32, "…")) ?>
+        </p>
+        <div>
+          <?= nl2br(html::purify(text::limit_chars($item->description, 64, "…"))) ?>
+        </div>
+      </a>
+    </li>
+    <? endforeach ?>
+  </ul>
+  <?= $theme->paginator() ?>
+
+  <? else: ?>
+  <p>
+    <?= t("No results found for <b>%term</b>", array("term" => $q)) ?>
+  </p>
+
+  <? endif; ?>
+</div>
diff --git a/modules/search/views/search_link.html.php b/modules/search/views/search_link.html.php
new file mode 100644
index 0000000..4f9abc1
--- /dev/null
+++ b/modules/search/views/search_link.html.php
@@ -0,0 +1,22 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<form action="<?= url::site("search") ?>" id="g-quick-search-form" class="g-short-form">
+  <? if (isset($item)): ?>
+    <? $album_id = $item->is_album() ? $item->id : $item->parent_id; ?>
+  <? else: ?>
+    <? $album_id = item::root()->id; ?>
+  <? endif; ?>
+  <ul>
+    <li>
+      <? if ($album_id == item::root()->id): ?>
+        <label for="g-search"><?= t("Search the gallery") ?></label>
+      <? else: ?>
+        <label for="g-search"><?= t("Search this album") ?></label>
+      <? endif; ?>
+      <input type="hidden" name="album" value="<?= $album_id ?>" />
+      <input type="text" name="q" id="g-search" class="text" />
+    </li>
+    <li>
+      <input type="submit" value="<?= t("Go")->for_html_attr() ?>" class="submit" />
+    </li>
+  </ul>
+</form>
diff --git a/modules/server_add/controllers/admin_server_add.php b/modules/server_add/controllers/admin_server_add.php
new file mode 100644
index 0000000..ba2b9b3
--- /dev/null
+++ b/modules/server_add/controllers/admin_server_add.php
@@ -0,0 +1,97 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Server_Add_Controller extends Admin_Controller {
+  public function index() {
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Add from server");
+    $view->content = new View("admin_server_add.html");
+    $view->content->form = $this->_get_admin_form();
+    $paths = unserialize(module::get_var("server_add", "authorized_paths", "a:0:{}"));
+    $view->content->paths = array_keys($paths);
+
+    print $view;
+  }
+
+  public function add_path() {
+    access::verify_csrf();
+
+    $form = $this->_get_admin_form();
+    $paths = unserialize(module::get_var("server_add", "authorized_paths", "a:0:{}"));
+    if ($form->validate()) {
+      $path = html_entity_decode($form->add_path->path->value);
+      if (is_link($path)) {
+        $form->add_path->path->add_error("is_symlink", 1);
+      } else if (!is_readable($path)) {
+        $form->add_path->path->add_error("not_readable", 1);
+      } else {
+        $paths[$path] = 1;
+        module::set_var("server_add", "authorized_paths", serialize($paths));
+        message::success(t("Added path %path", array("path" => $path)));
+        server_add::check_config($paths);
+        url::redirect("admin/server_add");
+      }
+    }
+
+    $view = new Admin_View("admin.html");
+    $view->content = new View("admin_server_add.html");
+    $view->content->form = $form;
+    $view->content->paths = array_keys($paths);
+    print $view;
+  }
+
+  public function remove_path() {
+    access::verify_csrf();
+
+    $path = Input::instance()->get("path");
+    $paths = unserialize(module::get_var("server_add", "authorized_paths"));
+    if (isset($paths[$path])) {
+      unset($paths[$path]);
+      message::success(t("Removed path %path", array("path" => $path)));
+      module::set_var("server_add", "authorized_paths", serialize($paths));
+      server_add::check_config($paths);
+    }
+    url::redirect("admin/server_add");
+  }
+
+  public function autocomplete() {
+    $directories = array();
+
+    $path_prefix = Input::instance()->get("q");
+    foreach (glob("{$path_prefix}*") as $file) {
+      if (is_dir($file) && !is_link($file)) {
+        $directories[] = html::clean($file);
+      }
+    }
+
+    ajax::response(implode("\n", $directories));
+  }
+
+  private function _get_admin_form() {
+    $form = new Forge("admin/server_add/add_path", "", "post",
+                      array("id" => "g-server-add-admin-form", "class" => "g-short-form"));
+    $add_path = $form->group("add_path");
+    $add_path->input("path")->label(t("Path"))->rules("required")->id("g-path")
+      ->error_messages("not_readable", t("This directory is not readable by the webserver"))
+      ->error_messages("is_symlink", t("Symbolic links are not allowed"));
+    $add_path->submit("add")->value(t("Add Path"));
+
+    return $form;
+  }
+}
diff --git a/modules/server_add/controllers/server_add.php b/modules/server_add/controllers/server_add.php
new file mode 100644
index 0000000..f6e0a94
--- /dev/null
+++ b/modules/server_add/controllers/server_add.php
@@ -0,0 +1,315 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Server_Add_Controller extends Admin_Controller {
+  public function browse($id) {
+    $paths = unserialize(module::get_var("server_add", "authorized_paths"));
+    foreach (array_keys($paths) as $path) {
+      $files[] = $path;
+    }
+
+    // Clean leftover task rows.  There really should be support for this in the task framework
+    db::build()
+      ->where("task_id", "NOT IN", db::build()->select("id")->from("tasks"))
+      ->delete("server_add_entries")
+      ->execute();
+
+    $item = ORM::factory("item", $id);
+    $view = new View("server_add_tree_dialog.html");
+    $view->item = $item;
+    $view->tree = new View("server_add_tree.html");
+    $view->tree->files = $files;
+    $view->tree->parents = array();
+    print $view;
+  }
+
+  public function children() {
+    $path = Input::instance()->get("path");
+
+    $tree = new View("server_add_tree.html");
+    $tree->files = array();
+    $tree->parents = array();
+
+    // Make a tree with the parents back up to the authorized path, and all the children under the
+    // current path.
+    if (server_add::is_valid_path($path)) {
+      $tree->parents[] = $path;
+      while (server_add::is_valid_path(dirname($tree->parents[0]))) {
+        array_unshift($tree->parents, dirname($tree->parents[0]));
+      }
+
+      $glob_path = str_replace(array("{", "}", "[", "]"), array("\{", "\}", "\[", "\]"), $path);
+      foreach (glob("$glob_path/*") as $file) {
+        if (!is_readable($file)) {
+          continue;
+        }
+        if (!is_dir($file)) {
+          $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
+          if (!legal_file::get_extensions($ext)) {
+            continue;
+          }
+        }
+
+        $tree->files[] = $file;
+      }
+    } else {
+      // Missing or invalid path; print out the list of authorized path
+      $paths = unserialize(module::get_var("server_add", "authorized_paths"));
+      foreach (array_keys($paths) as $path) {
+        $tree->files[] = $path;
+      }
+    }
+    print $tree;
+  }
+
+  /**
+   * Begin the task of adding photos.
+   */
+  public function start() {
+    access::verify_csrf();
+    $item = ORM::factory("item", Input::instance()->get("item_id"));
+
+    $task_def = Task_Definition::factory()
+      ->callback("Server_Add_Controller::add")
+      ->description(t("Add photos or movies from the local server"))
+      ->name(t("Add from server"));
+    $task = task::create($task_def, array("item_id" => $item->id));
+
+    foreach (Input::instance()->post("paths") as $path) {
+      if (server_add::is_valid_path($path)) {
+        $entry = ORM::factory("server_add_entry");
+        $entry->path = $path;
+        $entry->is_directory = intval(is_dir($path));
+        $entry->parent_id = null;
+        $entry->task_id = $task->id;
+        $entry->save();
+      }
+    }
+
+    json::reply(
+      array("result" => "started",
+            "status" => (string)$task->status,
+            "url" => url::site("server_add/run/$task->id?csrf=" . access::csrf_token())));
+  }
+
+  /**
+   * Run the task of adding photos
+   */
+  function run($task_id) {
+    access::verify_csrf();
+
+    $task = ORM::factory("task", $task_id);
+    if (!$task->loaded() || $task->owner_id != identity::active_user()->id) {
+      access::forbidden();
+    }
+
+    $task = task::run($task_id);
+    // Prevent the JavaScript code from breaking by forcing a period as
+    // decimal separator for all locales with sprintf("%F", $value).
+    json::reply(array("done" => (bool)$task->done,
+                      "status" => (string)$task->status,
+                      "percent_complete" => sprintf("%F", $task->percent_complete)));
+  }
+
+  /**
+   * This is the task code that adds photos and albums.  It first examines all the target files
+   * and creates a set of Server_Add_Entry_Models, then runs through the list of models and adds
+   * them one at a time.
+   */
+  static function add($task) {
+    $mode = $task->get("mode", "init");
+    $start = microtime(true);
+
+    switch ($mode) {
+    case "init":
+      $task->set("mode", "build-file-list");
+      $task->set("dirs_scanned", 0);
+      $task->percent_complete = 0;
+      $task->status = t("Starting up");
+      batch::start();
+      break;
+
+    case "build-file-list":  // 0% to 10%
+      // We can't fit an arbitrary number of paths in a task, so store them in a separate table.
+      // Don't use an iterator here because we can't get enough control over it when we're dealing
+      // with a deep hierarchy and we don't want to go over our time quota.
+      $paths = unserialize(module::get_var("server_add", "authorized_paths"));
+      $dirs_scanned = $task->get("dirs_scanned");
+      while (microtime(true) - $start < 0.5) {
+        // Process every directory that doesn't yet have a parent id, these are the
+        // paths that we're importing.
+        $entry = ORM::factory("server_add_entry")
+          ->where("task_id", "=", $task->id)
+          ->where("is_directory", "=", 1)
+          ->where("checked", "=", 0)
+          ->order_by("id", "ASC")
+          ->find();
+
+        if ($entry->loaded()) {
+          $child_paths = glob(preg_quote($entry->path) . "/*");
+          if (!$child_paths) {
+            $child_paths = glob("{$entry->path}/*");
+          }
+          foreach ($child_paths as $child_path) {
+            if (!is_dir($child_path)) {
+              $ext = strtolower(pathinfo($child_path, PATHINFO_EXTENSION));
+              if (!legal_file::get_extensions($ext) || !filesize($child_path)) {
+                // Not importable, skip it.
+                continue;
+              }
+            }
+
+            $child_entry = ORM::factory("server_add_entry");
+            $child_entry->task_id = $task->id;
+            $child_entry->path = $child_path;
+            $child_entry->parent_id = $entry->id;  // null if the parent was a staging dir
+            $child_entry->is_directory = is_dir($child_path);
+            $child_entry->save();
+          }
+
+          // We've processed this entry, mark it as done.
+          $entry->checked = 1;
+          $entry->save();
+          $dirs_scanned++;
+        }
+      }
+
+      // We have no idea how long this can take because we have no idea how deep the tree
+      // hierarchy rabbit hole goes.  Leave ourselves room here for 100 iterations and don't go
+      // over 10% in percent_complete.
+      $task->set("dirs_scanned", $dirs_scanned);
+      $task->percent_complete = min($task->percent_complete + 0.1, 10);
+      $task->status = t2("Scanned one directory", "Scanned %count directories", $dirs_scanned);
+
+      if (!$entry->loaded()) {
+        $task->set("mode", "add-files");
+        $task->set(
+          "total_files",
+          ORM::factory("server_add_entry")->where("task_id", "=", $task->id)->count_all());
+        $task->percent_complete = 10;
+      }
+      break;
+
+    case "add-files": // 10% to 100%
+      $completed_files = $task->get("completed_files", 0);
+      $total_files = $task->get("total_files");
+
+      // Ordering by id ensures that we add them in the order that we created the entries, which
+      // will create albums first.  Ignore entries which already have an Item_Model attached,
+      // they're done.
+      $entries = ORM::factory("server_add_entry")
+        ->where("task_id", "=", $task->id)
+        ->where("item_id", "IS", null)
+        ->order_by("id", "ASC")
+        ->limit(10)
+        ->find_all();
+      if ($entries->count() == 0) {
+        // Out of entries, we're done.
+        $task->set("mode", "done");
+      }
+
+      $owner_id = identity::active_user()->id;
+      foreach ($entries as $entry) {
+        if (microtime(true) - $start > 0.5) {
+          break;
+        }
+
+        // Look up the parent item for this entry.  By now it should exist, but if none was
+        // specified, then this belongs as a child of the current item.
+        $parent_entry = ORM::factory("server_add_entry", $entry->parent_id);
+        if (!$parent_entry->loaded()) {
+          $parent = ORM::factory("item", $task->get("item_id"));
+        } else {
+          $parent = ORM::factory("item", $parent_entry->item_id);
+        }
+
+        $name = basename($entry->path);
+        $title = item::convert_filename_to_title($name);
+        if ($entry->is_directory) {
+          $album = ORM::factory("item");
+          $album->type = "album";
+          $album->parent_id = $parent->id;
+          $album->name = $name;
+          $album->title = $title;
+          $album->owner_id = $owner_id;
+          $album->sort_order = $parent->sort_order;
+          $album->sort_column = $parent->sort_column;
+          $album->save();
+          $entry->item_id = $album->id;
+        } else {
+          try {
+            $extension = strtolower(pathinfo($name, PATHINFO_EXTENSION));
+            if (legal_file::get_photo_extensions($extension)) {
+              $photo = ORM::factory("item");
+              $photo->type = "photo";
+              $photo->parent_id = $parent->id;
+              $photo->set_data_file($entry->path);
+              $photo->name = $name;
+              $photo->title = $title;
+              $photo->owner_id = $owner_id;
+              $photo->save();
+              $entry->item_id = $photo->id;
+            } else if (legal_file::get_movie_extensions($extension)) {
+              $movie = ORM::factory("item");
+              $movie->type = "movie";
+              $movie->parent_id = $parent->id;
+              $movie->set_data_file($entry->path);
+              $movie->name = $name;
+              $movie->title = $title;
+              $movie->owner_id = $owner_id;
+              $movie->save();
+              $entry->item_id = $movie->id;
+            } else {
+              // This should never happen, because we don't add stuff to the list that we can't
+              // process.  But just in, case.. set this to a non-null value so that we skip this
+              // entry.
+              $entry->item_id = 0;
+              $task->log("Skipping unknown file type: {$entry->path}");
+            }
+          } catch (Exception $e) {
+            // This can happen if a photo file is invalid, like a BMP masquerading as a .jpg
+            $entry->item_id = 0;
+            $task->log("Skipping invalid file: {$entry->path}");
+          }
+        }
+
+        $completed_files++;
+        $entry->save();
+      }
+      $task->set("completed_files", $completed_files);
+      $task->status = t("Adding photos / albums (%completed of %total)",
+                        array("completed" => $completed_files,
+                              "total" => $total_files));
+      $task->percent_complete = $total_files ? 10 + 100 * ($completed_files / $total_files) : 100;
+      break;
+
+    case "done":
+      batch::stop();
+      $task->done = true;
+      $task->state = "success";
+      $task->percent_complete = 100;
+      ORM::factory("server_add_entry")
+        ->where("task_id", "=", $task->id)
+        ->delete_all();
+      message::info(t2("Successfully added one photo / album",
+                       "Successfully added %count photos / albums",
+                       $task->get("completed_files")));
+    }
+  }
+}
diff --git a/modules/server_add/css/server_add.css b/modules/server_add/css/server_add.css
new file mode 100644
index 0000000..36746ab
--- /dev/null
+++ b/modules/server_add/css/server_add.css
@@ -0,0 +1,38 @@
+#g-server-add button {
+  margin-bottom: .5em;
+}
+
+#g-server-add-tree {
+  cursor: pointer;
+  padding-left: 4px;
+  width: 95%;
+}
+
+#g-server-add-tree li {
+  padding: 0;
+  float: none;
+}
+
+#g-server-add-tree span.selected {
+  background: #ddd;
+}
+
+#g-server-add-tree {
+  border: 1px solid #ccc;
+  height: 20em;
+  overflow: auto;
+  margin-bottom: .5em;
+  padding: .5em;
+}
+
+#g-server-add ul ul li {
+  padding-left: 1.2em;
+}
+
+#g-server-add-paths li .ui-icon {
+  margin-top: .4em;
+}
+
+#g-server-add-admin-form .textbox  {
+  width: 400px;
+}
diff --git a/modules/server_add/helpers/server_add.php b/modules/server_add/helpers/server_add.php
new file mode 100644
index 0000000..5cf08ce
--- /dev/null
+++ b/modules/server_add/helpers/server_add.php
@@ -0,0 +1,49 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class server_add_Core {
+  static function check_config($paths=null) {
+    if ($paths === null) {
+      $paths = unserialize(module::get_var("server_add", "authorized_paths"));
+    }
+    if (empty($paths)) {
+      site_status::warning(
+        t("Server Add needs configuration. <a href=\"%url\">Configure it now!</a>",
+          array("url" => html::mark_clean(url::site("admin/server_add")))),
+        "server_add_configuration");
+    } else {
+      site_status::clear("server_add_configuration");
+    }
+  }
+
+  static function is_valid_path($path) {
+    if (!is_readable($path) || is_link($path)) {
+      return false;
+    }
+
+    $authorized_paths = unserialize(module::get_var("server_add", "authorized_paths"));
+    foreach (array_keys($authorized_paths) as $valid_path) {
+      if (strpos($path, $valid_path) === 0) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+}
diff --git a/modules/server_add/helpers/server_add_event.php b/modules/server_add/helpers/server_add_event.php
new file mode 100644
index 0000000..a718e2f
--- /dev/null
+++ b/modules/server_add/helpers/server_add_event.php
@@ -0,0 +1,42 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class server_add_event_Core {
+  static function admin_menu($menu, $theme) {
+    $menu->get("settings_menu")
+      ->append(Menu::factory("link")
+               ->id("server_add")
+               ->label(t("Server add"))
+               ->url(url::site("admin/server_add")));
+  }
+
+  static function site_menu($menu, $theme) {
+    $item = $theme->item();
+    $paths = unserialize(module::get_var("server_add", "authorized_paths"));
+
+    if ($item && identity::active_user()->admin && $item->is_album() && !empty($paths) &&
+        is_writable($item->is_album() ? $item->file_path() : $item->parent()->file_path())) {
+      $menu->get("add_menu")
+        ->append(Menu::factory("dialog")
+                 ->id("server_add")
+                 ->label(t("Server add"))
+                 ->url(url::site("server_add/browse/$item->id")));
+    }
+  }
+}
diff --git a/modules/server_add/helpers/server_add_installer.php b/modules/server_add/helpers/server_add_installer.php
new file mode 100644
index 0000000..b62bbcf
--- /dev/null
+++ b/modules/server_add/helpers/server_add_installer.php
@@ -0,0 +1,73 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class server_add_installer {
+  static function install() {
+    $db = Database::instance();
+    $db->query("CREATE TABLE {server_add_entries} (
+                  `id` int(9) NOT NULL auto_increment,
+                  `checked` boolean default 0,
+                  `is_directory` boolean default 0,
+                  `item_id` int(9),
+                  `parent_id` int(9),
+                  `path` varchar(255) NOT NULL,
+                  `task_id` int(9) NOT NULL,
+                  PRIMARY KEY (`id`))
+                DEFAULT CHARSET=utf8;");
+    server_add::check_config();
+  }
+
+  static function upgrade($version) {
+    $db = Database::instance();
+    if ($version == 1) {
+      $db->query("CREATE TABLE {server_add_files} (
+                    `id` int(9) NOT NULL auto_increment,
+                    `task_id` int(9) NOT NULL,
+                    `file` varchar(255) NOT NULL,
+                    PRIMARY KEY (`id`))
+                  DEFAULT CHARSET=utf8;");
+      module::set_version("server_add", $version = 2);
+    }
+
+    if ($version == 2) {
+      $db->query("ALTER TABLE {server_add_files} ADD COLUMN `item_id` int(9)");
+      $db->query("ALTER TABLE {server_add_files} ADD COLUMN `parent_id` int(9)");
+      module::set_version("server_add", $version = 3);
+    }
+
+    if ($version == 3) {
+      $db->query("DROP TABLE {server_add_files}");
+      $db->query("CREATE TABLE {server_add_entries} (
+                    `id` int(9) NOT NULL auto_increment,
+                    `checked` boolean default 0,
+                    `is_directory` boolean default 0,
+                    `item_id` int(9),
+                    `parent_id` int(9),
+                    `path` varchar(255) NOT NULL,
+                    `task_id` int(9) NOT NULL,
+                    PRIMARY KEY (`id`))
+                  DEFAULT CHARSET=utf8;");
+      module::set_version("server_add", $version = 4);
+    }
+  }
+
+  static function deactivate() {
+    site_status::clear("server_add_configuration");
+  }
+}
diff --git a/modules/server_add/helpers/server_add_theme.php b/modules/server_add/helpers/server_add_theme.php
new file mode 100644
index 0000000..7dfe658
--- /dev/null
+++ b/modules/server_add/helpers/server_add_theme.php
@@ -0,0 +1,27 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class server_add_theme_Core {
+  static function head($theme) {
+    if (identity::active_user()->admin) {
+      return $theme->css("server_add.css")
+        . $theme->script("server_add.js");
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/server_add/js/server_add.js b/modules/server_add/js/server_add.js
new file mode 100644
index 0000000..02dda4c
--- /dev/null
+++ b/modules/server_add/js/server_add.js
@@ -0,0 +1,125 @@
+(function($) {
+   $.widget("ui.gallery_server_add",  {
+     _init: function() {
+       var self = this;
+       $("#g-server-add-add-button", this.element).click(function(event) {
+         event.preventDefault();
+         $(".g-progress-bar", this.element).
+           progressbar().
+           progressbar("value", 0);
+         $("#g-server-add-progress", this.element).slideDown("fast", function() { self.start_add(); });
+       });
+       $("#g-server-add-pause-button", this.element).click(function(event) {
+         self.pause = true;
+         $("#g-server-add-pause-button", this.element).hide();
+         $("#g-server-add-continue-button", this.element).show();
+       });
+       $("#g-server-add-continue-button", this.element).click(function(event) {
+         self.pause = false;
+         $("#g-server-add-pause-button", this.element).show();
+         $("#g-server-add-continue-button", this.element).hide();
+         self.run_add();
+       });
+       $("#g-server-add-close-button", this.element).click(function(event) {
+         $("#g-dialog").dialog("close");
+         window.location.reload();
+       });
+       $("#g-server-add-tree span.g-directory", this.element).dblclick(function(event) {
+         self.open_dir(event);
+       });
+       $("#g-server-add-tree span.g-file, #g-server-add-tree span.g-directory", this.element).click(function(event) {
+         self.select_file(event);
+       });
+       $("#g-server-add-tree span.g-directory", this.element).dblclick(function(event) {
+         self.open_dir(event);
+       });
+       $("#g-dialog").bind("dialogclose", function(event, ui) {
+         window.location.reload();
+       });
+     },
+
+     taskURL: null,
+     pause: false,
+
+     start_add: function() {
+       var self = this;
+       var paths = [];
+       $.each($("span.selected", self.element), function () {
+	 paths.push($(this).attr("ref"));
+       });
+
+       $("#g-server-add-add-button", this.element).hide();
+       $("#g-server-add-pause-button", this.element).show();
+
+       $.ajax({
+         url: START_URL,
+         type: "POST",
+         async: false,
+         data: { "paths[]": paths },
+         dataType: "json",
+         success: function(data, textStatus) {
+           $("#g-status").html(data.status);
+           $(".g-progress-bar", self.element).progressbar("value", data.percent_complete);
+           self.taskURL = data.url;
+           setTimeout(function() { self.run_add(); }, 25);
+         }
+       });
+       return false;
+     },
+
+     run_add: function () {
+       var self = this;
+       $.ajax({
+         url: self.taskURL,
+         async: false,
+         dataType: "json",
+         success: function(data, textStatus) {
+           $("#g-status").html(data.status);
+           $(".g-progress-bar", self.element).progressbar("value", data.percent_complete);
+           if (data.done) {
+	     $("#g-server-add-progress", this.element).slideUp();
+             $("#g-server-add-add-button", this.element).show();
+             $("#g-server-add-pause-button", this.element).hide();
+             $("#g-server-add-continue-button", this.element).hide();
+           } else {
+             if (!self.pause) {
+               setTimeout(function() { self.run_add(); }, 25);
+             }
+           }
+         }
+       });
+     },
+
+     /**
+      * Load a new directory
+      */
+     open_dir: function(event) {
+       var self = this;
+       var path = $(event.target).attr("ref");
+       $.ajax({
+         url: GET_CHILDREN_URL.replace("__PATH__", path),
+         success: function(data, textStatus) {
+           $("#g-server-add-tree", self.element).html(data);
+           $("#g-server-add-tree span.g-directory", self.element).dblclick(function(event) {
+             self.open_dir(event);
+           });
+           $("#g-server-add-tree span.g-file, #g-server-add-tree span.g-directory", this.element).click(function(event) {
+             self.select_file(event);
+           });
+         }
+       });
+     },
+
+     /**
+      * Manage file selection state.
+      */
+     select_file:  function (event) {
+       $(event.target).toggleClass("selected");
+       if ($("#g-server-add span.selected").length) {
+         $("#g-server-add-add-button").enable(true).removeClass("ui-state-disabled");
+       } else {
+         $("#g-server-add-add-button").enable(false).addClass("ui-state-disabled");
+       }
+     }
+  });
+})(jQuery);
diff --git a/modules/server_add/models/server_add_entry.php b/modules/server_add/models/server_add_entry.php
new file mode 100644
index 0000000..572ebcb
--- /dev/null
+++ b/modules/server_add/models/server_add_entry.php
@@ -0,0 +1,21 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Server_Add_Entry_Model_Core extends ORM {
+}
diff --git a/modules/server_add/module.info b/modules/server_add/module.info
new file mode 100644
index 0000000..dc455c7
--- /dev/null
+++ b/modules/server_add/module.info
@@ -0,0 +1,7 @@
+name = "Server Add"
+description = "Allows authorized users to load images directly from your web server"
+version = 4
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:server_add"
+discuss_url = "http://galleryproject.org/forum_module_server_add"
diff --git a/modules/server_add/views/admin_server_add.html.php b/modules/server_add/views/admin_server_add.html.php
new file mode 100644
index 0000000..f59e327
--- /dev/null
+++ b/modules/server_add/views/admin_server_add.html.php
@@ -0,0 +1,40 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?= $theme->css("server_add.css") ?>
+<?= $theme->css("jquery.autocomplete.css") ?>
+<?= $theme->script("jquery.autocomplete.js") ?>
+<script type="text/javascript">
+$("document").ready(function() {
+  $("#g-path").gallery_autocomplete(
+    "<?= url::site("__ARGS__") ?>".replace("__ARGS__", "admin/server_add/autocomplete"),
+    {
+      max: 256,
+      loadingClass: "g-loading-small",
+    });
+});
+</script>
+
+<div class="g-block">
+  <h1> <?= t("Add from server administration") ?> </h1>
+  <div class="g-block-content">
+    <?= $form ?>
+    <h2><?= t("Authorized paths") ?></h2>
+    <ul id="g-server-add-paths">
+      <? if (empty($paths)): ?>
+      <li class="g-module-status g-info"><?= t("No authorized image source paths defined yet") ?></li>
+      <? endif ?>
+
+      <? foreach ($paths as $id => $path): ?>
+      <li>
+        <?= html::clean($path) ?>
+        <a href="<?= url::site("admin/server_add/remove_path?path=" . urlencode($path) . "&amp;csrf=" . access::csrf_token()) ?>"
+           id="icon_<?= $id ?>"
+           class="g-remove-dir g-button">
+          <span class="ui-icon ui-icon-trash">
+            <?= t("delete") ?>
+          </span>
+        </a>
+      </li>
+      <? endforeach ?>
+    </ul>
+  </div>
+</div>
diff --git a/modules/server_add/views/server_add_tree.html.php b/modules/server_add/views/server_add_tree.html.php
new file mode 100644
index 0000000..9135432
--- /dev/null
+++ b/modules/server_add/views/server_add_tree.html.php
@@ -0,0 +1,37 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<li class="ui-icon-left">
+  <span class="ui-icon ui-icon-folder-open"></span>
+  <span class="g-directory" ref="">
+    <?= t("All") ?>
+  </span>
+  <ul>
+
+    <? foreach ($parents as $dir): ?>
+    <li class="ui-icon-left">
+      <span class="ui-icon ui-icon-folder-open"></span>
+      <span class="g-directory" ref="<?= html::clean_attribute($dir) ?>">
+        <?= html::clean(basename($dir)) ?>
+      </span>
+      <ul>
+        <? endforeach ?>
+
+        <? foreach ($files as $file): ?>
+        <li class="ui-icon-left">
+          <span class="ui-icon <?= is_dir($file) ? "ui-icon-folder-collapsed" : "ui-icon-document" ?>"></span>
+          <span class="<?= is_dir($file) ? "g-directory" : "g-file" ?>"
+                ref="<?= html::clean_attribute($file) ?>" >
+            <?= html::clean(basename($file)) ?>
+          </span>
+        </li>
+        <? endforeach ?>
+        <? if (!$files): ?>
+        <li> <i> <?= t("empty") ?> </i> </li>
+        <? endif ?>
+
+        <? foreach ($parents as $dir): ?>
+      </ul>
+    </li>
+    <? endforeach ?>
+
+  </ul>
+</li>
diff --git a/modules/server_add/views/server_add_tree_dialog.html.php b/modules/server_add/views/server_add_tree_dialog.html.php
new file mode 100644
index 0000000..824a86a
--- /dev/null
+++ b/modules/server_add/views/server_add_tree_dialog.html.php
@@ -0,0 +1,52 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  var GET_CHILDREN_URL = "<?= url::site("server_add/children?path=__PATH__") ?>";
+  var START_URL = "<?= url::site("server_add/start?item_id={$item->id}&csrf=$csrf") ?>";
+</script>
+
+<div id="g-server-add">
+  <h1 style="display: none;"><?= t("Add Photos to '%title'", array("title" => html::purify($item->title))) ?></h1>
+
+  <p id="g-description"><?= t("Photos will be added to album:") ?></p>
+  <ul class="g-breadcrumbs">
+    <? $i = 0 ?>
+    <? foreach ($item->parents() as $parent): ?>
+    <li<? if ($i == 0) print " class=\"g-first\"" ?>> <?= html::purify($parent->title) ?> </li>
+    <? $i++ ?>
+    <? endforeach ?>
+    <li class="g-active"> <?= html::purify($item->title) ?> </li>
+  </ul>
+
+  <ul id="g-server-add-tree" class="g-checkbox-tree">
+    <?= $tree ?>
+  </ul>
+
+  <div id="g-server-add-progress" style="display: none">
+    <div class="g-progress-bar"></div>
+    <div id="g-status"></div>
+  </div>
+
+  <span>
+    <button id="g-server-add-add-button" class="ui-state-default ui-state-disabled ui-corner-all"
+            disabled="disabled">
+      <?= t("Add") ?>
+    </button>
+    <button id="g-server-add-pause-button" class="ui-state-default ui-corner-all" style="display:none">
+      <?= t("Pause") ?>
+    </button>
+    <button id="g-server-add-continue-button" class="ui-state-default ui-corner-all" style="display:none">
+      <?= t("Continue") ?>
+    </button>
+
+    <button id="g-server-add-close-button" class="ui-state-default ui-corner-all">
+      <?= t("Close") ?>
+    </button>
+  </span>
+
+  <script type="text/javascript">
+    $("#g-server-add").ready(function() {
+      $("#g-server-add").gallery_server_add();
+    });
+  </script>
+
+</div>
diff --git a/modules/slideshow/helpers/slideshow_event.php b/modules/slideshow/helpers/slideshow_event.php
new file mode 100644
index 0000000..add1e33
--- /dev/null
+++ b/modules/slideshow/helpers/slideshow_event.php
@@ -0,0 +1,80 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class slideshow_event_Core {
+  static function pre_deactivate($data) {
+    if ($data->module == "rss") {
+      $data->messages["warn"][] = t("The Slideshow module requires the RSS module.");
+    }
+  }
+
+  static function module_change($changes) {
+    if (!module::is_active("rss") || in_array("rss", $changes->deactivate)) {
+      site_status::warning(
+        t("The Slideshow module requires the RSS module.  <a href=\"%url\">Activate the RSS module now</a>",
+          array("url" => html::mark_clean(url::site("admin/modules")))),
+        "slideshow_needs_rss");
+    } else {
+      site_status::clear("slideshow_needs_rss");
+    }
+  }
+
+  static function album_menu($menu, $theme) {
+    $max_scale = module::get_var("slideshow", "max_scale");
+    if ($theme->item()->descendants_count(array(array("type", "=", "photo")))) {
+      $menu->append(Menu::factory("link")
+                    ->id("slideshow")
+                    ->label(t("View slideshow"))
+                    ->url("javascript:cooliris.embed.show(" .
+                          "{maxScale:$max_scale,feed:'" . self::_feed_url($theme) . "'})")
+                    ->css_id("g-slideshow-link"));
+    }
+  }
+
+  static function photo_menu($menu, $theme) {
+    $max_scale = module::get_var("slideshow", "max_scale");
+    $menu->append(Menu::factory("link")
+                  ->id("slideshow")
+                  ->label(t("View slideshow"))
+                  ->url("javascript:cooliris.embed.show(" .
+                        "{maxScale:$max_scale,feed:'" . self::_feed_url($theme) . "'})")
+                  ->css_id("g-slideshow-link"));
+  }
+
+  static function tag_menu($menu, $theme) {
+    $max_scale = module::get_var("slideshow", "max_scale");
+    $menu->append(Menu::factory("link")
+                  ->id("slideshow")
+                  ->label(t("View slideshow"))
+                  ->url("javascript:cooliris.embed.show(" .
+                        "{maxScale:$max_scale,feed:'" . self::_feed_url($theme) . "'})")
+                  ->css_id("g-slideshow-link"));
+  }
+
+  private static function _feed_url($theme) {
+    if ($item = $theme->item()) {
+      if (!$item->is_album()) {
+        $item = $item->parent();
+      }
+      return rss::url("gallery/album/{$item->id}");
+    } else {
+      return rss::url("tag/tag/{$theme->tag()->id}");
+    }
+  }
+}
diff --git a/modules/slideshow/helpers/slideshow_installer.php b/modules/slideshow/helpers/slideshow_installer.php
new file mode 100644
index 0000000..22bd953
--- /dev/null
+++ b/modules/slideshow/helpers/slideshow_installer.php
@@ -0,0 +1,43 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class slideshow_installer {
+  static function install() {
+    module::set_var("slideshow", "max_scale", 0);
+  }
+
+  static function upgrade($version) {
+    if ($version == 1) {
+      module::set_var("slideshow", "max_scale", 0);
+      module::set_version("slideshow", $version = 2);
+    }
+  }
+
+  static function deactivate() {
+    site_status::clear("slideshow_needs_rss");
+  }
+
+  static function can_activate() {
+    $messages = array();
+    if (!module::is_active("rss")) {
+      $messages["warn"][] = t("The Slideshow module requires the RSS module.");
+    }
+    return $messages;
+  }
+}
diff --git a/modules/slideshow/helpers/slideshow_theme.php b/modules/slideshow/helpers/slideshow_theme.php
new file mode 100644
index 0000000..bb02212
--- /dev/null
+++ b/modules/slideshow/helpers/slideshow_theme.php
@@ -0,0 +1,26 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class slideshow_theme_Core {
+  static function page_bottom($theme) {
+    $proto = request::protocol();
+    return "<script src=\"$proto://e.cooliris.com/slideshow/v/37732/go.js\" " .
+      "type=\"text/javascript\"></script>";
+  }
+}
diff --git a/modules/slideshow/module.info b/modules/slideshow/module.info
new file mode 100644
index 0000000..2d71f71
--- /dev/null
+++ b/modules/slideshow/module.info
@@ -0,0 +1,7 @@
+name = "Slideshow"
+description = "Allows users to view a slideshow of photos"
+version = 2
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:slideshow"
+discuss_url = "http://galleryproject.org/forum_module_slideshow"
diff --git a/modules/tag/controllers/admin_tags.php b/modules/tag/controllers/admin_tags.php
new file mode 100644
index 0000000..19906c6
--- /dev/null
+++ b/modules/tag/controllers/admin_tags.php
@@ -0,0 +1,119 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Tags_Controller extends Admin_Controller {
+  public function index() {
+    $filter = Input::instance()->get("filter");
+
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Manage tags");
+    $view->content = new View("admin_tags.html");
+    $view->content->filter = $filter;
+
+    $query = ORM::factory("tag");
+    if ($filter) {
+      $query->like("name", $filter);
+    }
+    $view->content->tags = $query->order_by("name", "ASC")->find_all();
+    print $view;
+  }
+
+  public function form_delete($id) {
+    $tag = ORM::factory("tag", $id);
+    if ($tag->loaded()) {
+      print tag::get_delete_form($tag);
+    }
+  }
+
+  public function delete($id) {
+    access::verify_csrf();
+
+    $tag = ORM::factory("tag", $id);
+    if (!$tag->loaded()) {
+      throw new Kohana_404_Exception();
+    }
+
+    $form = tag::get_delete_form($tag);
+    if ($form->validate()) {
+      $name = $tag->name;
+      $tag->delete();
+      message::success(t("Deleted tag %tag_name", array("tag_name" => $name)));
+      log::success("tags", t("Deleted tag %tag_name", array("tag_name" => $name)));
+
+      json::reply(array("result" => "success", "location" => url::site("admin/tags")));
+    } else {
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function form_rename($id) {
+    $tag = ORM::factory("tag", $id);
+    if ($tag->loaded()) {
+      print InPlaceEdit::factory($tag->name)
+        ->action("admin/tags/rename/$id")
+        ->render();
+    }
+  }
+
+  public function rename($id) {
+    access::verify_csrf();
+
+    $tag = ORM::factory("tag", $id);
+    if (!$tag->loaded()) {
+      throw new Kohana_404_Exception();
+    }
+
+    $in_place_edit = InPlaceEdit::factory($tag->name)
+      ->action("admin/tags/rename/$tag->id")
+      ->rules(array("required", "length[1,64]"));
+
+    if ($in_place_edit->validate()) {
+      $old_name = $tag->name;
+      $new_name_or_list = $in_place_edit->value();
+      $tag_list = explode(",", $new_name_or_list);
+
+      $tag->name = array_shift($tag_list);
+      $tag->save();
+
+      if (!empty($tag_list)) {
+        $this->_copy_items_for_tags($tag, $tag_list);
+        $message = t("Split tag <i>%old_name</i> into <i>%tag_list</i>",
+                     array("old_name" => $old_name, "tag_list" => $new_name_or_list));
+      } else {
+        $message = t("Renamed tag <i>%old_name</i> to <i>%new_name</i>",
+                     array("old_name" => $old_name, "new_name" => $tag->name));
+      }
+
+      message::success($message);
+      log::success("tags", $message);
+
+      json::reply(array("result" => "success", "location" => url::site("admin/tags")));
+    } else {
+      json::reply(array("result" => "error", "form" => (string)$in_place_edit->render()));
+    }
+  }
+
+  private function _copy_items_for_tags($tag, $tag_list) {
+    foreach ($tag->items() as $item) {
+      foreach ($tag_list as $new_tag_name) {
+        tag::add($item, trim($new_tag_name));
+      }
+    }
+  }
+}
diff --git a/modules/tag/controllers/tag.php b/modules/tag/controllers/tag.php
new file mode 100644
index 0000000..bada9ba
--- /dev/null
+++ b/modules/tag/controllers/tag.php
@@ -0,0 +1,96 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Tag_Controller extends Controller {
+  public function __call($function, $args) {
+    $tag_id = $function;
+    $tag = ORM::factory("tag")->where("id", "=", $tag_id)->find();
+    $page_size = module::get_var("gallery", "page_size", 9);
+
+    $input = Input::instance();
+    $show = $input->get("show");
+
+    if ($show) {
+      $child = ORM::factory("item", $show);
+      $index = tag::get_position($tag, $child);
+      if ($index) {
+        $page = ceil($index / $page_size);
+        $uri = "tag/$tag_id/" . urlencode($tag->name);
+        url::redirect($uri . ($page == 1 ? "" : "?page=$page"));
+      }
+    } else {
+      $page = (int) $input->get("page", "1");
+    }
+
+    $children_count = $tag->items_count();
+    $offset = ($page-1) * $page_size;
+    $max_pages = max(ceil($children_count / $page_size), 1);
+
+    // Make sure that the page references a valid offset
+    if ($page < 1) {
+      url::redirect(url::merge(array("page" => 1)));
+    } else if ($page > $max_pages) {
+      url::redirect(url::merge(array("page" => $max_pages)));
+    }
+
+    $root = item::root();
+    $template = new Theme_View("page.html", "collection", "tag");
+    $template->set_global(
+      array("page" => $page,
+            "max_pages" => $max_pages,
+            "page_size" => $page_size,
+            "tag" => $tag,
+            "children" => $tag->items($page_size, $offset),
+            "breadcrumbs" => array(
+              Breadcrumb::instance($root->title, $root->url())->set_first(),
+              Breadcrumb::instance(t("Tag: %tag_name", array("tag_name" => $tag->name)),
+                                   $tag->url())->set_last()),
+            "children_count" => $children_count));
+    $template->content = new View("dynamic.html");
+    $template->content->title = t("Tag: %tag_name", array("tag_name" => $tag->name));
+    print $template;
+
+    item::set_display_context_callback("Tag_Controller::get_display_context", $tag->id);
+  }
+
+  static function get_display_context($item, $tag_id) {
+    $tag = ORM::factory("tag", $tag_id);
+    $where = array(array("type", "!=", "album"));
+
+    $position = tag::get_position($tag, $item, $where);
+    if ($position > 1) {
+      list ($previous_item, $ignore, $next_item) = $tag->items(3, $position - 2, $where);
+    } else {
+      $previous_item = null;
+      list ($next_item) = $tag->items(1, $position, $where);
+    }
+
+    $root = item::root();
+    return array("position" => $position,
+                 "previous_item" => $previous_item,
+                 "next_item" => $next_item,
+                 "sibling_count" => $tag->items_count($where),
+                 "siblings_callback" => array(array($tag, "items"), array()),
+                 "breadcrumbs" => array(
+                   Breadcrumb::instance($root->title, $root->url())->set_first(),
+                   Breadcrumb::instance(t("Tag: %tag_name", array("tag_name" => $tag->name)),
+                                        $tag->url("show={$item->id}")),
+                   Breadcrumb::instance($item->title, $item->url())->set_last()));
+  }
+}
diff --git a/modules/tag/controllers/tag_name.php b/modules/tag/controllers/tag_name.php
new file mode 100644
index 0000000..f96ab69
--- /dev/null
+++ b/modules/tag/controllers/tag_name.php
@@ -0,0 +1,33 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Tag_Name_Controller extends Controller {
+  public function __call($function, $args) {
+    $tag_name = $function;
+    $tag = ORM::factory("tag")->where("name", "=", $tag_name)->find();
+    if (!$tag->loaded()) {
+      // No matching tag was found. If this was an imported tag, this is probably a bug.
+      // If the user typed the URL manually, it might just be wrong
+      throw new Kohana_404_Exception();
+    }
+
+    url::redirect($tag->abs_url());
+  }
+
+}
diff --git a/modules/tag/controllers/tags.php b/modules/tag/controllers/tags.php
new file mode 100644
index 0000000..77d45a9
--- /dev/null
+++ b/modules/tag/controllers/tags.php
@@ -0,0 +1,65 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Tags_Controller extends Controller {
+  public function index() {
+    // Far from perfection, but at least require view permission for the root album
+    $album = ORM::factory("item", 1);
+    access::required("view", $album);
+
+    print tag::cloud(module::get_var("tag", "tag_cloud_size", 30));
+  }
+
+  public function create($item_id) {
+    $item = ORM::factory("item", $item_id);
+    access::required("view", $item);
+    access::required("edit", $item);
+
+    $form = tag::get_add_form($item);
+    if ($form->validate()) {
+      foreach (explode(",", $form->add_tag->inputs["name"]->value) as $tag_name) {
+        $tag_name = trim($tag_name);
+        if ($tag_name) {
+          $tag = tag::add($item, $tag_name);
+        }
+      }
+
+      json::reply(array("result" => "success", "cloud" => (string)tag::cloud(30)));
+    } else {
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function autocomplete() {
+    $tags = array();
+    $tag_parts = explode(",", Input::instance()->get("q"));
+    $limit = Input::instance()->get("limit");
+    $tag_part = ltrim(end($tag_parts));
+    $tag_list = ORM::factory("tag")
+      ->where("name", "LIKE", Database::escape_for_like($tag_part) . "%")
+      ->order_by("name", "ASC")
+      ->limit($limit)
+      ->find_all();
+    foreach ($tag_list as $tag) {
+      $tags[] = html::clean($tag->name);
+    }
+
+    ajax::response(implode("\n", $tags));
+  }
+}
diff --git a/modules/tag/css/tag.css b/modules/tag/css/tag.css
new file mode 100644
index 0000000..8a64960
--- /dev/null
+++ b/modules/tag/css/tag.css
@@ -0,0 +1,102 @@
+/* Tag cloud ~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-tag-cloud ul {
+  font-size: 1.2em;
+  text-align: justify;
+}
+
+#g-tag-cloud ul li {
+  display: inline;
+  line-height: 1.5em;
+  text-align: justify;
+}
+
+#g-tag-cloud ul li a {
+  text-decoration: none;
+}
+
+#g-tag-cloud ul li span {
+  display: none;
+}
+
+#g-tag-cloud ul li.size0 a {
+  color: #9cf;
+  font-size: 70%;
+  font-weight: 100;
+}
+
+#g-tag-cloud ul li.size1 a {
+  color: #9cf;
+  font-size: 80%;
+  font-weight: 100;
+}
+
+#g-tag-cloud ul li.size2 a {
+  color: #69f;
+  font-size: 90%;
+  font-weight: 300;
+}
+
+#g-tag-cloud ul li.size3 a {
+  color: #69c;
+  font-size: 100%;
+  font-weight: 500;
+}
+
+#g-tag-cloud ul li.size4 a {
+  color: #369;
+  font-size: 110%;
+  font-weight: 700;
+}
+
+#g-tag-cloud ul li.size5 a {
+  color: #0e2b52;
+  font-size: 120%;
+  font-weight: 900;
+}
+
+#g-tag-cloud ul li.size6 a {
+  color: #0e2b52;
+  font-size: 130%;
+  font-weight: 900;
+}
+
+#g-tag-cloud ul li.size7 a {
+  color: #0e2b52;
+  font-size: 140%;
+  font-weight: 900;
+}
+
+#g-tag-cloud ul li a:hover {
+  color: #f30;
+  text-decoration: underline;
+}
+
+/* Add tag form ~~~~~~~~~~~~~~~~~~~~ */
+
+#g-sidebar .g-short-form .textbox {
+  width: 11em;
+}
+
+/* Tag admin ~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-tag-admin {
+  table-layout: fixed;
+}
+
+#g-tag-admin td {
+  border: 0;
+  vertical-align: top;
+}
+
+#g-tag-admin ul {
+  margin-bottom: 2em;
+}
+
+#g-tag-admin li {
+  padding: .1em 0 .2em 0;
+}
+
+#g-tag-admin form ul {
+  margin-bottom: 0;
+}
diff --git a/modules/tag/helpers/item_tags_rest.php b/modules/tag/helpers/item_tags_rest.php
new file mode 100644
index 0000000..c153cb9
--- /dev/null
+++ b/modules/tag/helpers/item_tags_rest.php
@@ -0,0 +1,66 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class item_tags_rest_Core {
+  static function get($request) {
+    $item = rest::resolve($request->url);
+    $tags = array();
+    foreach (tag::item_tags($item) as $tag) {
+      $tags[] = rest::url("tag_item", $tag, $item);
+    }
+
+    return array(
+      "url" => $request->url,
+      "members" => $tags);
+  }
+
+  static function post($request) {
+    $tag = rest::resolve($request->params->entity->tag);
+    $item = rest::resolve($request->params->entity->item);
+    access::required("view", $item);
+
+    tag::add($item, $tag->name);
+    return array(
+      "url" => rest::url("tag_item", $tag, $item),
+      "members" => array(
+        rest::url("tag", $tag),
+        rest::url("item", $item)));
+  }
+
+  static function delete($request) {
+    $item = rest::resolve($request->url);
+    access::required("edit", $item);
+
+    // Deleting this collection means removing all tags associated with the item.
+    tag::clear_all($item);
+  }
+
+  static function resolve($id) {
+    $item = ORM::factory("item", $id);
+    if (!access::can("view", $item)) {
+      throw new Kohana_404_Exception();
+    }
+
+    return $item;
+  }
+
+  static function url($item) {
+    return url::abs_site("rest/item_tags/{$item->id}");
+  }
+}
diff --git a/modules/tag/helpers/tag.php b/modules/tag/helpers/tag.php
new file mode 100644
index 0000000..a946e01
--- /dev/null
+++ b/modules/tag/helpers/tag.php
@@ -0,0 +1,181 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class tag_Core {
+  /**
+   * Associate a tag with an item.  Create the tag if it doesn't already exist.
+   *
+   * @todo Write test.
+   *
+   * @param Item_Model $item an item
+   * @param string     $tag_name a tag name
+   * @return Tag_Model
+   * @throws Exception("@todo {$tag_name} WAS_NOT_ADDED_TO {$item->id}")
+   */
+  static function add($item, $tag_name) {
+    if (empty($tag_name)) {
+      throw new exception("@todo MISSING_TAG_NAME");
+    }
+
+    $tag = ORM::factory("tag")->where("name", "=", $tag_name)->find();
+    if (!$tag->loaded()) {
+      $tag->name = $tag_name;
+    }
+
+    $tag->add($item);
+    return $tag->save();
+  }
+
+  /**
+   * Return the N most popular tags.
+   *
+   * @return ORM_Iterator of Tag_Model in descending tag count order
+   */
+  static function popular_tags($count) {
+    $count = max($count, 1);
+    return ORM::factory("tag")
+      ->order_by("count", "DESC")
+      ->limit($count)
+      ->find_all();
+  }
+
+  /**
+   * Return a rendering of the cloud for the N most popular tags.
+   *
+   * @param integer $count the number of tags
+   * @return View
+   */
+  static function cloud($count) {
+    $tags = tag::popular_tags($count)->as_array();
+    if ($tags) {
+      $cloud = new View("tag_cloud.html");
+      $cloud->max_count = $tags[0]->count;
+      if (!$cloud->max_count) {
+        return;
+      }
+      usort($tags, array("tag", "sort_by_name"));
+      $cloud->tags = $tags;
+      return $cloud;
+    }
+  }
+
+  static function sort_by_name($tag1, $tag2) {
+    return strcasecmp($tag1->name, $tag2->name);
+  }
+
+  /**
+   * Return all the tags for a given item.
+   * @return array
+   */
+  static function item_tags($item) {
+    return ORM::factory("tag")
+      ->join("items_tags", "tags.id", "items_tags.tag_id", "left")
+      ->where("items_tags.item_id", "=", $item->id)
+      ->find_all();
+  }
+
+  /**
+   * Return all the items for a given tag.
+   * @return array
+   */
+  static function tag_items($tag) {
+    return ORM::factory("item")
+      ->join("items_tags", "items_tags.item_id", "items.id", "left")
+      ->where("items_tags.tag_id", "=", $tag->id)
+      ->find_all();
+  }
+
+  static function get_add_form($item) {
+    $form = new Forge("tags/create/{$item->id}", "", "post", array("id" => "g-add-tag-form", "class" => "g-short-form"));
+    $label = $item->is_album() ?
+      t("Add tag to album") :
+      ($item->is_photo() ? t("Add tag to photo") : t("Add tag to movie"));
+
+    $group = $form->group("add_tag")->label("Add Tag");
+    $group->input("name")->label($label)->rules("required")->id("name");
+    $group->hidden("item_id")->value($item->id);
+    $group->submit("")->value(t("Add Tag"));
+    return $form;
+  }
+
+  static function get_delete_form($tag) {
+    $form = new Forge("admin/tags/delete/$tag->id", "", "post", array("id" => "g-delete-tag-form"));
+    $group = $form->group("delete_tag")
+      ->label(t("Really delete tag %tag_name?", array("tag_name" => $tag->name)));
+    $group->submit("")->value(t("Delete Tag"));
+    return $form;
+  }
+
+  /**
+   * Delete all tags associated with an item
+   */
+  static function clear_all($item) {
+    db::build()
+      ->update("tags")
+      ->set("count", db::expr("`count` - 1"))
+      ->where("count", ">", 0)
+      ->where("id", "IN", db::build()->select("tag_id")->from("items_tags")->where("item_id", "=", $item->id))
+      ->execute();
+    db::build()
+      ->delete("items_tags")
+      ->where("item_id", "=", $item->id)
+      ->execute();
+  }
+
+  /**
+   * Remove all items from a tag
+   */
+  static function remove_items($tag) {
+    db::build()
+      ->delete("items_tags")
+      ->where("tag_id", "=", $tag->id)
+      ->execute();
+    $tag->count = 0;
+    $tag->save();
+  }
+
+  /**
+   * Get rid of any tags that have no associated items.
+   */
+  static function compact() {
+    // @todo There's a potential race condition here which we can solve by adding a lock around
+    // this and all the cases where we create/update tags.  I'm loathe to do that since it's an
+    // extremely rare case.
+    db::build()->delete("tags")->where("count", "=", 0)->execute();
+  }
+
+  /**
+   * Find the position of the given item in the tag collection.  The resulting
+   * value is 1-indexed, so the first child in the album is at position 1.
+   *
+   * @param Tag_Model  $tag
+   * @param Item_Model $item
+   * @param array      $where an array of arrays, each compatible with ORM::where()
+   */
+  static function get_position($tag, $item, $where=array()) {
+    return ORM::factory("item")
+      ->viewable()
+      ->join("items_tags", "items.id", "items_tags.item_id")
+      ->where("items_tags.tag_id", "=", $tag->id)
+      ->where("items.id", "<=", $item->id)
+      ->merge_where($where)
+      ->order_by("items.id")
+      ->count_all();
+  }
+}
\ No newline at end of file
diff --git a/modules/tag/helpers/tag_block.php b/modules/tag/helpers/tag_block.php
new file mode 100644
index 0000000..e7a7144
--- /dev/null
+++ b/modules/tag/helpers/tag_block.php
@@ -0,0 +1,45 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class tag_block_Core {
+  static function get_site_list() {
+    return array("tag" => t("Popular tags"));
+  }
+
+  static function get($block_id, $theme) {
+    $block = "";
+    switch ($block_id) {
+    case "tag":
+      $block = new Block();
+      $block->css_id = "g-tag";
+      $block->title = t("Popular tags");
+      $block->content = new View("tag_block.html");
+      $block->content->cloud = tag::cloud(module::get_var("tag", "tag_cloud_size", 30));
+
+      if ($theme->item() && $theme->page_subtype() != "tag" && access::can("edit", $theme->item())) {
+        $controller = new Tags_Controller();
+        $block->content->form = tag::get_add_form($theme->item());
+      } else {
+        $block->content->form = "";
+      }
+      break;
+    }
+    return $block;
+  }
+}
\ No newline at end of file
diff --git a/modules/tag/helpers/tag_event.php b/modules/tag/helpers/tag_event.php
new file mode 100644
index 0000000..d62ae36
--- /dev/null
+++ b/modules/tag/helpers/tag_event.php
@@ -0,0 +1,165 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class tag_event_Core {
+  /**
+   * Handle the creation of a new photo.
+   * @todo Get tags from the XMP and/or IPTC data in the image
+   *
+   * @param Item_Model $photo
+   */
+  static function item_created($photo) {
+    $tags = array();
+    if ($photo->is_photo()) {
+      $path = $photo->file_path();
+      $size = getimagesize($photo->file_path(), $info);
+      if (is_array($info) && !empty($info["APP13"])) {
+        $iptc = iptcparse($info["APP13"]);
+        if (!empty($iptc["2#025"])) {
+          foreach($iptc["2#025"] as $tag) {
+            $tag = str_replace("\0",  "", $tag);
+            foreach (explode(",", $tag) as $word) {
+              $word = trim($word);
+              $word = encoding::convert_to_utf8($word);
+              $tags[$word] = 1;
+            }
+          }
+        }
+      }
+    }
+
+    // @todo figure out how to read the keywords from xmp
+    foreach(array_keys($tags) as $tag) {
+      try {
+        tag::add($photo, $tag);
+      } catch (Exception $e) {
+        Kohana_Log::add("error", "Error adding tag: $tag\n" .
+                    $e->getMessage() . "\n" . $e->getTraceAsString());
+      }
+    }
+
+    return;
+  }
+
+  static function item_deleted($item) {
+    tag::clear_all($item);
+    if (!batch::in_progress()) {
+      tag::compact();
+    }
+  }
+
+  static function batch_complete() {
+    tag::compact();
+  }
+
+  static function item_edit_form($item, $form) {
+    $url = url::site("tags/autocomplete");
+    $form->script("")
+      ->text("$('form input[name=tags]').ready(function() {
+                $('form input[name=tags]').gallery_autocomplete(
+                  '$url', {max: 30, multiple: true, multipleSeparator: ',', cacheLength: 1});
+              });");
+
+    $tag_names = array();
+    foreach (tag::item_tags($item) as $tag) {
+      $tag_names[] = $tag->name;
+    }
+    $form->edit_item->input("tags")->label(t("Tags (comma separated)"))
+      ->value(implode(", ", $tag_names));
+  }
+
+  static function item_edit_form_completed($item, $form) {
+    tag::clear_all($item);
+    foreach (explode(",", $form->edit_item->tags->value) as $tag_name) {
+      if ($tag_name) {
+        tag::add($item, trim($tag_name));
+      }
+    }
+    module::event("item_related_update", $item);
+    tag::compact();
+  }
+
+  static function admin_menu($menu, $theme) {
+    $menu->get("content_menu")
+      ->append(Menu::factory("link")
+               ->id("tags")
+               ->label(t("Tags"))
+               ->url(url::site("admin/tags")));
+  }
+
+  static function item_index_data($item, $data) {
+    foreach (tag::item_tags($item) as $tag) {
+      $data[] = $tag->name;
+    }
+  }
+
+  static function add_photos_form($album, $form) {
+    $group = $form->add_photos;
+    if (!is_object($group->uploadify)) {
+      return;
+    }
+
+    $group->input("tags")
+      ->label(t("Add tags to all uploaded files"))
+      ->value("");
+    $group->uploadify->script_data("tags", "");
+
+    $autocomplete_url = url::site("tags/autocomplete");
+    $group->script("")
+      ->text("$('input[name=tags]')
+                .gallery_autocomplete(
+                  '$autocomplete_url',
+                  {max: 30, multiple: true, multipleSeparator: ',', cacheLength: 1}
+                );
+              $('input[name=tags]')
+                .change(function (event) {
+                  $('#g-uploadify').uploadifySettings('scriptData', {'tags': $(this).val()});
+                });");
+  }
+
+  static function add_photos_form_completed($album, $form) {
+    $group = $form->add_photos;
+    if (!is_object($group->uploadify)) {
+      return;
+    }
+
+    foreach (explode(",", $form->add_photos->tags->value) as $tag_name) {
+      $tag_name = trim($tag_name);
+      if ($tag_name) {
+        $tag = tag::add($album, $tag_name);
+      }
+    }
+  }
+
+  static function info_block_get_metadata($block, $item) {
+    $tags = array();
+    foreach (tag::item_tags($item) as $tag) {
+      $tags[] = "<a href=\"{$tag->url()}\">" .
+        html::clean($tag->name) . "</a>";
+    }
+    if ($tags) {
+      $info = $block->content->metadata;
+      $info["tags"] = array(
+        "label" => t("Tags:"),
+        "value" => implode(", ", $tags)
+      );
+      $block->content->metadata = $info;
+    }
+  }
+}
diff --git a/modules/tag/helpers/tag_installer.php b/modules/tag/helpers/tag_installer.php
new file mode 100644
index 0000000..1fd18f3
--- /dev/null
+++ b/modules/tag/helpers/tag_installer.php
@@ -0,0 +1,59 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class tag_installer {
+  static function install() {
+    $db = Database::instance();
+    $db->query("CREATE TABLE IF NOT EXISTS {tags} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `name` varchar(128) NOT NULL,
+                 `count` int(10) unsigned NOT NULL DEFAULT 0,
+                 PRIMARY KEY (`id`),
+                 UNIQUE KEY(`name`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE IF NOT EXISTS {items_tags} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `item_id` int(9) NOT NULL,
+                 `tag_id` int(9) NOT NULL,
+                 PRIMARY KEY (`id`),
+                 KEY(`tag_id`, `id`),
+                 KEY(`item_id`, `id`))
+               DEFAULT CHARSET=utf8;");
+    module::set_var("tag", "tag_cloud_size", 30);
+  }
+
+  static function upgrade($version) {
+    $db = Database::instance();
+    if ($version == 1) {
+      $db->query("ALTER TABLE {tags} MODIFY COLUMN `name` VARCHAR(128)");
+      module::set_version("tag", $version = 2);
+    }
+    if ($version == 2) {
+      module::set_var("tag", "tag_cloud_size", 30);
+      module::set_version("tag", $version = 3);
+    }
+  }
+
+  static function uninstall() {
+    $db = Database::instance();
+    $db->query("DROP TABLE IF EXISTS {tags};");
+    $db->query("DROP TABLE IF EXISTS {items_tags};");
+  }
+}
diff --git a/modules/tag/helpers/tag_item_rest.php b/modules/tag/helpers/tag_item_rest.php
new file mode 100644
index 0000000..0b7a77f
--- /dev/null
+++ b/modules/tag/helpers/tag_item_rest.php
@@ -0,0 +1,51 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class tag_item_rest_Core {
+  static function get($request) {
+    list ($tag, $item) = rest::resolve($request->url);
+    return array(
+      "url" => $request->url,
+      "entity" => array(
+        "tag" => rest::url("tag", $tag),
+        "item" => rest::url("item", $item)));
+  }
+
+  static function delete($request) {
+    list ($tag, $item) = rest::resolve($request->url);
+    access::required("edit", $item);
+    $tag->remove($item);
+    $tag->save();
+  }
+
+  static function resolve($tuple) {
+    list ($tag_id, $item_id) = explode(",", $tuple);
+    $tag = ORM::factory("tag", $tag_id);
+    $item = ORM::factory("item", $item_id);
+    if (!$tag->loaded() || !$item->loaded() || !$tag->has($item) || !access::can("view", $item)) {
+      throw new Kohana_404_Exception();
+    }
+
+    return array($tag, $item);
+  }
+
+  static function url($tag, $item) {
+    return url::abs_site("rest/tag_item/{$tag->id},{$item->id}");
+  }
+}
diff --git a/modules/tag/helpers/tag_items_rest.php b/modules/tag/helpers/tag_items_rest.php
new file mode 100644
index 0000000..5d9919e
--- /dev/null
+++ b/modules/tag/helpers/tag_items_rest.php
@@ -0,0 +1,64 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class tag_items_rest_Core {
+  static function get($request) {
+    $tag = rest::resolve($request->url);
+    $items = array();
+    foreach ($tag->items() as $item) {
+      if (access::can("view", $item)) {
+        $items[] = rest::url("tag_item", $tag, $item);
+      }
+    }
+
+    return array(
+      "url" => $request->url,
+      "members" => $items);
+  }
+
+  static function post($request) {
+    $tag = rest::resolve($request->params->entity->tag);
+    $item = rest::resolve($request->params->entity->item);
+    access::required("view", $item);
+
+    if (!$tag->loaded()) {
+      throw new Kohana_404_Exception();
+    }
+
+    tag::add($item, $tag->name);
+    return array(
+      "url" => rest::url("tag_item", $tag, $item),
+      "members" => array(
+        "tag" => rest::url("tag", $tag),
+        "item" => rest::url("item", $item)));
+  }
+
+  static function delete($request) {
+    $tag = rest::resolve($request->url);
+    $tag->remove_items();
+  }
+
+  static function resolve($id) {
+    return ORM::factory("tag", $id);
+  }
+
+  static function url($tag) {
+    return url::abs_site("rest/tag_items/{$tag->id}");
+  }
+}
diff --git a/modules/tag/helpers/tag_rest.php b/modules/tag/helpers/tag_rest.php
new file mode 100644
index 0000000..9ccb67c
--- /dev/null
+++ b/modules/tag/helpers/tag_rest.php
@@ -0,0 +1,88 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class tag_rest_Core {
+  static function get($request) {
+    $tag = rest::resolve($request->url);
+    $tag_items = array();
+    foreach ($tag->items() as $item) {
+      if (access::can("view", $item)) {
+        $tag_items[] = rest::url("tag_item", $tag, $item);
+      }
+    }
+
+    return array(
+      "url" => $request->url,
+      "entity" => $tag->as_array(),
+      "relationships" => array(
+        "items" => array(
+          "url" => rest::url("tag_items", $tag),
+          "members" => $tag_items)));
+  }
+
+  static function put($request) {
+    // Who can we allow to edit a tag name?  If we allow anybody to do it then any logged in
+    // user can rename all your tags to something offensive.  Right now limit renaming to admins.
+    if (!identity::active_user()->admin) {
+      access::forbidden();
+    }
+    $tag = rest::resolve($request->url);
+    if (isset($request->params->entity->name)) {
+      $tag->name = $request->params->entity->name;
+      $tag->save();
+    }
+  }
+
+  static function delete($request) {
+    // Restrict deleting tags to admins.  Otherwise, a logged in user can do great harm to an
+    // install.
+    if (!identity::active_user()->admin) {
+      access::forbidden();
+    }
+    $tag = rest::resolve($request->url);
+    $tag->delete();
+  }
+
+  static function relationships($resource_type, $resource) {
+    switch ($resource_type) {
+    case "item":
+      $tags = array();
+      foreach (tag::item_tags($resource) as $tag) {
+        $tags[] = rest::url("tag_item", $tag, $resource);
+      }
+      return array(
+        "tags" => array(
+          "url" => rest::url("item_tags", $resource),
+          "members" => $tags));
+    }
+  }
+
+  static function resolve($id) {
+    $tag = ORM::factory("tag", $id);
+    if (!$tag->loaded()) {
+      throw new Kohana_404_Exception();
+    }
+
+    return $tag;
+  }
+
+  static function url($tag) {
+    return url::abs_site("rest/tag/{$tag->id}");
+  }
+}
diff --git a/modules/tag/helpers/tag_rss.php b/modules/tag/helpers/tag_rss.php
new file mode 100644
index 0000000..b432e23
--- /dev/null
+++ b/modules/tag/helpers/tag_rss.php
@@ -0,0 +1,48 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class tag_rss_Core {
+  static function available_feeds($item, $tag) {
+    if ($tag) {
+      $feeds["tag/tag/{$tag->id}"] =
+        t("Tag feed for %tag_name", array("tag_name" => $tag->name));
+      return $feeds;
+    }
+    return array();
+  }
+
+  static function feed($feed_id, $offset, $limit, $id) {
+    if ($feed_id == "tag") {
+      $tag = ORM::factory("tag", $id);
+      if (!$tag->loaded()) {
+        throw new Kohana_404_Exception();
+      }
+
+      $feed = new stdClass();
+      $feed->items = $tag->items($limit, $offset, "photo");
+      $feed->max_pages = ceil($tag->count / $limit);
+      $feed->title = t("%site_title - %tag_name",
+                       array("site_title" => item::root()->title, "tag_name" => $tag->name));
+      $feed->description = t("Photos related to %tag_name", array("tag_name" => $tag->name));
+
+      return $feed;
+    }
+  }
+}
diff --git a/modules/tag/helpers/tag_task.php b/modules/tag/helpers/tag_task.php
new file mode 100644
index 0000000..af9f2f1
--- /dev/null
+++ b/modules/tag/helpers/tag_task.php
@@ -0,0 +1,97 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class tag_task_Core {
+
+  static function available_tasks() {
+    $tasks[] = Task_Definition::factory()
+      ->callback("tag_task::clean_up_tags")
+      ->name(t("Clean up tags"))
+      ->description(t("Correct tag counts and remove tags with no items"))
+      ->severity(log::SUCCESS);
+    return $tasks;
+  }
+
+  /**
+   * Fix up tag counts and delete any tags that have no associated items.
+   * @param Task_Model the task
+   */
+  static function clean_up_tags($task) {
+    $errors = array();
+    try {
+      $start = microtime(true);
+      $last_tag_id = $task->get("last_tag_id", null);
+      $current = 0;
+      $total = 0;
+
+      switch ($task->get("mode", "init")) {
+      case "init":
+        $task->set("total", ORM::factory("tag")->count_all());
+        $task->set("mode", "clean_up_tags");
+        $task->set("completed", 0);
+        $task->set("last_tag_id", 0);
+
+      case "clean_up_tags":
+        $completed = $task->get("completed");
+        $total = $task->get("total");
+        $last_tag_id = $task->get("last_tag_id");
+        $tags = ORM::factory("tag")->where("id", ">", $last_tag_id)->find_all(25);
+        Kohana_Log::add("error",print_r(Database::instance()->last_query(),1));
+        while ($current < $total && microtime(true) - $start < 1 && $tag = $tags->current()) {
+          $last_tag_id = $tag->id;
+          $real_count = $tag->items_count();
+          if ($tag->count != $real_count) {
+            $tag->count = $real_count;
+            if ($tag->count) {
+              $task->log(
+                "Fixing count for tag {$tag->name} (id: {$tag->id}, new count: {$tag->count})");
+              $tag->save();
+            } else {
+              $task->log("Deleting empty tag {$tag->name} ({$tag->id})");
+              $tag->delete();
+            }
+          }
+
+          $completed++;
+          $tags->next();
+        }
+        $task->percent_complete = $completed / $total * 100;
+        $task->set("completed", $completed);
+        $task->set("last_tag_id", $last_tag_id);
+      }
+
+      $task->status = t2("Examined %count tag", "Examined %count tags", $completed);
+
+      if ($completed == $total) {
+        $task->done = true;
+        $task->state = "success";
+        $task->percent_complete = 100;
+      }
+    } catch (Exception $e) {
+      Kohana_Log::add("error",(string)$e);
+      $task->done = true;
+      $task->state = "error";
+      $task->status = $e->getMessage();
+      $errors[] = (string)$e;
+    }
+    if ($errors) {
+      $task->log($errors);
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/tag/helpers/tag_theme.php b/modules/tag/helpers/tag_theme.php
new file mode 100644
index 0000000..81d1352
--- /dev/null
+++ b/modules/tag/helpers/tag_theme.php
@@ -0,0 +1,31 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class tag_theme_Core {
+  static function head($theme) {
+    return $theme->css("jquery.autocomplete.css")
+      . $theme->script("jquery.autocomplete.js")
+      . $theme->css("tag.css");
+  }
+
+  static function admin_head($theme) {
+    return $theme->css("tag.css")
+      . $theme->script("gallery.in_place_edit.js");
+  }
+}
\ No newline at end of file
diff --git a/modules/tag/helpers/tags_rest.php b/modules/tag/helpers/tags_rest.php
new file mode 100644
index 0000000..88a349b
--- /dev/null
+++ b/modules/tag/helpers/tags_rest.php
@@ -0,0 +1,77 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class tags_rest_Core {
+  /**
+   * Possible request parameters:
+   *   start=#
+   *     start at the Nth comment (zero based)
+   *
+   *   num=#
+   *     return up to N comments (max 100)
+   */
+  static function get($request) {
+    $tags = array();
+
+    $num = 10;
+    $start = 0;
+    if (isset($request->params)) {
+      $p = $request->params;
+      $num = isset($p->num) ? min((int)$p->num, 100) : 10;
+      $start = isset($p->start) ? (int)$p->start : 0;
+    }
+
+    foreach (ORM::factory("tag")->find_all($num, $start) as $tag) {
+      $tags[] = rest::url("tag", $tag);
+    }
+    return array("url" => rest::url("tags"),
+                 "members" => $tags);
+  }
+
+  static function post($request) {
+    // The user must have some edit permission somewhere to create a tag.
+    if (!identity::active_user()->admin) {
+      $query = db::build()->from("access_caches")->and_open();
+      foreach (identity::active_user()->groups() as $group) {
+        $query->or_where("edit_{$group->id}", "=", access::ALLOW);
+      }
+      $has_any_edit_perm = $query->close()->count_records();
+      if (!$has_any_edit_perm) {
+        access::forbidden();
+      }
+    }
+
+    if (empty($request->params->entity->name)) {
+      throw new Rest_Exception("Bad Request", 400);
+    }
+
+    $tag = ORM::factory("tag")->where("name", "=", $request->params->entity->name)->find();
+    if (!$tag->loaded()) {
+      $tag->name = $request->params->entity->name;
+      $tag->count = 0;
+      $tag->save();
+    }
+
+    return array("url" => rest::url("tag", $tag));
+  }
+
+  static function url() {
+    return url::abs_site("rest/tags");
+  }
+}
diff --git a/modules/tag/models/tag.php b/modules/tag/models/tag.php
new file mode 100644
index 0000000..0550910
--- /dev/null
+++ b/modules/tag/models/tag.php
@@ -0,0 +1,169 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Tag_Model_Core extends ORM {
+  protected $has_and_belongs_to_many = array("items");
+
+  public function __construct($id=null) {
+    parent::__construct($id);
+
+    if (!$this->loaded()) {
+      // Set reasonable defaults
+      $this->count = 0;
+    }
+  }
+
+  /**
+   * Return all viewable items associated with this tag.
+   * @param integer  $limit  number of rows to limit result to
+   * @param integer  $offset offset in result to start returning rows from
+   * @param string   $where   an array of arrays, each compatible with ORM::where()
+   * @return ORM_Iterator
+   */
+  public function items($limit=null, $offset=null, $where=array()) {
+    if (is_scalar($where)) {
+      // backwards compatibility
+      $where = array(array("items.type", "=", $where));
+    }
+    return ORM::factory("item")
+      ->viewable()
+      ->join("items_tags", "items.id", "items_tags.item_id")
+      ->where("items_tags.tag_id", "=", $this->id)
+      ->merge_where($where)
+      ->order_by("items.id")
+      ->find_all($limit, $offset);
+  }
+
+  /**
+   * Return the count of all viewable items associated with this tag.
+   * @param string   $where   an array of arrays, each compatible with ORM::where()
+   * @return integer
+   */
+  public function items_count($where=array()) {
+    if (is_scalar($where)) {
+      // backwards compatibility
+      $where = array(array("items.type", "=", $where));
+    }
+    return $model = ORM::factory("item")
+      ->viewable()
+      ->join("items_tags", "items.id", "items_tags.item_id")
+      ->where("items_tags.tag_id", "=", $this->id)
+      ->merge_where($where)
+      ->count_all();
+  }
+
+  /**
+   * Overload ORM::save() to trigger an item_related_update event for all items that are related
+   * to this tag.
+   */
+  public function save() {
+    // Check to see if another tag exists with the same name
+    $duplicate_tag = ORM::factory("tag")
+      ->where("name", "=", $this->name)
+      ->where("id", "!=", $this->id)
+      ->find();
+    if ($duplicate_tag->loaded()) {
+      // If so, tag its items with this tag so as to merge it
+      $duplicate_tag_items = ORM::factory("item")
+        ->join("items_tags", "items.id", "items_tags.item_id")
+        ->where("items_tags.tag_id", "=", $duplicate_tag->id)
+        ->find_all();
+      foreach ($duplicate_tag_items as $item) {
+        $this->add($item);
+      }
+
+      // ... and remove the duplicate tag
+      $duplicate_tag->delete();
+    }
+
+    if (isset($this->object_relations["items"])) {
+      $added = array_diff($this->changed_relations["items"], $this->object_relations["items"]);
+      $removed = array_diff($this->object_relations["items"], $this->changed_relations["items"]);
+      if (isset($this->changed_relations["items"])) {
+        $changed = array_merge($added, $removed);
+      }
+      $this->count = count($this->object_relations["items"]) + count($added) - count($removed);
+    }
+
+    $result = parent::save();
+
+    if (!empty($changed)) {
+      foreach (ORM::factory("item")->where("id", "IN", $changed)->find_all() as $item) {
+        module::event("item_related_update", $item);
+      }
+    }
+
+    return $result;
+  }
+
+  /**
+   * Overload ORM::delete() to trigger an item_related_update event for all items that are
+   * related to this tag, and delete all items_tags relationships.
+   */
+  public function delete($ignored_id=null) {
+    $related_item_ids = array();
+    foreach (db::build()
+             ->select("item_id")
+             ->from("items_tags")
+             ->where("tag_id", "=", $this->id)
+             ->execute() as $row) {
+      $related_item_ids[$row->item_id] = 1;
+    }
+
+    db::build()->delete("items_tags")->where("tag_id", "=", $this->id)->execute();
+    $result = parent::delete();
+
+    if ($related_item_ids) {
+      foreach (ORM::factory("item")
+               ->where("id", "IN", array_keys($related_item_ids))
+               ->find_all() as $item) {
+        module::event("item_related_update", $item);
+      }
+    }
+    return $result;
+  }
+
+  /**
+   * Return the server-relative url to this item, eg:
+   *   /gallery3/index.php/tags/35/Bob
+   *
+   * @param string $query the query string (eg "page=3")
+   */
+  public function url($query=null) {
+    $url = url::site("tag/{$this->id}/" . urlencode($this->name));
+    if ($query) {
+      $url .= "?$query";
+    }
+    return $url;
+  }
+
+  /**
+   * Return the full url to this item, eg:
+   *   http://example.com/gallery3/index.php/tags/35/Bob
+   *
+   * @param string $query the query string (eg "page=3")
+   */
+  public function abs_url($query=null) {
+    $url = url::abs_site("tag/{$this->id}/" . urlencode($this->name));
+    if ($query) {
+      $url .= "?$query";
+    }
+    return $url;
+  }
+}
diff --git a/modules/tag/module.info b/modules/tag/module.info
new file mode 100644
index 0000000..19fbdb4
--- /dev/null
+++ b/modules/tag/module.info
@@ -0,0 +1,7 @@
+name = "Tags"
+description = "Allows users to tag photos and albums"
+version = 3
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:tag"
+discuss_url = "http://galleryproject.org/forum_module_tag"
diff --git a/modules/tag/views/admin_tags.html.php b/modules/tag/views/admin_tags.html.php
new file mode 100644
index 0000000..e1db387
--- /dev/null
+++ b/modules/tag/views/admin_tags.html.php
@@ -0,0 +1,59 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  $("document").ready(function() {
+    // using JS for adding link titles to avoid running t() for each tag
+    $("#g-tag-admin .g-tag-name").attr("title", <?= t("Click to edit this tag")->for_js() ?>);
+    $("#g-tag-admin .g-delete-link").attr("title", $(".g-delete-link:first span").html());
+
+    // In-place editing for tag admin
+    $(".g-editable").gallery_in_place_edit({
+      form_url: <?= html::js_string(url::site("admin/tags/form_rename/__ID__")) ?>
+    });
+  });
+</script>
+
+<? $tags_per_column = $tags->count()/5 ?>
+<? $column_tag_count = 0 ?>
+
+<div class="g-block">
+  <h1> <?= t("Manage tags") ?> </h1>
+
+  <div class="g-block-content">
+    <table id="g-tag-admin">
+      <caption>
+        <?= t2("There is one tag", "There are %count tags", $tags->count()) ?>
+      </caption>
+      <tr>
+        <td>
+        <? foreach ($tags as $i => $tag): ?>
+          <? $current_letter = strtoupper(mb_substr($tag->name, 0, 1)) ?>
+
+          <? if ($i == 0): /* first letter */ ?>
+          <strong><?= html::clean($current_letter) ?></strong>
+          <ul>
+          <? elseif ($last_letter != $current_letter): /* new letter */ ?>
+          </ul>
+            <? if ($column_tag_count > $tags_per_column): /* new column */ ?>
+              <? $column_tag_count = 0 ?>
+        </td>
+        <td>
+            <? endif ?>
+          <strong><?= html::clean($current_letter) ?></strong>
+          <ul>
+          <? endif ?>
+              <li>
+                <span class="g-editable g-tag-name" rel="<?= $tag->id ?>"><?= html::clean($tag->name) ?></span>
+                <span class="g-understate">(<?= $tag->count ?>)</span>
+                <a href="<?= url::site("admin/tags/form_delete/$tag->id") ?>"
+                    class="g-dialog-link g-delete-link g-button">
+                  <span class="ui-icon ui-icon-trash"><?= t("Delete this tag") ?></span></a>
+              </li>
+          <? $column_tag_count++ ?>
+          <? $last_letter = $current_letter ?>
+        <? endforeach ?>
+          </ul>
+        </td>
+      </tr>
+    </table>
+  </div>
+</div>
diff --git a/modules/tag/views/tag_block.html.php b/modules/tag/views/tag_block.html.php
new file mode 100644
index 0000000..d25b8dc
--- /dev/null
+++ b/modules/tag/views/tag_block.html.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  $("#g-add-tag-form").ready(function() {
+    var url = $("#g-tag-cloud-autocomplete-url").attr("href");
+    $("#g-add-tag-form input:text").gallery_autocomplete(
+      url, {
+        max: 30,
+        multiple: true,
+        multipleSeparator: ',',
+        cacheLength: 1,
+        selectFirst: false
+      }
+    );
+    $("#g-add-tag-form").ajaxForm({
+      dataType: "json",
+      success: function(data) {
+        if (data.result == "success") {
+          $("#g-tag-cloud").html(data.cloud);
+        }
+        $("#g-add-tag-form").resetForm();
+      }
+    });
+  });
+</script>
+<div id="g-tag-cloud">
+   <a id="g-tag-cloud-autocomplete-url" style="display: none"
+      href="<?= url::site("tags/autocomplete") ?>"></a>
+  <?= $cloud ?>
+</div>
+<?= $form ?>
diff --git a/modules/tag/views/tag_cloud.html.php b/modules/tag/views/tag_cloud.html.php
new file mode 100644
index 0000000..c900ae7
--- /dev/null
+++ b/modules/tag/views/tag_cloud.html.php
@@ -0,0 +1,9 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul>
+  <? foreach ($tags as $tag): ?>
+  <li class="size<?=(int)(($tag->count / $max_count) * 7) ?>">
+    <span><?= $tag->count ?> photos are tagged with </span>
+    <a href="<?= $tag->url() ?>" title="<?= $tag->count?> Bilder"><?= html::clean($tag->name) ?></a>
+  </li>
+  <? endforeach ?>
+</ul>
diff --git a/modules/thumbnav/changelog.log b/modules/thumbnav/changelog.log
new file mode 100644
index 0000000..2efdcc2
--- /dev/null
+++ b/modules/thumbnav/changelog.log
@@ -0,0 +1,20 @@
+Thumb Navigator Changelog
+
+version 1.8
+- ADMIN: Added option to hide albums from the list
+- Module info adjusted to match new format in G3 3.0.2+
+- Fix: Added translation logic for help info
+- Fix: Added check for security access to the photo
+- Added support for modules which "hack" the item logic - instead of using access functionality, changed to use ->viewable()
+
+version 1.7:
+- Fix opacity settings for IE9
+
+version 1.6:
+- Some minor optimizations in Admin section
+
+version 1.5:
+- Some minor fixes
+
+version 1.4:
+- Fixed uninitialized state for content variable
\ No newline at end of file
diff --git a/modules/thumbnav/controllers/admin_thumbnav.php b/modules/thumbnav/controllers/admin_thumbnav.php
new file mode 100644
index 0000000..63b4b36
--- /dev/null
+++ b/modules/thumbnav/controllers/admin_thumbnav.php
@@ -0,0 +1,65 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+
+class Admin_thumbnav_Controller extends Admin_Controller {
+
+  public function index() {
+    $view = new Admin_View("admin.html");
+    $view->content = new View("admin_thumbnav.html");
+    $view->content->form = $this->_get_setting_form();
+    $view->content->help = $this->get_edit_form_help();
+    print $view;
+  }
+
+  public function save() {
+    access::verify_csrf();
+
+    $form = $this->_get_setting_form();
+    if ($form->validate()):
+      $thumb_count = $form->g_admin_thumbnavcfg->thumb_count->value;
+      if ($thumb_count==9):
+        module::clear_var("thumbnav", "thumb_count");
+      else:
+        module::set_var("thumbnav", "thumb_count", $thumb_count);
+      endif;
+      if ($form->g_admin_thumbnavcfg->hidealbum->value):
+        module::set_var("thumbnav", "hide_albums", TRUE);
+      else:
+        module::clear_var("thumbnav", "hide_albums");
+      endif;
+
+      message::success("Settings have been Saved.");
+      url::redirect("admin/thumbnav");
+    endif;
+
+    $view = new Admin_View("admin.html");
+    $view->content = new View("admin_thumbnav.html");
+    $view->content->form = $form;
+    $view->content->help = $this->get_edit_form_help();
+    print $view;
+  }
+
+  private function _get_setting_form() {
+    $form = new Forge("admin/thumbnav/save", "", "post", array("id" => "g-admin-thumbnav-form"));
+    $group = $form->group("g_admin_thumbnavcfg")->label(t("Settings"));
+    $group->input("thumb_count")
+      ->label(t("Thumbs displayed"))
+      ->rules("required|valid_digit")
+      ->value(module::get_var("thumbnav", "thumb_count", 9));
+    $group->checkbox("hidealbum")->label(t("Hide Albums in the list"))
+      ->checked(module::get_var("thumbnav", "hide_albums"));
+    $form->submit("")->value(t("Save"));
+    return $form;
+  }
+
+  protected function get_edit_form_help() {
+    $help = '<fieldset>';
+    $help .= '<legend>Help</legend><ul>';
+    $help .= '<li><h3>Settings</h3>
+      <p>Adjust Max Number of images in the block using <b>Thumbs displayed</b>. Default is 9. 
+      </li>';
+
+    $help .= '</ul></fieldset>';
+    return t($help);
+  }
+
+}
diff --git a/modules/thumbnav/css/thumbnav.css b/modules/thumbnav/css/thumbnav.css
new file mode 100644
index 0000000..549058e
--- /dev/null
+++ b/modules/thumbnav/css/thumbnav.css
@@ -0,0 +1,11 @@
+/* Thumb Navigator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+  
+.g-thumbnav { text-align: center; padding: 0; }
+.g-navthumb { width: 62px; height: 62px; filter:alpha(opacity=55); opacity:.55; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=55)"; }
+
+.g-thumbnav ul { display: inline-block; padding: 0; margin: 0 0.5em; }
+.g-thumbnav li { float: left; border: transparent 1px solid;}
+.g-thumbnav li.g-current { border-color: #ddd; }
+
+.g-thumbnav li.g-current .g-navthumb,
+.g-navthumb:hover { background: #fff; filter:alpha(opacity=100); opacity:1; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; }
diff --git a/modules/thumbnav/helpers/thumbnav_block.php b/modules/thumbnav/helpers/thumbnav_block.php
new file mode 100644
index 0000000..898d691
--- /dev/null
+++ b/modules/thumbnav/helpers/thumbnav_block.php
@@ -0,0 +1,89 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+
+class ThumbNav_block_Core {
+
+  static function get_site_list() {
+    return array("thumbnav_block" => t("Navigator"));
+  }
+
+  static function get($block_id, $theme) {
+    $block = "";
+    switch ($block_id) {
+      case "thumbnav_block":
+        $item = $theme->item;
+        if ((!isset($item)) or (!$item->is_photo())): // Only should be used in photo pages
+          break;
+        endif;
+
+        $hide_albums = module::get_var("thumbnav", "hide_albums", TRUE);
+
+        $siblings = $item->parent()->children();
+        $itemlist = Array();
+        foreach ($siblings as $sibling):
+	        if (isset($sibling)):
+            if ($sibling->viewable()):
+		          if (($hide_albums and ($sibling->is_photo())) or (!$hide_albums)):
+			          $itemlist[] = $sibling;
+			        endif;
+		        endif;
+	        endif;
+	      endforeach;
+
+        $current = -1;
+        $total = count($itemlist);
+
+        $thumb_count = module::get_var("thumbnav", "thumb_count", 9);
+        $thumb_count = min($thumb_count, $total);
+
+        $shift_right = floor($thumb_count / 2);
+        $shift_left = $thumb_count - $shift_right - 1;
+
+        for ($i = 1; $i <= $total; $i++):
+          if ($itemlist[$i-1]->rand_key == $item->rand_key):
+            $current = $i;
+            break;
+          endif;
+        endfor;
+
+  	    $content = '<ul>';
+        if ($current >= 1):
+          $first = $current - $shift_left;
+          $last = $current + $shift_right;
+          if ($first <= 0):
+            $last = min($last - $first + 1, $total);
+            $first = 1;
+          elseif ($last > $total):
+            $first = max($first - ($last - $total), 1);
+            $last = $total;
+          endif;
+
+          for ($i = $first; $i <= $last; $i++):
+            $thumb_item = $itemlist[$i - 1];
+
+	          if ($i == $current):                                
+  	          $content .= '<li class="g-current">';
+	          else:
+  	          $content .= '<li>';
+	          endif;
+  	        $content .= '<a href="' . $thumb_item->url() . '" title="' . html::purify($thumb_item->title) . '" target="_self">';
+	          $content .= $thumb_item->thumb_img(array("class" => "g-navthumb"), 60);         
+  	        $content .= '</a></li>';
+          endfor; 
+        endif;
+
+        $content .= "</ul>";
+        $content .= "<div style=\"clear: both;\"></div>";
+
+        $block = new Block();
+        $block->css_id = "g-thumbnav-block";
+        $block->title = t("Navigator");
+        $block->content = new View("thumbnav_block.html");
+        $block->content->player = $content;
+        break;
+    }
+
+    return $block;
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/modules/thumbnav/helpers/thumbnav_event.php b/modules/thumbnav/helpers/thumbnav_event.php
new file mode 100644
index 0000000..c0e8243
--- /dev/null
+++ b/modules/thumbnav/helpers/thumbnav_event.php
@@ -0,0 +1,20 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+class thumbnav_event_Core {
+
+  static function activate() {
+    thumbnav::check_config();
+  }
+
+  static function deactivate() {
+    site_status::clear("thumbnav_config");
+  }
+
+  static function admin_menu($menu, $theme) {
+    $menu
+      ->get("settings_menu")
+      ->append(Menu::factory("link")
+               ->id("thumbnav")
+               ->label(t("Thumb Navigator"))
+               ->url(url::site("admin/thumbnav")));
+  }
+}
diff --git a/modules/thumbnav/helpers/thumbnav_theme.php b/modules/thumbnav/helpers/thumbnav_theme.php
new file mode 100644
index 0000000..6f11b30
--- /dev/null
+++ b/modules/thumbnav/helpers/thumbnav_theme.php
@@ -0,0 +1,8 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+
+class ThumbNav_theme_Core {
+
+  static function head($theme) {
+    $theme->css("thumbnav.css");
+  }
+}
\ No newline at end of file
diff --git a/modules/thumbnav/module.info b/modules/thumbnav/module.info
new file mode 100644
index 0000000..fcb03ce
--- /dev/null
+++ b/modules/thumbnav/module.info
@@ -0,0 +1,7 @@
+name        = "Thumb Navigator"
+description = "Sidebar block: Adds thumb navigation option in Photo View.<br />Version 1.8 | By <a href=http://blog.dragonsoft.us>Serguei Dosyukov</a> | <a href=http://codex.gallery2.org/Gallery3:Modules:thumbnav>Visit plugin Site</a> | <a href=http://gallery.menalto.com/node/95116>Support</a> | <a href=thumbnav>Settings</a>"
+version     = 18
+author_name = "Serguei Dosyukov"
+author_url  = "http://blog.dragonsoft.us/gallery-3/"
+info_url    = "http://codex.gallery2.org/Gallery3:Modules:thumbnav"
+discuss_url = "http://gallery.menalto.com/node/95116"
diff --git a/modules/thumbnav/views/admin_include.html.php b/modules/thumbnav/views/admin_include.html.php
new file mode 100644
index 0000000..1853596
--- /dev/null
+++ b/modules/thumbnav/views/admin_include.html.php
@@ -0,0 +1,95 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<style>
+#g-header                    { margin-bottom: 10px; }
+#gd-admin                    { position: relative; font-size: 0.9em; }
+#gd-admin legend             { width: 100.5%; padding: 0.4em 0.8em; margin-left: -1.1em; background: url(/themes/greydragon/images/blue-grad.png) #d5e6f2 repeat-x left top; border: #dfdfdf 1px solid; border-top-left-radius: 0.4em; border-top-right-radius: 0.4em; }
+
+.g-admin-left                { float: left; width: 53%; }
+.g-admin-right               { float: left; width: 46%; margin-left: 1%; margin-top: 1em; }
+.g-admin-right h3            { border-bottom: #a2bdbf 1px solid; margin-top: 0.3em; margin-bottom: 0.3em; }
+
+#gd-admin-head               { position: relative; height: auto; clear: both; display: block; overflow: auto; font-size: 11px; padding: 0.4em 0.8em; background-color: #b7c9d6; border: #a2bdbf 1px solid; }
+#gd-admin-title              { float: left; color: #333v42; font-weight: bold; font-size: 1.6em; text-shadow: #deeefa 0 1px 0; }
+#gd-admin-hlinks ul          { float: right; margin-top: 0.4em; font-size: 11px; }
+#gd-admin-hlinks li          { list-style-type: none; float: left; color: #618299; display: inline; }
+#gd-admin-hlinks a           { font-weight: bold; font-size: 13px; }
+
+#gd-admin form              { border: none; }
+#gd-admin fieldset          { border: #ccc 1px solid; border-radius: 0.4em; }
+#gd-admin input.g-error     { padding-left: 30px; border: none; }
+#gd-admin input.g-success   { background-color: transparent; }
+#gd-admin input.g-warning   { background-color: transparent; border: none; }
+#gd-admin p.g-error         { padding-left: 30px; border: none; margin-bottom: 0; background-image: none; }
+
+#g-content                  { padding: 0 1em; width: 97%; font-size: 1em; }
+#g-content form ul li input  { display: inline; float: left; margin-right: 0.8em; } 
+#g-content form ul li select { display: inline; float: left; margin-right: 0.8em; width: 50.6%; }
+#g-content form ul li input[type='text'] { width: 50%; }
+#g-content form ul li textarea { height: 6em; }
+#g-content form input[type="submit"] { border: #5b86ab 2px solid; padding: 0.3em; color: #fff; background: url(/themes/greydragon/images/button-grad-vs.png) #5580a6 repeat-x left top; }
+#g-content form input[type="submit"]:hover,
+input.ui-state-hover { background-image: url(/themes/greydragon/images/button-grad-active-vs.png); border-color: #2e5475; color: #eaf2fa !important; }
+#g-content form #vercheck, #g-content form #shadowbox, #g-content form #organizecheck { display: none; }
+</style>
+
+<script>
+  $(document).ready( function() { 
+    $('form').submit( function() {
+      $('input[type=submit]', this).attr('disabled', 'disabled');
+    });
+  });
+</script>
+
+<?
+  if ($is_module):
+    $admin_info = new ArrayObject(parse_ini_file(MODPATH   . $name . "/module.info"), ArrayObject::ARRAY_AS_PROPS);
+    $version = number_format($admin_info->version / 10, 1, '.', '');
+  else:
+    $admin_info = new ArrayObject(parse_ini_file(THEMEPATH . $name . "/theme.info"), ArrayObject::ARRAY_AS_PROPS);
+    $version = $admin_info->version;
+  endif;
+?>
+
+<div id="gd-admin" class="g-block">
+  <div id="gd-admin-head">
+    <div id="gd-admin-title"><?= t($admin_info->name) ?> - <?= $version ?></div>
+    <div id="gd-admin-hlinks">
+      <ul><li><a href="http://blog.dragonsoft.us/gallery-3/" target="_blank"><?= t("Home") ?></a>&nbsp;|&nbsp;</li>
+        <? if (isset($admin_info->discuss_url)): ?>
+        <li><a href="<?= $admin_info->discuss_url;  ?>" target="_blank"><?= t("Support") ?></a>&nbsp;|&nbsp;</li>
+        <? endif; ?>
+        <? if (isset($admin_info->info_url)): ?>
+        <li><a href="<?= $admin_info->info_url; ?>" target="_blank"><?= t("Download") ?></a>&nbsp;|&nbsp;</li>
+        <? endif; ?>
+        <? if (isset($admin_info->vote)): ?>
+        <li><a href="<?= $admin_info->vote;     ?>" target="_blank"><?= t("Vote") ?></a>&nbsp;|&nbsp;</li>
+        <? endif; ?>
+        <li><a href="http://twitter.com/greydragon_th" target="_blank" title="<?= t("Follow Us on Twitter") ?>"><?= t("Follow Us") ?></a>&nbsp;|&nbsp;</li>
+        <li><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9MWBSVJMWMJEU" target="_blank" ><?= t("Coffee Fund") ?></a>&nbsp;</li>
+      </ul>
+    </div>
+  </div>
+  <div class="g-block-content g-admin-left">
+  <?= $form ?>
+  </div>
+  <div class="g-admin-right">
+  <?= $help ?>
+  </div>
+</div>
diff --git a/modules/thumbnav/views/admin_thumbnav.html.php b/modules/thumbnav/views/admin_thumbnav.html.php
new file mode 100644
index 0000000..b542705
--- /dev/null
+++ b/modules/thumbnav/views/admin_thumbnav.html.php
@@ -0,0 +1,10 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?
+  $view = new View("admin_include.html");
+
+  $view->is_module = TRUE;
+  $view->name = "thumbnav";
+  $view->form = $form;
+  $view->help = $help;
+  print $view;
+?>
diff --git a/modules/thumbnav/views/thumbnav_block.html.php b/modules/thumbnav/views/thumbnav_block.html.php
new file mode 100644
index 0000000..d4c2c76
--- /dev/null
+++ b/modules/thumbnav/views/thumbnav_block.html.php
@@ -0,0 +1,5 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+
+<div class="g-thumbnav">
+  <?= $player ?>
+</div>
\ No newline at end of file
diff --git a/modules/user/config/identity.php b/modules/user/config/identity.php
new file mode 100644
index 0000000..f2fcebf
--- /dev/null
+++ b/modules/user/config/identity.php
@@ -0,0 +1,37 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+/*
+ * @package  Identity
+ *
+ * User settings, defined as arrays, or "groups". If no group name is
+ * used when loading the cache library, the group named "default" will be used.
+ *
+ * Each group can be used independently, and multiple groups can be used at once.
+ *
+ * Group Options:
+ *  driver        - User backend driver. Gallery comes with Gallery user driver.
+ *  allow_updates - Flag to indicate that the back end allows updates.
+ *  params        - Driver parameters, specific to each driver.
+ */
+$config["user"] = array (
+  "driver"        => "gallery",
+  "allow_updates" => true,
+  "params"        => array(),
+);
diff --git a/modules/user/controllers/admin_users.php b/modules/user/controllers/admin_users.php
new file mode 100644
index 0000000..ed589a3
--- /dev/null
+++ b/modules/user/controllers/admin_users.php
@@ -0,0 +1,442 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Users_Controller extends Admin_Controller {
+  public function index() {
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Users and groups");
+    $view->page_type = "collection";
+    $view->page_subtype = "admin_users";
+    $view->content = new View("admin_users.html");
+
+    // @todo: add this as a config option
+    $page_size = module::get_var("user", "page_size", 10);
+    $page = Input::instance()->get("page", "1");
+    $builder = db::build();
+    $user_count = $builder->from("users")->count_records();
+
+    // Pagination info
+    $view->page = $page;
+    $view->page_size = $page_size;
+    $view->children_count = $user_count;
+    $view->max_pages = ceil($view->children_count / $view->page_size);
+
+    $view->content->pager = new Pagination();
+    $view->content->pager->initialize(
+      array("query_string" => "page",
+            "total_items" => $user_count,
+            "items_per_page" => $page_size,
+            "style" => "classic"));
+
+    // Make sure that the page references a valid offset
+    if ($page < 1) {
+      url::redirect(url::merge(array("page" => 1)));
+    } else if ($page > $view->content->pager->total_pages) {
+      url::redirect(url::merge(array("page" => $view->content->pager->total_pages)));
+    }
+
+    // Join our users against the items table so that we can get a count of their items
+    // in the same query.
+    $view->content->users = ORM::factory("user")
+      ->order_by("users.name", "ASC")
+      ->find_all($page_size, $view->content->pager->sql_offset);
+    $view->content->groups = ORM::factory("group")->order_by("name", "ASC")->find_all();
+
+    print $view;
+  }
+
+  public function add_user() {
+    access::verify_csrf();
+
+    $form = $this->_get_user_add_form_admin();
+    try {
+      $user = ORM::factory("user");
+      $valid = $form->validate();
+      $user->name = $form->add_user->inputs["name"]->value;
+      $user->full_name = $form->add_user->full_name->value;
+      $user->password = $form->add_user->password->value;
+      $user->email = $form->add_user->email->value;
+      $user->url = $form->add_user->url->value;
+      $user->locale = $form->add_user->locale->value;
+      $user->admin = $form->add_user->admin->checked;
+      $user->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        $form->add_user->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      $user->save();
+      module::event("user_add_form_admin_completed", $user, $form);
+      message::success(t("Created user %user_name", array("user_name" => $user->name)));
+      json::reply(array("result" => "success"));
+    } else {
+      print json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function add_user_form() {
+    print $this->_get_user_add_form_admin();
+  }
+
+  public function delete_user($id) {
+    access::verify_csrf();
+
+    if ($id == identity::active_user()->id || $id == user::guest()->id) {
+      access::forbidden();
+    }
+
+    $user = user::lookup($id);
+    if (empty($user)) {
+      throw new Kohana_404_Exception();
+    }
+
+    $form = $this->_get_user_delete_form_admin($user);
+    if($form->validate()) {
+      $name = $user->name;
+      $user->delete();
+    } else {
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+
+    $message = t("Deleted user %user_name", array("user_name" => $name));
+    log::success("user", $message);
+    message::success($message);
+    json::reply(array("result" => "success"));
+  }
+
+  public function delete_user_form($id) {
+    $user = user::lookup($id);
+    if (empty($user)) {
+      throw new Kohana_404_Exception();
+    }
+    $v = new View("admin_users_delete_user.html");
+    $v->user = $user;
+    $v->form = $this->_get_user_delete_form_admin($user);
+    print $v;
+  }
+
+  public function edit_user($id) {
+    access::verify_csrf();
+
+    $user = user::lookup($id);
+    if (empty($user)) {
+      throw new Kohana_404_Exception();
+    }
+
+    $form = $this->_get_user_edit_form_admin($user);
+    try {
+      $valid = $form->validate();
+      $user->name = $form->edit_user->inputs["name"]->value;
+      $user->full_name = $form->edit_user->full_name->value;
+      if ($form->edit_user->password->value) {
+        $user->password = $form->edit_user->password->value;
+      }
+      $user->email = $form->edit_user->email->value;
+      $user->url = $form->edit_user->url->value;
+      $user->locale = $form->edit_user->locale->value;
+      if ($user->id != identity::active_user()->id) {
+        $user->admin = $form->edit_user->admin->checked;
+      }
+
+      $user->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        $form->edit_user->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      $user->save();
+      module::event("user_edit_form_admin_completed", $user, $form);
+      message::success(t("Changed user %user_name", array("user_name" => $user->name)));
+      json::reply(array("result" => "success"));
+    } else {
+      json::reply(array("result" => "error", "html" => (string) $form));
+    }
+  }
+
+  public function edit_user_form($id) {
+    $user = user::lookup($id);
+    if (empty($user)) {
+      throw new Kohana_404_Exception();
+    }
+
+    print $this->_get_user_edit_form_admin($user);
+  }
+
+  public function add_user_to_group($user_id, $group_id) {
+    access::verify_csrf();
+    $group = group::lookup($group_id);
+    $user = user::lookup($user_id);
+    $group->add($user);
+    $group->save();
+  }
+
+  public function remove_user_from_group($user_id, $group_id) {
+    access::verify_csrf();
+    $group = group::lookup($group_id);
+    $user = user::lookup($user_id);
+    $group->remove($user);
+    $group->save();
+  }
+
+  public function group($group_id) {
+    $view = new View("admin_users_group.html");
+    $view->group = group::lookup($group_id);
+    print $view;
+  }
+
+  public function add_group() {
+    access::verify_csrf();
+
+    $form = $this->_get_group_add_form_admin();
+    try {
+      $valid = $form->validate();
+      $group = ORM::factory("group");
+      $group->name = $form->add_group->inputs["name"]->value;
+      $group->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        $form->add_group->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      $group->save();
+      message::success(
+        t("Created group %group_name", array("group_name" => $group->name)));
+      json::reply(array("result" => "success"));
+    } else {
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function add_group_form() {
+    print $this->_get_group_add_form_admin();
+  }
+
+  public function delete_group($id) {
+    access::verify_csrf();
+
+    $group = group::lookup($id);
+    if (empty($group)) {
+      throw new Kohana_404_Exception();
+    }
+
+    $form = $this->_get_group_delete_form_admin($group);
+    if ($form->validate()) {
+      $name = $group->name;
+      $group->delete();
+    } else {
+      json::reply(array("result" => "error", "html" => (string) $form));
+    }
+
+    $message = t("Deleted group %group_name", array("group_name" => $name));
+    log::success("group", $message);
+    message::success($message);
+    json::reply(array("result" => "success"));
+  }
+
+  public function delete_group_form($id) {
+    $group = group::lookup($id);
+    if (empty($group)) {
+      throw new Kohana_404_Exception();
+    }
+
+    print $this->_get_group_delete_form_admin($group);
+  }
+
+  public function edit_group($id) {
+    access::verify_csrf();
+
+    $group = group::lookup($id);
+    if (empty($group)) {
+       throw new Kohana_404_Exception();
+    }
+
+    $form = $this->_get_group_edit_form_admin($group);
+    try {
+      $valid = $form->validate();
+      $group->name = $form->edit_group->inputs["name"]->value;
+      $group->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        $form->edit_group->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      $group->save();
+      message::success(
+        t("Changed group %group_name", array("group_name" => $group->name)));
+      json::reply(array("result" => "success"));
+    } else {
+      $group->reload();
+      message::error(
+        t("Failed to change group %group_name", array("group_name" => $group->name)));
+      json::reply(array("result" => "error", "html" => (string) $form));
+    }
+  }
+
+  public function edit_group_form($id) {
+    $group = group::lookup($id);
+    if (empty($group)) {
+      throw new Kohana_404_Exception();
+    }
+
+    print $this->_get_group_edit_form_admin($group);
+  }
+
+  /* User Form Definitions */
+  static function _get_user_edit_form_admin($user) {
+    $form = new Forge(
+      "admin/users/edit_user/$user->id", "", "post", array("id" => "g-edit-user-form"));
+    $group = $form->group("edit_user")->label(t("Edit user"));
+    $group->input("name")->label(t("Username"))->id("g-username")->value($user->name)
+      ->error_messages("required", t("A name is required"))
+      ->error_messages("conflict", t("There is already a user with that username"))
+      ->error_messages("length", t("This name is too long"));
+    $group->input("full_name")->label(t("Full name"))->id("g-fullname")->value($user->full_name)
+      ->error_messages("length", t("This name is too long"));
+    $group->password("password")->label(t("Password"))->id("g-password")
+      ->error_messages("min_length", t("This password is too short"));
+    $group->script("")
+      ->text(
+        '$("form").ready(function(){$(\'input[name="password"]\').user_password_strength();});');
+    $group->password("password2")->label(t("Confirm password"))->id("g-password2")
+      ->error_messages("matches", t("The passwords you entered do not match"))
+      ->matches($group->password);
+    $group->input("email")->label(t("Email"))->id("g-email")->value($user->email)
+      ->error_messages("required", t("You must enter a valid email address"))
+      ->error_messages("length", t("This email address is too long"))
+      ->error_messages("email", t("You must enter a valid email address"));
+    $group->input("url")->label(t("URL"))->id("g-url")->value($user->url)
+      ->error_messages("url", t("You must enter a valid URL"));
+    self::_add_locale_dropdown($group, $user);
+    $group->checkbox("admin")->label(t("Admin"))->id("g-admin")->checked($user->admin);
+
+    // Don't allow the user to control their own admin bit, else you can lock yourself out
+    if ($user->id == identity::active_user()->id) {
+      $group->admin->disabled(1);
+    }
+
+    module::event("user_edit_form_admin", $user, $form);
+    $group->submit("")->value(t("Modify user"));
+    return $form;
+  }
+
+  static function _get_user_add_form_admin() {
+    $form = new Forge("admin/users/add_user", "", "post", array("id" => "g-add-user-form"));
+    $group = $form->group("add_user")->label(t("Add user"));
+    $group->input("name")->label(t("Username"))->id("g-username")
+      ->error_messages("required", t("A name is required"))
+      ->error_messages("length", t("This name is too long"))
+      ->error_messages("conflict", t("There is already a user with that username"));
+    $group->input("full_name")->label(t("Full name"))->id("g-fullname")
+      ->error_messages("length", t("This name is too long"));
+    $group->password("password")->label(t("Password"))->id("g-password")
+      ->error_messages("min_length", t("This password is too short"));
+    $group->script("")
+      ->text(
+        '$("form").ready(function(){$(\'input[name="password"]\').user_password_strength();});');
+    $group->password("password2")->label(t("Confirm password"))->id("g-password2")
+      ->error_messages("matches", t("The passwords you entered do not match"))
+      ->matches($group->password);
+    $group->input("email")->label(t("Email"))->id("g-email")
+      ->error_messages("required", t("You must enter a valid email address"))
+      ->error_messages("length", t("This email address is too long"))
+      ->error_messages("email", t("You must enter a valid email address"));
+    $group->input("url")->label(t("URL"))->id("g-url")
+      ->error_messages("url", t("You must enter a valid URL"));
+    self::_add_locale_dropdown($group);
+    $group->checkbox("admin")->label(t("Admin"))->id("g-admin");
+
+    module::event("user_add_form_admin", $user, $form);
+    $group->submit("")->value(t("Add user"));
+    return $form;
+  }
+
+  private static function _add_locale_dropdown(&$form, $user=null) {
+    $locales = locales::installed();
+    foreach ($locales as $locale => $display_name) {
+      $locales[$locale] = SafeString::of_safe_html($display_name);
+    }
+
+    // Put "none" at the first position in the array
+    $locales = array_merge(array("" => t("« none »")), $locales);
+    $selected_locale = ($user && $user->locale) ? $user->locale : "";
+    $form->dropdown("locale")
+      ->label(t("Language preference"))
+      ->options($locales)
+      ->selected($selected_locale);
+  }
+
+  private function _get_user_delete_form_admin($user) {
+    $form = new Forge("admin/users/delete_user/$user->id", "", "post",
+                      array("id" => "g-delete-user-form"));
+    $group = $form->group("delete_user")->label(
+      t("Delete user %name?", array("name" => $user->display_name())));
+    $group->submit("")->value(t("Delete"));
+    return $form;
+  }
+
+  /* Group Form Definitions */
+  private function _get_group_edit_form_admin($group) {
+    $form = new Forge("admin/users/edit_group/$group->id", "", "post", array("id" => "g-edit-group-form"));
+    $form_group = $form->group("edit_group")->label(t("Edit group"));
+    $form_group->input("name")->label(t("Name"))->id("g-name")->value($group->name)
+      ->error_messages("required", t("A name is required"));
+    $form_group->inputs["name"]->error_messages("conflict", t("There is already a group with that name"))
+      ->error_messages("required", t("You must enter a group name"))
+      ->error_messages("length",
+                       t("The group name must be less than %max_length characters",
+                         array("max_length" => 255)));
+    $form_group->submit("")->value(t("Save"));
+    return $form;
+  }
+
+  private function _get_group_add_form_admin() {
+    $form = new Forge("admin/users/add_group", "", "post", array("id" => "g-add-group-form"));
+    $form_group = $form->group("add_group")->label(t("Add group"));
+    $form_group->input("name")->label(t("Name"))->id("g-name");
+    $form_group->inputs["name"]->error_messages("conflict", t("There is already a group with that name"))
+      ->error_messages("required", t("You must enter a group name"));
+    $form_group->submit("")->value(t("Add group"));
+    return $form;
+  }
+
+  private function _get_group_delete_form_admin($group) {
+    $form = new Forge("admin/users/delete_group/$group->id", "", "post",
+                      array("id" => "g-delete-group-form"));
+    $form_group = $form->group("delete_group")->label(
+      t("Are you sure you want to delete group %group_name?", array("group_name" => $group->name)));
+    $form_group->submit("")->value(t("Delete"));
+    return $form;
+  }
+}
diff --git a/modules/user/controllers/password.php b/modules/user/controllers/password.php
new file mode 100644
index 0000000..ea14144
--- /dev/null
+++ b/modules/user/controllers/password.php
@@ -0,0 +1,141 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Password_Controller extends Controller {
+  const ALLOW_MAINTENANCE_MODE = true;
+  const ALLOW_PRIVATE_GALLERY = true;
+
+  public function reset() {
+    $form = self::_reset_form();
+    if (request::method() == "post") {
+      // @todo separate the post from get parts of this function
+      access::verify_csrf();
+      // Basic validation (was some user name specified?)
+      if ($form->validate()) {
+        $this->_send_reset($form);
+      } else {
+        json::reply(array("result" => "error", "html" => (string)$form));
+      }
+    } else {
+      print $form;
+    }
+  }
+
+  public function do_reset() {
+    if (request::method() == "post") {
+      $this->_change_password();
+    } else {
+      $user = user::lookup_by_hash(Input::instance()->get("key"));
+      if (!empty($user)) {
+        print $this->_new_password_form($user->hash);
+      } else {
+        throw new Exception("@todo FORBIDDEN", 503);
+      }
+    }
+  }
+
+  private function _send_reset($form) {
+    $user_name = $form->reset->inputs["name"]->value;
+    $user = user::lookup_by_name($user_name);
+    if ($user && !empty($user->email)) {
+      $user->hash = random::hash();
+      $user->save();
+      $message = new View("reset_password.html");
+      $message->confirm_url = url::abs_site("password/do_reset?key=$user->hash");
+      $message->user = $user;
+
+      Sendmail::factory()
+        ->to($user->email)
+        ->subject(t("Password Reset Request"))
+        ->header("Mime-Version", "1.0")
+        ->header("Content-type", "text/html; charset=UTF-8")
+        ->message($message->render())
+        ->send();
+
+      log::success(
+        "user",
+        t("Password reset email sent for user %name", array("name" => $user->name)));
+    } else if (!$user) {
+      // Don't include the username here until you're sure that it's XSS safe
+      log::warning(
+                   "user", t("Password reset email requested for user %user_name, which does not exist.",
+                             array("user_name" => $user_name)));
+    } else  {
+      log::warning(
+          "user", t("Password reset failed for %user_name (has no email address on record).",
+                    array("user_name" => $user->name)));
+    }
+
+    // Always pretend that an email has been sent to avoid leaking
+    // information on what user names are actually real.
+    message::success(t("Password reset email sent"));
+    json::reply(array("result" => "success"));
+  }
+
+  private static function _reset_form() {
+    $form = new Forge(url::current(true), "", "post", array("id" => "g-reset-form"));
+    $group = $form->group("reset")->label(t("Reset Password"));
+    $group->input("name")->label(t("Username"))->id("g-name")->class(null)
+      ->rules("required")
+      ->error_messages("required", t("You must enter a user name"));
+    $group->submit("")->value(t("Reset"));
+
+    return $form;
+  }
+
+  private function _new_password_form($hash=null) {
+    $template = new Theme_View("page.html", "other", "reset");
+
+    $form = new Forge("password/do_reset", "", "post", array("id" => "g-change-password-form"));
+    $group = $form->group("reset")->label(t("Change Password"));
+    $hidden = $group->hidden("hash");
+    if (!empty($hash)) {
+      $hidden->value($hash);
+    }
+    $minimum_length = module::get_var("user", "minimum_password_length", 5);
+    $input_password = $group->password("password")->label(t("Password"))->id("g-password")
+      ->rules($minimum_length ? "required|length[$minimum_length, 40]" : "length[40]");
+    $group->password("password2")->label(t("Confirm Password"))->id("g-password2")
+      ->matches($group->password);
+    $group->inputs["password2"]->error_messages(
+      "mistyped", t("The password and the confirm password must match"));
+    $group->submit("")->value(t("Update"));
+
+    $template->content = $form;
+    return $template;
+  }
+
+  private function _change_password() {
+    $view = $this->_new_password_form();
+    if ($view->content->validate()) {
+      $user = user::lookup_by_hash(Input::instance()->post("hash"));
+      if (empty($user)) {
+        throw new Exception("@todo FORBIDDEN", 503);
+      }
+
+      $user->password = $view->content->reset->password->value;
+      $user->hash = null;
+      $user->save();
+      message::success(t("Password reset successfully"));
+      url::redirect(item::root()->abs_url());
+    } else {
+      print $view;
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/user/controllers/users.php b/modules/user/controllers/users.php
new file mode 100644
index 0000000..ee81344
--- /dev/null
+++ b/modules/user/controllers/users.php
@@ -0,0 +1,239 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Users_Controller extends Controller {
+  public function update($id) {
+    $user = user::lookup($id);
+    if (!$user || $user->guest || $user->id != identity::active_user()->id) {
+      access::forbidden();
+    }
+
+    $form = $this->_get_edit_form($user);
+    try {
+      $valid = $form->validate();
+      $user->full_name = $form->edit_user->full_name->value;
+      $user->url = $form->edit_user->url->value;
+
+      if (count(locales::installed()) > 1 &&
+          $user->locale != $form->edit_user->locale->value) {
+        $user->locale = $form->edit_user->locale->value;
+        $flush_locale_cookie = true;
+      }
+
+      $user->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        $form->edit_user->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      if (isset($flush_locale_cookie)) {
+        // Delete the session based locale preference
+        setcookie("g_locale", "", time() - 24 * 3600, "/");
+      }
+
+      $user->save();
+      module::event("user_edit_form_completed", $user, $form);
+      message::success(t("User information updated"));
+      json::reply(array("result" => "success",
+                        "resource" => url::site("users/{$user->id}")));
+    } else {
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function change_password($id) {
+    $user = user::lookup($id);
+    if (!$user || $user->guest || $user->id != identity::active_user()->id) {
+      access::forbidden();
+    }
+
+    $form = $this->_get_change_password_form($user);
+    try {
+      $valid = $form->validate();
+      $user->password = $form->change_password->password->value;
+      $user->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        $form->change_password->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      $user->save();
+      module::event("user_change_password_form_completed", $user, $form);
+      message::success(t("Password changed"));
+      module::event("user_auth", $user);
+      module::event("user_password_change", $user);
+      json::reply(array("result" => "success",
+                        "resource" => url::site("users/{$user->id}")));
+    } else {
+      log::warning("user", t("Failed password change for %name", array("name" => $user->name)));
+      $name = $user->name;
+      module::event("user_auth_failed", $name);
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function change_email($id) {
+    $user = user::lookup($id);
+    if (!$user || $user->guest || $user->id != identity::active_user()->id) {
+      access::forbidden();
+    }
+
+    $form = $this->_get_change_email_form($user);
+    try {
+      $valid = $form->validate();
+      $user->email = $form->change_email->email->value;
+      $user->validate();
+    } catch (ORM_Validation_Exception $e) {
+      // Translate ORM validation errors into form error messages
+      foreach ($e->validation->errors() as $key => $error) {
+        $form->change_email->inputs[$key]->add_error($error, 1);
+      }
+      $valid = false;
+    }
+
+    if ($valid) {
+      $user->save();
+      module::event("user_change_email_form_completed", $user, $form);
+      message::success(t("Email address changed"));
+      module::event("user_auth", $user);
+      json::reply(array("result" => "success",
+                        "resource" => url::site("users/{$user->id}")));
+    } else {
+      log::warning("user", t("Failed email change for %name", array("name" => $user->name)));
+      $name = $user->name;
+      module::event("user_auth_failed", $name);
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function form_edit($id) {
+    $user = user::lookup($id);
+    if (!$user || $user->guest || $user->id != identity::active_user()->id) {
+      access::forbidden();
+    }
+
+    print $this->_get_edit_form($user);
+  }
+
+  public function form_change_password($id) {
+    $user = user::lookup($id);
+    if (!$user || $user->guest || $user->id != identity::active_user()->id) {
+      access::forbidden();
+    }
+
+    print $this->_get_change_password_form($user);
+  }
+
+  public function form_change_email($id) {
+    $user = user::lookup($id);
+    if (!$user || $user->guest || $user->id != identity::active_user()->id) {
+      access::forbidden();
+    }
+
+    print $this->_get_change_email_form($user);
+  }
+
+  private function _get_change_password_form($user) {
+    $form = new Forge(
+      "users/change_password/$user->id", "", "post", array("id" => "g-change-password-user-form"));
+    $group = $form->group("change_password")->label(t("Change your password"));
+    $group->password("old_password")->label(t("Old password"))->id("g-password")
+      ->callback("auth::validate_too_many_failed_auth_attempts")
+      ->callback("user::valid_password")
+      ->error_messages("invalid_password", t("Incorrect password"))
+      ->error_messages(
+        "too_many_failed_auth_attempts",
+        t("Too many incorrect passwords.  Try again later"));
+    $group->password("password")->label(t("New password"))->id("g-password")
+      ->error_messages("min_length", t("Your new password is too short"));
+    $group->script("")
+      ->text(
+        '$("form").ready(function(){$(\'input[name="password"]\').user_password_strength();});');
+    $group->password("password2")->label(t("Confirm new password"))->id("g-password2")
+      ->matches($group->password)
+      ->error_messages("matches", t("The passwords you entered do not match"));
+
+    module::event("user_change_password_form", $user, $form);
+    $group->submit("")->value(t("Save"));
+    return $form;
+  }
+
+  private function _get_change_email_form($user) {
+    $form = new Forge(
+      "users/change_email/$user->id", "", "post", array("id" => "g-change-email-user-form"));
+    $group = $form->group("change_email")->label(t("Change your email address"));
+    $group->password("password")->label(t("Current password"))->id("g-password")
+      ->callback("auth::validate_too_many_failed_auth_attempts")
+      ->callback("user::valid_password")
+      ->error_messages("invalid_password", t("Incorrect password"))
+      ->error_messages(
+        "too_many_failed_auth_attempts",
+        t("Too many incorrect passwords.  Try again later"));
+    $group->input("email")->label(t("New email address"))->id("g-email")->value($user->email)
+      ->error_messages("email", t("You must enter a valid email address"))
+      ->error_messages("length", t("Your email address is too long"))
+      ->error_messages("required", t("You must enter a valid email address"));
+
+    module::event("user_change_email_form", $user, $form);
+    $group->submit("")->value(t("Save"));
+    return $form;
+  }
+
+  private function _get_edit_form($user) {
+    $form = new Forge("users/update/$user->id", "", "post", array("id" => "g-edit-user-form"));
+    $group = $form->group("edit_user")->label(t("Edit your profile"));
+    $group->input("full_name")->label(t("Full Name"))->id("g-fullname")->value($user->full_name)
+      ->error_messages("length", t("Your name is too long"));
+    self::_add_locale_dropdown($group, $user);
+    $group->input("url")->label(t("URL"))->id("g-url")->value($user->url)
+      ->error_messages("url", t("You must enter a valid url"));
+
+    module::event("user_edit_form", $user, $form);
+    $group->submit("")->value(t("Save"));
+    return $form;
+  }
+
+  /** @todo combine with Admin_Users_Controller::_add_locale_dropdown */
+  private function _add_locale_dropdown(&$form, $user=null) {
+    $locales = locales::installed();
+    if (count($locales) <= 1) {
+      return;
+    }
+
+    foreach ($locales as $locale => $display_name) {
+      $locales[$locale] = SafeString::of_safe_html($display_name);
+    }
+
+    // Put "none" at the first position in the array
+    $locales = array_merge(array("" => t("« none »")), $locales);
+    $selected_locale = ($user && $user->locale) ? $user->locale : "";
+    $form->dropdown("locale")
+      ->label(t("Language preference"))
+      ->options($locales)
+      ->selected($selected_locale);
+  }
+}
diff --git a/modules/user/css/user.css b/modules/user/css/user.css
new file mode 100644
index 0000000..93e3d02
--- /dev/null
+++ b/modules/user/css/user.css
@@ -0,0 +1,120 @@
+/* User- and group-related form width ~~~~ */
+
+#g-login-form,
+#g-add-user-form
+#g-edit-user-form,
+#g-delete-user-form,
+#g-user-admin {
+  width: 270px;
+}
+
+/* User/group admin ~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-user-admin {
+  width: auto;
+  margin-bottom: 4em;
+}
+
+#g-group-admin {
+}
+
+#g-user-admin-list .g-admin {
+  color: #55f;
+  font-weight: bold;
+}
+
+.g-group {
+  display: block;
+  border: 1px solid #999;
+  margin: 0 1em 1em 0;
+  padding: 0;
+  width: 200px;
+}
+
+.g-group h4 {
+  background-color: #eee;
+  border-bottom: 1px dashed #ccc;
+  padding: .5em 0 .5em .5em;
+}
+
+.g-group .g-button {
+  padding: 0;
+}
+
+.g-group .g-member-list,
+.g-group div {
+  height: 180px;
+  margin: 1px;
+  overflow: auto;
+}
+
+.g-group p {
+  margin-top: 1em;
+  padding: .5em;
+  text-align: center;
+}
+
+.g-group .g-user {
+  padding: .2em 0 0 .5em;
+}
+
+.g-group .g-user .g-button {
+  vertical-align: middle;
+}
+
+.g-default-group h4,
+.g-default-group .g-user {
+  color: #999;
+}
+
+.g-group.ui-droppable {
+  padding: 0 !important;
+}
+
+/* Password strength meter ~~~~~~~~~~~~~~~ */
+
+.g-password-strength0 {
+  background: url(../images/progressImg1.png) no-repeat 0 0;
+  width: 138px;
+  height: 7px;
+}
+
+.g-password-strength10 {
+  background-position:0 -7px;
+}
+
+.g-password-strength20 {
+  background-position:0 -14px;
+}
+
+.g-password-strength30 {
+  background-position:0 -21px;
+}
+
+.g-password-strength40 {
+  background-position:0 -28px;
+}
+
+.g-password-strength50 {
+  background-position:0 -35px;
+}
+
+.g-password-strength60 {
+  background-position:0 -42px;
+}
+
+.g-password-strength70 {
+  background-position:0 -49px;
+}
+
+.g-password-strength80 {
+  background-position:0 -56px;
+}
+
+.g-password-strength90 {
+  background-position:0 -63px;
+}
+
+.g-password-strength100 {
+  background-position:0 -70px;
+}
diff --git a/modules/user/helpers/group.php b/modules/user/helpers/group.php
new file mode 100644
index 0000000..59c9859
--- /dev/null
+++ b/modules/user/helpers/group.php
@@ -0,0 +1,82 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling groups.
+ *
+ * Note: by design, this class does not do any permission checking.
+ */
+class group_Core {
+  /**
+   * The group of all possible visitors.  This includes the guest user.
+   *
+   * @return Group_Definition the group object
+   */
+  static function everybody() {
+    return model_cache::get("group", 1);
+  }
+
+  /**
+   * The group of all logged-in visitors.  This does not include guest users.
+   *
+   * @return Group_Definition the group object
+   */
+  static function registered_users() {
+    return model_cache::get("group", 2);
+  }
+
+  /**
+   * Look up a group by id.
+   * @param integer      $id the user id
+   * @return Group_Definition  the group object, or null if the id was invalid.
+   */
+  static function lookup($id) {
+    return self::_lookup_by_field("id", $id);
+  }
+
+  /**
+   * Look up a group by name.
+   * @param integer      $id the group name
+   * @return Group_Definition  the group object, or null if the name was invalid.
+   */
+  static function lookup_by_name($name) {
+    return self::_lookup_by_field("name", $name);
+  }
+
+  /**
+   * Search the groups by the field and value.
+   * @param string      $field_name column to look up the user by
+   * @param string      $value value to match
+   * @return Group_Definition  the group object, or null if the name was invalid.
+   */
+  private static function _lookup_by_field($field_name, $value) {
+    try {
+      $group = model_cache::get("group", $value, $field_name);
+      if ($group->loaded()) {
+        return $group;
+      }
+    } catch (Exception $e) {
+      if (strpos($e->getMessage(), "MISSING_MODEL") === false) {
+        throw $e;
+      }
+    }
+    return null;
+  }
+}
diff --git a/modules/user/helpers/user.php b/modules/user/helpers/user.php
new file mode 100644
index 0000000..f59cf76
--- /dev/null
+++ b/modules/user/helpers/user.php
@@ -0,0 +1,176 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling users.
+ *
+ * Note: by design, this class does not do any permission checking.
+ */
+class user_Core {
+  /**
+   * Return the guest user.
+   *
+   * @todo consider caching
+   *
+   * @return User_Model
+   */
+  static function guest() {
+    return model_cache::get("user", 1);
+  }
+
+  /**
+   * Return an admin user.  Prefer the currently logged in user, if possible.
+   *
+   * @return User_Model
+   */
+  static function admin_user() {
+    $active = identity::active_user();
+    if ($active->admin) {
+      return $active;
+    }
+
+    return ORM::factory("user")->where("admin", "=", 1)->order_by("id", "ASC")->find();
+  }
+
+  /**
+   * Is the password provided correct?
+   *
+   * @param user User Model
+   * @param string $password a plaintext password
+   * @return boolean true if the password is correct
+   */
+  static function is_correct_password($user, $password) {
+    $valid = $user->password;
+
+    // Try phpass first, since that's what we generate.
+    if (strlen($valid) == 34) {
+      require_once(MODPATH . "user/lib/PasswordHash.php");
+      $hashGenerator = new PasswordHash(10, true);
+      return $hashGenerator->CheckPassword($password, $valid);
+    }
+
+    $salt = substr($valid, 0, 4);
+    // Support both old (G1 thru 1.4.0; G2 thru alpha-4) and new password schemes:
+    $guess = (strlen($valid) == 32) ? md5($password) : ($salt . md5($salt . $password));
+    if (!strcmp($guess, $valid)) {
+      return true;
+    }
+
+    // Passwords with <&"> created by G2 prior to 2.1 were hashed with entities
+    $sanitizedPassword = html::chars($password, false);
+    $guess = (strlen($valid) == 32) ? md5($sanitizedPassword)
+          : ($salt . md5($salt . $sanitizedPassword));
+    if (!strcmp($guess, $valid)) {
+      return true;
+    }
+
+    return false;
+  }
+
+  static function valid_password($password_input) {
+    if (!user::is_correct_password(identity::active_user(), $password_input->value)) {
+      $password_input->add_error("invalid_password", 1);
+    }
+  }
+
+  static function valid_username($text_input) {
+    if (!self::lookup_by_name($text_input->value)) {
+      $text_input->add_error("invalid_username", 1);
+    }
+  }
+
+  /**
+   * Create the hashed passwords.
+   * @param string $password a plaintext password
+   * @return string hashed password
+   */
+  static function hash_password($password) {
+    require_once(MODPATH . "user/lib/PasswordHash.php");
+    $hashGenerator = new PasswordHash(10, true);
+    return $hashGenerator->HashPassword($password);
+  }
+
+  /**
+   * Look up a user by id.
+   * @param integer      $id the user id
+   * @return User_Model  the user object, or null if the id was invalid.
+   */
+  static function lookup($id) {
+    return self::_lookup_user_by_field("id", $id);
+  }
+
+  /**
+   * Look up a user by name.
+   * @param integer      $name the user name
+   * @return User_Model  the user object, or null if the name was invalid.
+   */
+  static function lookup_by_name($name) {
+    return self::_lookup_user_by_field("name", $name);
+  }
+
+  /**
+   * Look up a user by hash.
+   * @param integer      $hash the user hash value
+   * @return User_Model  the user object, or null if the name was invalid.
+   */
+  static function lookup_by_hash($hash) {
+    return self::_lookup_user_by_field("hash", $hash);
+  }
+
+  /**
+   * List the users
+   * @param mixed      filters (@see Database.php
+   * @return array     the user list.
+   */
+  static function get_user_list($filter=array()) {
+    $user = ORM::factory("user");
+
+    foreach($filter as $method => $args) {
+      switch ($method) {
+      case "in":
+        $user->in($args[0], $args[1]);
+        break;
+      default:
+        $user->$method($args);
+      }
+    }
+    return $user->find_all();
+  }
+
+  /**
+   * Look up a user by field value.
+   * @param string      search field
+   * @param string      search value
+   * @return User_Core  the user object, or null if the name was invalid.
+   */
+  private static function _lookup_user_by_field($field_name, $value) {
+    try {
+      $user = model_cache::get("user", $value, $field_name);
+      if ($user->loaded()) {
+        return $user;
+      }
+    } catch (Exception $e) {
+      if (strpos($e->getMessage(), "MISSING_MODEL") === false) {
+       throw $e;
+      }
+    }
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/modules/user/helpers/user_event.php b/modules/user/helpers/user_event.php
new file mode 100644
index 0000000..40f6dde
--- /dev/null
+++ b/modules/user/helpers/user_event.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+class user_event_Core {
+  static function admin_menu($menu, $theme) {
+    $menu->add_after("appearance_menu", Menu::factory("link")
+                     ->id("users_groups")
+                     ->label(t("Users/Groups"))
+                     ->url(url::site("admin/users")));
+
+    return $menu;
+  }
+}
diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php
new file mode 100644
index 0000000..67f6a3d
--- /dev/null
+++ b/modules/user/helpers/user_installer.php
@@ -0,0 +1,142 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class user_installer {
+  static function can_activate() {
+    return array("warn" => array(IdentityProvider::confirmation_message()));
+  }
+
+  static function activate() {
+    IdentityProvider::change_provider("user");
+    // Set the latest version in initialize() below
+  }
+
+  static function upgrade($version) {
+    if ($version == 1) {
+      module::set_var("user", "mininum_password_length", 5);
+      module::set_version("user", $version = 2);
+    }
+
+    if ($version == 2) {
+      db::build()
+        ->update("users")
+        ->set("email", "unknown@unknown.com")
+        ->where("guest", "=", 0)
+        ->and_open()
+        ->where("email", "IS", null)
+        ->or_where("email", "=", "")
+        ->close()
+        ->execute();
+      module::set_version("user", $version = 3);
+    }
+
+    if ($version == 3) {
+      $password_length = module::get_var("user", "mininum_password_length", 5);
+      module::set_var("user", "minimum_password_length", $password_length);
+      module::clear_var("user", "mininum_password_length");
+      module::set_version("user", $version = 4);
+    }
+  }
+
+  static function uninstall() {
+    // Delete all users and groups so that we give other modules an opportunity to clean up
+    foreach (ORM::factory("user")->find_all() as $user) {
+      $user->delete();
+    }
+
+    foreach (ORM::factory("group")->find_all() as $group) {
+      $group->delete();
+    }
+
+    $db = Database::instance();
+    $db->query("DROP TABLE IF EXISTS {users};");
+    $db->query("DROP TABLE IF EXISTS {groups};");
+    $db->query("DROP TABLE IF EXISTS {groups_users};");
+  }
+
+  static function initialize() {
+    $db = Database::instance();
+    $db->query("CREATE TABLE IF NOT EXISTS {users} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `name` varchar(32) NOT NULL,
+                 `full_name` varchar(255) NOT NULL,
+                 `password` varchar(64) NOT NULL,
+                 `login_count` int(10) unsigned NOT NULL DEFAULT 0,
+                 `last_login` int(10) unsigned NOT NULL DEFAULT 0,
+                 `email` varchar(64) default NULL,
+                 `admin` BOOLEAN default 0,
+                 `guest` BOOLEAN default 0,
+                 `hash` char(32) default NULL,
+                 `url` varchar(255) default NULL,
+                 `locale` char(10) default NULL,
+                 PRIMARY KEY (`id`),
+                 UNIQUE KEY(`hash`),
+                 UNIQUE KEY(`name`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE IF NOT EXISTS {groups} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `name` char(64) default NULL,
+                 `special` BOOLEAN default 0,
+                 PRIMARY KEY (`id`),
+                 UNIQUE KEY(`name`))
+               DEFAULT CHARSET=utf8;");
+
+    $db->query("CREATE TABLE IF NOT EXISTS {groups_users} (
+                 `group_id` int(9) NOT NULL,
+                 `user_id` int(9) NOT NULL,
+                 PRIMARY KEY (`group_id`, `user_id`),
+                 UNIQUE KEY(`user_id`, `group_id`))
+               DEFAULT CHARSET=utf8;");
+
+    $everybody = ORM::factory("group");
+    $everybody->name = "Everybody";
+    $everybody->special = true;
+    $everybody->save();
+
+    $registered = ORM::factory("group");
+    $registered->name = "Registered Users";
+    $registered->special = true;
+    $registered->save();
+
+    $guest = ORM::factory("user");
+    $guest->name = "guest";
+    $guest->full_name = "Guest User";
+    $guest->password = "";
+    $guest->guest = true;
+    $guest->save();
+
+    $admin = ORM::factory("user");
+    $admin->name = "admin";
+    $admin->full_name = "Gallery Administrator";
+    $admin->password = "admin";
+    $admin->email = "unknown@unknown.com";
+    $admin->admin = true;
+    $admin->save();
+
+    $root = ORM::factory("item", 1);
+    access::allow($everybody, "view", $root);
+    access::allow($everybody, "view_full", $root);
+
+    access::allow($registered, "view", $root);
+    access::allow($registered, "view_full", $root);
+
+    module::set_var("user", "minimum_password_length", 5);
+  }
+}
\ No newline at end of file
diff --git a/modules/user/helpers/user_theme.php b/modules/user/helpers/user_theme.php
new file mode 100644
index 0000000..c608cdf
--- /dev/null
+++ b/modules/user/helpers/user_theme.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class user_theme_Core {
+  static function head($theme) {
+    return $theme->css("user.css")
+      . $theme->script("password_strength.js");
+  }
+
+  static function admin_head($theme) {
+    return $theme->css("user.css")
+      . $theme->script("password_strength.js");
+  }
+}
\ No newline at end of file
diff --git a/modules/user/images/progressImg1.png b/modules/user/images/progressImg1.png
new file mode 100644
index 0000000..a909364
Binary files /dev/null and b/modules/user/images/progressImg1.png differ
diff --git a/modules/user/js/password_strength.js b/modules/user/js/password_strength.js
new file mode 100644
index 0000000..2442b8d
--- /dev/null
+++ b/modules/user/js/password_strength.js
@@ -0,0 +1,39 @@
+(function($) {
+   // Based on the Password Strength Indictor By Benjamin Sterling
+   // http://benjaminsterling.com/password-strength-indicator-and-generator/
+   $.widget("ui.user_password_strength",  {
+     _init: function() {
+       var self = this;
+       $(this.element).keyup(function() {
+	 var strength = self.calculateStrength (this.value);
+	 var index = Math.min(Math.floor( strength / 10 ), 10);
+         $("#g-password-gauge")
+           .removeAttr('class')
+	   .addClass( "g-password-strength0" )
+	   .addClass( self.options.classes[ index ] );
+       }).after("<div id='g-password-gauge' class='g-password-strength0'></div>");
+     },
+
+     calculateStrength: function(value) {
+       // Factor in the length of the password
+       var strength = Math.min(5, value.length) * 10 - 20;
+       // Factor in the number of numbers
+       strength += Math.min(3, value.length - value.replace(/[0-9]/g,"").length) * 10;
+       // Factor in the number of non word characters
+       strength += Math.min(3, value.length - value.replace(/\W/g,"").length) * 15;
+       // Factor in the number of Upper case letters
+       strength += Math.min(3, value.length - value.replace(/[A-Z]/g,"").length) * 10;
+
+       // Normalizxe between 0 and 100
+       return Math.max(0, Math.min(100, strength));
+     }
+   });
+   $.extend($.ui.user_password_strength,  {
+     defaults: {
+	classes : ['g-password-strength10', 'g-password-strength20', 'g-password-strength30',
+                   'g-password-strength40', 'g-password-strength50', 'g-password-strength60',
+                   'g-password-strength70',' g-password-strength80',' g-password-strength90',
+                   'g-password-strength100']
+     }
+   });
+ })(jQuery);
diff --git a/modules/user/lib/PasswordHash.php b/modules/user/lib/PasswordHash.php
new file mode 100644
index 0000000..d6783c0
--- /dev/null
+++ b/modules/user/lib/PasswordHash.php
@@ -0,0 +1,248 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+#
+# Portable PHP password hashing framework.
+#
+# Version 0.1 / genuine.
+#
+# Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
+# the public domain.
+#
+# There's absolutely no warranty.
+#
+# The homepage URL for this framework is:
+#
+#	http://www.openwall.com/phpass/
+#
+# Please be sure to update the Version line if you edit this file in any way.
+# It is suggested that you leave the main version number intact, but indicate
+# your project name (after the slash) and add your own revision information.
+#
+# Please do not change the "private" password hashing method implemented in
+# here, thereby making your hashes incompatible.  However, if you must, please
+# change the hash type identifier (the "$P$") to something different.
+#
+# Obviously, since this code is in the public domain, the above are not
+# requirements (there can be none), but merely suggestions.
+#
+class PasswordHash {
+	var $itoa64;
+	var $iteration_count_log2;
+	var $portable_hashes;
+	var $random_state;
+
+	function PasswordHash($iteration_count_log2, $portable_hashes)
+	{
+		$this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+
+		if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
+			$iteration_count_log2 = 8;
+		$this->iteration_count_log2 = $iteration_count_log2;
+
+		$this->portable_hashes = $portable_hashes;
+
+		$this->random_state = microtime() . getmypid();
+	}
+
+	function get_random_bytes($count)
+	{
+		$output = '';
+		if (($fh = @fopen('/dev/urandom', 'rb'))) {
+			$output = fread($fh, $count);
+			fclose($fh);
+		}
+
+		if (strlen($output) < $count) {
+			$output = '';
+			for ($i = 0; $i < $count; $i += 16) {
+				$this->random_state =
+				    md5(microtime() . $this->random_state);
+				$output .=
+				    pack('H*', md5($this->random_state));
+			}
+			$output = substr($output, 0, $count);
+		}
+
+		return $output;
+	}
+
+	function encode64($input, $count)
+	{
+		$output = '';
+		$i = 0;
+		do {
+			$value = ord($input[$i++]);
+			$output .= $this->itoa64[$value & 0x3f];
+			if ($i < $count)
+				$value |= ord($input[$i]) << 8;
+			$output .= $this->itoa64[($value >> 6) & 0x3f];
+			if ($i++ >= $count)
+				break;
+			if ($i < $count)
+				$value |= ord($input[$i]) << 16;
+			$output .= $this->itoa64[($value >> 12) & 0x3f];
+			if ($i++ >= $count)
+				break;
+			$output .= $this->itoa64[($value >> 18) & 0x3f];
+		} while ($i < $count);
+
+		return $output;
+	}
+
+	function gensalt_private($input)
+	{
+		$output = '$P$';
+		$output .= $this->itoa64[min($this->iteration_count_log2 +
+			((PHP_VERSION >= '5') ? 5 : 3), 30)];
+		$output .= $this->encode64($input, 6);
+
+		return $output;
+	}
+
+	function crypt_private($password, $setting)
+	{
+		$output = '*0';
+		if (substr($setting, 0, 2) == $output)
+			$output = '*1';
+
+		if (substr($setting, 0, 3) != '$P$')
+			return $output;
+
+		$count_log2 = strpos($this->itoa64, $setting[3]);
+		if ($count_log2 < 7 || $count_log2 > 30)
+			return $output;
+
+		$count = 1 << $count_log2;
+
+		$salt = substr($setting, 4, 8);
+		if (strlen($salt) != 8)
+			return $output;
+
+		# We're kind of forced to use MD5 here since it's the only
+		# cryptographic primitive available in all versions of PHP
+		# currently in use.  To implement our own low-level crypto
+		# in PHP would result in much worse performance and
+		# consequently in lower iteration counts and hashes that are
+		# quicker to crack (by non-PHP code).
+		if (PHP_VERSION >= '5') {
+			$hash = md5($salt . $password, TRUE);
+			do {
+				$hash = md5($hash . $password, TRUE);
+			} while (--$count);
+		} else {
+			$hash = pack('H*', md5($salt . $password));
+			do {
+				$hash = pack('H*', md5($hash . $password));
+			} while (--$count);
+		}
+
+		$output = substr($setting, 0, 12);
+		$output .= $this->encode64($hash, 16);
+
+		return $output;
+	}
+
+	function gensalt_extended($input)
+	{
+		$count_log2 = min($this->iteration_count_log2 + 8, 24);
+		# This should be odd to not reveal weak DES keys, and the
+		# maximum valid value is (2**24 - 1) which is odd anyway.
+		$count = (1 << $count_log2) - 1;
+
+		$output = '_';
+		$output .= $this->itoa64[$count & 0x3f];
+		$output .= $this->itoa64[($count >> 6) & 0x3f];
+		$output .= $this->itoa64[($count >> 12) & 0x3f];
+		$output .= $this->itoa64[($count >> 18) & 0x3f];
+
+		$output .= $this->encode64($input, 3);
+
+		return $output;
+	}
+
+	function gensalt_blowfish($input)
+	{
+		# This one needs to use a different order of characters and a
+		# different encoding scheme from the one in encode64() above.
+		# We care because the last character in our encoded string will
+		# only represent 2 bits.  While two known implementations of
+		# bcrypt will happily accept and correct a salt string which
+		# has the 4 unused bits set to non-zero, we do not want to take
+		# chances and we also do not want to waste an additional byte
+		# of entropy.
+		$itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+
+		$output = '$2a$';
+		$output .= chr(ord('0') + $this->iteration_count_log2 / 10);
+		$output .= chr(ord('0') + $this->iteration_count_log2 % 10);
+		$output .= '$';
+
+		$i = 0;
+		do {
+			$c1 = ord($input[$i++]);
+			$output .= $itoa64[$c1 >> 2];
+			$c1 = ($c1 & 0x03) << 4;
+			if ($i >= 16) {
+				$output .= $itoa64[$c1];
+				break;
+			}
+
+			$c2 = ord($input[$i++]);
+			$c1 |= $c2 >> 4;
+			$output .= $itoa64[$c1];
+			$c1 = ($c2 & 0x0f) << 2;
+
+			$c2 = ord($input[$i++]);
+			$c1 |= $c2 >> 6;
+			$output .= $itoa64[$c1];
+			$output .= $itoa64[$c2 & 0x3f];
+		} while (1);
+
+		return $output;
+	}
+
+	function HashPassword($password)
+	{
+		$random = '';
+
+		if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) {
+			$random = $this->get_random_bytes(16);
+			$hash =
+			    crypt($password, $this->gensalt_blowfish($random));
+			if (strlen($hash) == 60)
+				return $hash;
+		}
+
+		if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) {
+			if (strlen($random) < 3)
+				$random = $this->get_random_bytes(3);
+			$hash =
+			    crypt($password, $this->gensalt_extended($random));
+			if (strlen($hash) == 20)
+				return $hash;
+		}
+
+		if (strlen($random) < 6)
+			$random = $this->get_random_bytes(6);
+		$hash =
+		    $this->crypt_private($password,
+		    $this->gensalt_private($random));
+		if (strlen($hash) == 34)
+			return $hash;
+
+		# Returning '*' on error is safe here, but would _not_ be safe
+		# in a crypt(3)-like function used _both_ for generating new
+		# hashes and for validating passwords against existing hashes.
+		return '*';
+	}
+
+	function CheckPassword($password, $stored_hash)
+	{
+		$hash = $this->crypt_private($password, $stored_hash);
+		if ($hash[0] == '*')
+			$hash = crypt($password, $stored_hash);
+
+		return $hash == $stored_hash;
+	}
+}
+
+?>
diff --git a/modules/user/libraries/drivers/IdentityProvider/Gallery.php b/modules/user/libraries/drivers/IdentityProvider/Gallery.php
new file mode 100644
index 0000000..67da33d
--- /dev/null
+++ b/modules/user/libraries/drivers/IdentityProvider/Gallery.php
@@ -0,0 +1,164 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+/*
+ * Based on the Cache_Sqlite_Driver developed by the Kohana Team
+ */
+class IdentityProvider_Gallery_Driver implements IdentityProvider_Driver {
+  /**
+   * @see IdentityProvider_Driver::guest.
+   */
+  public function guest() {
+    return user::guest();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::guest.
+   */
+  public function admin_user() {
+    return user::admin_user();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::create_user.
+   */
+  public function create_user($name, $full_name, $password, $email) {
+    $user = ORM::factory("user");
+    $user->name = $name;
+    $user->full_name = $full_name;
+    $user->password = $password;
+    $user->email = $email;
+    return $user->save();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::is_correct_password.
+   */
+  public function is_correct_password($user, $password) {
+    $valid = $user->password;
+
+    // Try phpass first, since that's what we generate.
+    if (strlen($valid) == 34) {
+      require_once(MODPATH . "user/lib/PasswordHash.php");
+      $hashGenerator = new PasswordHash(10, true);
+      return $hashGenerator->CheckPassword($password, $valid);
+    }
+
+    $salt = substr($valid, 0, 4);
+    // Support both old (G1 thru 1.4.0; G2 thru alpha-4) and new password schemes:
+    $guess = (strlen($valid) == 32) ? md5($password) : ($salt . md5($salt . $password));
+    if (!strcmp($guess, $valid)) {
+      return true;
+    }
+
+    // Passwords with <&"> created by G2 prior to 2.1 were hashed with entities
+    $sanitizedPassword = html::chars($password, false);
+    $guess = (strlen($valid) == 32) ? md5($sanitizedPassword)
+          : ($salt . md5($salt . $sanitizedPassword));
+    if (!strcmp($guess, $valid)) {
+      return true;
+    }
+
+    return false;
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_user.
+   */
+  public function lookup_user($id) {
+    return user::lookup($id);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_user_by_name.
+   */
+  public function lookup_user_by_name($name) {
+    return user::lookup_by_name($name);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::create_group.
+   */
+  public function create_group($name) {
+    $group = ORM::factory("group");
+    $group->name = $name;
+    return $group->save();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::everybody.
+   */
+  public function everybody() {
+    return group::everybody();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::registered_users.
+   */
+  public function registered_users() {
+    return group::registered_users();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_group.
+   */
+  public function lookup_group($id) {
+    return group::lookup($id);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::lookup_group_by_name.
+   */
+  public function lookup_group_by_name($name) {
+    return group::lookup_by_name($name);
+  }
+
+  /**
+   * @see IdentityProvider_Driver::get_user_list.
+   */
+  public function get_user_list($ids) {
+    return ORM::factory("user")
+      ->where("id", "IN", $ids)
+      ->find_all();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::groups.
+   */
+  public function groups() {
+    return ORM::factory("group")->find_all();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::add_user_to_group.
+   */
+  public function add_user_to_group($user, $group) {
+    $group->add($user);
+    $group->save();
+  }
+
+  /**
+   * @see IdentityProvider_Driver::remove_user_to_group.
+   */
+  public function remove_user_from_group($user, $group) {
+    $group->remove($user);
+    $group->save();
+  }
+} // End Identity Gallery Driver
+
diff --git a/modules/user/models/group.php b/modules/user/models/group.php
new file mode 100644
index 0000000..a5d7c5b
--- /dev/null
+++ b/modules/user/models/group.php
@@ -0,0 +1,89 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Group_Model_Core extends ORM implements Group_Definition {
+  protected $has_and_belongs_to_many = array("users");
+  protected $users_cache = null;
+
+  /**
+   * @see ORM::delete()
+   */
+  public function delete($id=null) {
+    $old = clone $this;
+    module::event("group_before_delete", $this);
+    parent::delete($id);
+
+    db::build()
+      ->delete("groups_users")
+      ->where("group_id", "=", empty($id) ? $old->id : $id)
+      ->execute();
+
+    module::event("group_deleted", $old);
+    $this->users_cache = null;
+  }
+
+  public function users() {
+    if (!$this->users_cache) {
+      $this->users_cache = $this->users->find_all()->as_array();
+    }
+    return $this->users_cache;
+  }
+
+  /**
+   * Specify our rules here so that we have access to the instance of this model.
+   */
+  public function validate(Validation $array=null) {
+    // validate() is recursive, only modify the rules on the outermost call.
+    if (!$array) {
+      $this->rules = array(
+        "name" => array("rules" => array("required", "length[1,255]"),
+                        "callbacks" => array(array($this, "valid_name"))));
+    }
+
+    parent::validate($array);
+  }
+
+  public function save() {
+    if (!$this->loaded()) {
+      // New group
+      parent::save();
+      module::event("group_created", $this);
+    } else {
+      // Updated group
+      $original = ORM::factory("group", $this->id);
+      parent::save();
+      module::event("group_updated", $original, $this);
+    }
+
+    $this->users_cache = null;
+    return $this;
+  }
+
+  /**
+   * Validate the user name.  Make sure there are no conflicts.
+   */
+  public function valid_name(Validation $v, $field) {
+    if (db::build()->from("groups")
+        ->where("name", "=", $this->name)
+        ->where("id", "<>", $this->id)
+        ->count_records() == 1) {
+      $v->add_error("name", "conflict");
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/user/models/user.php b/modules/user/models/user.php
new file mode 100644
index 0000000..af05c0c
--- /dev/null
+++ b/modules/user/models/user.php
@@ -0,0 +1,185 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class User_Model_Core extends ORM implements User_Definition {
+  protected $has_and_belongs_to_many = array("groups");
+  protected $password_length = null;
+  protected $groups_cache = null;
+
+  public function __set($column, $value) {
+    switch ($column) {
+    case "hashed_password":
+      $column = "password";
+      break;
+
+    case "password":
+      $this->password_length = strlen($value);
+      $value = user::hash_password($value);
+      break;
+    }
+    parent::__set($column, $value);
+  }
+
+  /**
+   * @see ORM::delete()
+   */
+  public function delete($id=null) {
+    $old = clone $this;
+    module::event("user_before_delete", $this);
+    parent::delete($id);
+
+    db::build()
+      ->delete("groups_users")
+      ->where("user_id", "=", empty($id) ? $old->id : $id)
+      ->execute();
+
+    module::event("user_deleted", $old);
+    $this->groups_cache = null;
+  }
+
+  /**
+   * Return a url to the user's avatar image.
+   * @param integer $size the target size of the image (default 80px)
+   * @return string a url
+   */
+  public function avatar_url($size=80, $default=null) {
+    return sprintf("http://www.gravatar.com/avatar/%s.jpg?s=%d&r=pg%s",
+                   md5($this->email), $size, $default ? "&d=" . urlencode($default) : "");
+  }
+
+  public function groups() {
+    if (!$this->groups_cache) {
+      $this->groups_cache = $this->groups->find_all()->as_array();
+    }
+    return $this->groups_cache;
+  }
+
+  /**
+   * Specify our rules here so that we have access to the instance of this model.
+   */
+  public function validate(Validation $array=null) {
+    // validate() is recursive, only modify the rules on the outermost call.
+    if (!$array) {
+      $this->rules = array(
+        "admin"     => array("callbacks" => array(array($this, "valid_admin"))),
+        "email"     => array("rules"     => array("length[1,255]", "valid::email"),
+                             "callbacks" => array(array($this, "valid_email"))),
+        "full_name" => array("rules"     => array("length[0,255]")),
+        "locale"    => array("rules"     => array("length[2,10]")),
+        "name"      => array("rules"     => array("length[1,32]", "required"),
+                             "callbacks" => array(array($this, "valid_name"))),
+        "password"  => array("callbacks" => array(array($this, "valid_password"))),
+        "url"       => array("rules"     => array("valid::url")),
+      );
+    }
+
+    parent::validate($array);
+  }
+
+  /**
+   * Handle any business logic necessary to create or update a user.
+   * @see ORM::save()
+   *
+   * @return ORM User_Model
+   */
+  public function save() {
+    if ($this->full_name === null) {
+      $this->full_name = "";
+    }
+
+    if (!$this->loaded()) {
+      // New user
+      $this->add(group::everybody());
+      if (!$this->guest) {
+        $this->add(group::registered_users());
+      }
+
+      parent::save();
+      module::event("user_created", $this);
+    } else {
+      // Updated user
+      $original = ORM::factory("user", $this->id);
+      parent::save();
+      module::event("user_updated", $original, $this);
+    }
+
+    $this->groups_cache = null;
+    return $this;
+  }
+
+  /**
+   * Return the best version of the user's name.  Either their specified full name, or fall back
+   * to the user name.
+   * @return string
+   */
+  public function display_name() {
+    return empty($this->full_name) ? $this->name : $this->full_name;
+  }
+
+  /**
+   * Validate the user name.  Make sure there are no conflicts.
+   */
+  public function valid_name(Validation $v, $field) {
+    if (db::build()->from("users")
+        ->where("name", "=", $this->name)
+        ->merge_where($this->id ? array(array("id", "<>", $this->id)) : null)
+        ->count_records() == 1) {
+      $v->add_error("name", "conflict");
+    }
+  }
+
+  /**
+   * Validate the password.
+   */
+  public function valid_password(Validation $v, $field) {
+    if ($this->guest) {
+      return;
+    }
+
+    if (!$this->loaded() || isset($this->password_length)) {
+      $minimum_length = module::get_var("user", "minimum_password_length", 5);
+      if ($this->password_length < $minimum_length) {
+        $v->add_error("password", "min_length");
+      }
+    }
+  }
+
+  /**
+   * Validate the admin bit.
+   */
+  public function valid_admin(Validation $v, $field) {
+    $active = identity::active_user();
+    if ($this->id == $active->id && $active->admin && !$this->admin) {
+      $v->add_error("admin", "locked");
+    }
+  }
+
+  /**
+   * Validate the email field.
+   */
+  public function valid_email(Validation $v, $field) {
+    if ($this->guest) {  // guests don't require an email address
+      return;
+    }
+
+    if (empty($this->email)) {
+      $v->add_error("email", "required");
+    }
+  }
+}
diff --git a/modules/user/module.info b/modules/user/module.info
new file mode 100644
index 0000000..d5128db
--- /dev/null
+++ b/modules/user/module.info
@@ -0,0 +1,8 @@
+name = "Users and Groups"
+description = "Gallery 3 user and group management"
+version = 4
+
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:user"
+discuss_url = "http://galleryproject.org/forum_module_user"
diff --git a/modules/user/views/admin_users.html.php b/modules/user/views/admin_users.html.php
new file mode 100644
index 0000000..033c9da
--- /dev/null
+++ b/modules/user/views/admin_users.html.php
@@ -0,0 +1,142 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  var add_user_to_group_url = "<?= url::site("admin/users/add_user_to_group/__USERID__/__GROUPID__?csrf=$csrf") ?>";
+  $(document).ready(function(){
+    $("#g-user-admin-list .g-core-info").draggable({
+      helper: "clone"
+    });
+    $("#g-group-admin .g-group").droppable({
+      accept: ".g-core-info",
+      hoverClass: "g-selected",
+      drop: function(ev, ui) {
+        var user_id = $(ui.draggable).attr("id").replace("g-user-", "");
+        var group_id = $(this).attr("id").replace("g-group-", "");
+        $.get(add_user_to_group_url.replace("__USERID__", user_id).replace("__GROUPID__", group_id),
+              {},
+              function() {
+                reload_group(group_id);
+              });
+      }
+    });
+    $("#g-group-1").droppable("destroy");
+    $("#g-group-2").droppable("destroy");
+  });
+
+  var reload_group = function(group_id) {
+    var reload_group_url = "<?= url::site("admin/users/group/__GROUPID__") ?>";
+    $.get(reload_group_url.replace("__GROUPID__", group_id),
+          {},
+          function(data) {
+            $("#g-group-" + group_id).html(data);
+            $("#g-group-" + group_id + " .g-dialog-link").gallery_dialog();
+          });
+  }
+
+  var remove_user = function(user_id, group_id) {
+    var remove_user_url = "<?= url::site("admin/users/remove_user_from_group/__USERID__/__GROUPID__?csrf=$csrf") ?>";
+    $.get(remove_user_url.replace("__USERID__", user_id).replace("__GROUPID__", group_id),
+          {},
+          function() {
+            reload_group(group_id);
+          });
+  }
+</script>
+
+<div class="g-block">
+  <h1> <?= t("Users and groups") ?> </h1>
+
+  <div class="g-block-content">
+
+    <div id="g-user-admin" class="g-block">
+      <a href="<?= url::site("admin/users/add_user_form") ?>"
+          class="g-dialog-link g-button g-right ui-icon-left ui-state-default ui-corner-all"
+          title="<?= t("Create a new user")->for_html_attr() ?>">
+        <span class="ui-icon ui-icon-circle-plus"></span>
+        <?= t("Add a new user") ?>
+      </a>
+
+      <h2> <?= t("Users") ?> </h2>
+
+      <div class="g-block-content">
+        <table id="g-user-admin-list">
+          <tr>
+            <th><?= t("Username") ?></th>
+            <th><?= t("Full name") ?></th>
+            <th><?= t("Email") ?></th>
+            <th><?= t("Last login") ?></th>
+            <th><?= t("Albums/Photos") ?></th>
+            <th><?= t("Actions") ?></th>
+          </tr>
+
+          <? foreach ($users as $i => $user): ?>
+          <tr id="g-user-<?= $user->id ?>" class="<?= text::alternate("g-odd", "g-even") ?> g-user <?= $user->admin ? "g-admin" : "" ?>">
+            <td id="g-user-<?= $user->id ?>" class="g-core-info g-draggable">
+              <img src="<?= $user->avatar_url(20, $theme->url("images/avatar.jpg", true)) ?>"
+                   title="<?= t("Drag user onto a group to add as a new member")->for_html_attr() ?>"
+                   alt="<?= html::clean_attribute($user->name) ?>"
+                   width="20"
+                   height="20" />
+              <?= html::clean($user->name) ?>
+            </td>
+            <td>
+              <?= html::clean($user->full_name) ?>
+            </td>
+            <td>
+              <?= html::clean($user->email) ?>
+            </td>
+            <td>
+              <?= ($user->last_login == 0) ? "" : gallery::date($user->last_login) ?>
+            </td>
+            <td>
+              <?= db::build()->from("items")->where("owner_id", "=", $user->id)->count_records() ?>
+            </td>
+            <td>
+              <a href="<?= url::site("admin/users/edit_user_form/$user->id") ?>"
+                  open_text="<?= t("Close") ?>"
+                  class="g-panel-link g-button ui-state-default ui-corner-all ui-icon-left">
+                <span class="ui-icon ui-icon-pencil"></span><span class="g-button-text"><?= t("Edit") ?></span></a>
+              <? if (identity::active_user()->id != $user->id && !$user->guest): ?>
+              <a href="<?= url::site("admin/users/delete_user_form/$user->id") ?>"
+                  class="g-dialog-link g-button ui-state-default ui-corner-all ui-icon-left">
+                <span class="ui-icon ui-icon-trash"></span><?= t("Delete") ?></a>
+              <? else: ?>
+              <span title="<?= t("This user cannot be deleted")->for_html_attr() ?>"
+                  class="g-button ui-state-disabled ui-corner-all ui-icon-left">
+                <span class="ui-icon ui-icon-trash"></span><?= t("Delete") ?></span>
+              <? endif ?>
+            </td>
+          </tr>
+          <? endforeach ?>
+        </table>
+
+        <div class="g-paginator">
+          <?= $theme->paginator() ?>
+        </div>
+
+      </div>
+    </div>
+
+    <div id="g-group-admin" class="g-block ui-helper-clearfix">
+      <a href="<?= url::site("admin/users/add_group_form") ?>"
+          class="g-dialog-link g-button g-right ui-icon-left ui-state-default ui-corner-all"
+          title="<?= t("Create a new group")->for_html_attr() ?>">
+        <span class="ui-icon ui-icon-circle-plus"></span>
+        <?= t("Add a new group") ?>
+      </a>
+
+      <h2> <?= t("Groups") ?> </h2>
+
+      <div class="g-block-content">
+        <ul>
+          <? foreach ($groups as $i => $group): ?>
+          <li id="g-group-<?= $group->id ?>" class="g-group g-left <?= ($group->special ? "g-default-group" : "") ?>">
+            <? $v = new View("admin_users_group.html"); $v->group = $group; ?>
+            <?= $v ?>
+          </li>
+          <? endforeach ?>
+        </ul>
+      </div>
+    </div>
+
+  </div>
+</div>
diff --git a/modules/user/views/admin_users_delete_user.html.php b/modules/user/views/admin_users_delete_user.html.php
new file mode 100644
index 0000000..44777ae
--- /dev/null
+++ b/modules/user/views/admin_users_delete_user.html.php
@@ -0,0 +1,7 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-admin-users-delete-user">
+  <p>
+    <?= t("Really delete <b>%name</b>?  Any photos, movies or albums owned by this user will transfer ownership to <b>%new_owner</b>.", array("name" => $user->display_name(), "new_owner" => identity::active_user()->display_name())) ?>
+  </p>
+  <?= $form ?>
+</div>
diff --git a/modules/user/views/admin_users_group.html.php b/modules/user/views/admin_users_group.html.php
new file mode 100644
index 0000000..31b9135
--- /dev/null
+++ b/modules/user/views/admin_users_group.html.php
@@ -0,0 +1,40 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h4>
+  <a href="<?= url::site("admin/users/edit_group_form/$group->id") ?>"
+   title="<?= t("Edit the %name group's name", array("name" => $group->name))->for_html_attr() ?>"
+   class="g-dialog-link"><?= html::clean($group->name) ?></a>
+  <? if (!$group->special): ?>
+  <a href="<?= url::site("admin/users/delete_group_form/$group->id") ?>"
+    title="<?= t("Delete the %name group", array("name" => $group->name))->for_html_attr() ?>"
+    class="g-dialog-link g-button g-right">
+    <span class="ui-icon ui-icon-trash"><?= t("Delete") ?></span></a>
+  <? else: ?>
+  <a title="<?= t("This default group cannot be deleted")->for_html_attr() ?>"
+     class="g-button g-right ui-state-disabled ui-icon-left">
+    <span class="ui-icon ui-icon-trash"><?= t("Delete") ?></span></a>
+  <? endif ?>
+</h4>
+
+<? if ($group->users->count_all() > 0): ?>
+<ul class="g-member-list">
+  <? foreach ($group->users->order_by("name", "ASC")->find_all() as $i => $user): ?>
+  <li class="g-user">
+    <?= html::clean($user->name) ?>
+    <? if (!$group->special): ?>
+    <a href="javascript:remove_user(<?= $user->id ?>, <?= $group->id ?>)"
+       class="g-button g-right ui-state-default ui-corner-all ui-icon-left"
+       title="<?= t("Remove %user from %group group",
+              array("user" => $user->name, "group" => $group->name))->for_html_attr() ?>">
+      <span class="ui-icon ui-icon-closethick"><?= t("Remove") ?></span>
+    </a>
+    <? endif ?>
+  </li>
+  <? endforeach ?>
+</ul>
+<? else: ?>
+<div>
+  <p class="ui-state-disabled">
+    <?= t("Drag &amp; drop users from the \"Users\" list onto this group to add group members.") ?>
+  </p>
+</div>
+<? endif ?>
diff --git a/modules/user/views/reset_password.html.php b/modules/user/views/reset_password.html.php
new file mode 100644
index 0000000..d939ad4
--- /dev/null
+++ b/modules/user/views/reset_password.html.php
@@ -0,0 +1,18 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<html>
+  <head>
+    <title><?= t("Password reset request") ?> </title>
+  </head>
+  <body>
+    <h2><?= t("Password reset request") ?> </h2>
+    <p>
+      <?= t("Hello, %name,", array("name" => $user->full_name ? $user->full_name : $user->name)) ?>
+    </p>
+    <p>
+  <?= t("We received a request to reset your password for <a href=\"%site_url\">%base_url</a>.  If you made this request, you can confirm it by <a href=\"%confirm_url\">clicking this link</a>.  If you didn't request this password reset, it's ok to ignore this mail.",
+        array("site_url" => html::mark_clean(url::abs_site("/")),
+              "base_url" => html::mark_clean(url::base(false)),
+              "confirm_url" => $confirm_url)) ?>
+    </p>
+  </body>
+</html>
diff --git a/modules/watermark/controllers/admin_watermarks.php b/modules/watermark/controllers/admin_watermarks.php
new file mode 100644
index 0000000..222279e
--- /dev/null
+++ b/modules/watermark/controllers/admin_watermarks.php
@@ -0,0 +1,158 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class Admin_Watermarks_Controller extends Admin_Controller {
+  public function index() {
+    $name = module::get_var("watermark", "name");
+
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Watermarks");
+    $view->content = new View("admin_watermarks.html");
+    if ($name) {
+      $view->content->name = module::get_var("watermark", "name");
+      $view->content->url = url::file("var/modules/watermark/$name");
+      $view->content->width = module::get_var("watermark", "width");
+      $view->content->height = module::get_var("watermark", "height");
+      $view->content->position = module::get_var("watermark", "position");
+    }
+    print $view;
+  }
+
+  public function form_edit() {
+    print watermark::get_edit_form();
+  }
+
+  public function edit() {
+    access::verify_csrf();
+
+    $form = watermark::get_edit_form();
+    if ($form->validate()) {
+      module::set_var("watermark", "position", $form->edit_watermark->position->value);
+      module::set_var("watermark", "transparency", $form->edit_watermark->transparency->value);
+      $this->_update_graphics_rules();
+
+      log::success("watermark", t("Watermark changed"));
+      message::success(t("Watermark changed"));
+      json::reply(
+        array("result" => "success",
+              "location" => url::site("admin/watermarks")));
+    } else {
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function form_delete() {
+    print watermark::get_delete_form();
+  }
+
+  public function delete() {
+    access::verify_csrf();
+
+    $form = watermark::get_delete_form();
+    if ($form->validate()) {
+      if ($name = basename(module::get_var("watermark", "name"))) {
+        system::delete_later(VARPATH . "modules/watermark/$name");
+
+        module::clear_var("watermark", "name");
+        module::clear_var("watermark", "width");
+        module::clear_var("watermark", "height");
+        module::clear_var("watermark", "mime_type");
+        module::clear_var("watermark", "position");
+        $this->_update_graphics_rules();
+
+        log::success("watermark", t("Watermark deleted"));
+        message::success(t("Watermark deleted"));
+      }
+      json::reply(array("result" => "success", "location" => url::site("admin/watermarks")));
+    } else {
+      json::reply(array("result" => "error", "html" => (string)$form));
+    }
+  }
+
+  public function form_add() {
+    print watermark::get_add_form();
+  }
+
+  public function add() {
+    access::verify_csrf();
+
+    $form = watermark::get_add_form();
+    // For TEST_MODE, we want to simulate a file upload.  Because this is not a true upload, Forge's
+    // validation logic will correctly reject it.  So, we skip validation when we're running tests.
+    if (TEST_MODE || $form->validate()) {
+      $file = $_POST["file"];
+      // Forge prefixes files with "uploadfile-xxxxxxx" for uniqueness
+      $name = preg_replace("/uploadfile-[^-]+-(.*)/", '$1', basename($file));
+
+      try {
+        list ($width, $height, $mime_type, $extension) = photo::get_file_metadata($file);
+        // Sanitize filename, which ensures a valid extension.  This renaming prevents the issues
+        // addressed in ticket #1855, where an image that looked valid (header said jpg) with a
+        // php extension was previously accepted without changing its extension.
+        $name = legal_file::sanitize_filename($name, $extension, "photo");
+      } catch (Exception $e) {
+        message::error(t("Invalid or unidentifiable image file"));
+        system::delete_later($file);
+        return;
+      }
+
+      rename($file, VARPATH . "modules/watermark/$name");
+      module::set_var("watermark", "name", $name);
+      module::set_var("watermark", "width", $width);
+      module::set_var("watermark", "height", $height);
+      module::set_var("watermark", "mime_type", $mime_type);
+      module::set_var("watermark", "position", $form->add_watermark->position->value);
+      module::set_var("watermark", "transparency", $form->add_watermark->transparency->value);
+      $this->_update_graphics_rules();
+      system::delete_later($file);
+
+      message::success(t("Watermark saved"));
+      log::success("watermark", t("Watermark saved"));
+      json::reply(array("result" => "success", "location" => url::site("admin/watermarks")));
+    } else {
+      // rawurlencode the results because the JS code that uploads the file buffers it in an
+      // iframe which entitizes the HTML and makes it difficult for the JS to process.  If we url
+      // encode it now, it passes through cleanly.  See ticket #797.
+      json::reply(array("result" => "error", "html" => rawurlencode((string)$form)));
+    }
+
+    // Override the application/json mime type.  The dialog based HTML uploader uses an iframe to
+    // buffer the reply, and on some browsers (Firefox 3.6) it does not know what to do with the
+    // JSON that it gets back so it puts up a dialog asking the user what to do with it.  So force
+    // the encoding type back to HTML for the iframe.
+    // See: http://jquery.malsup.com/form/#file-upload
+    header("Content-Type: text/html; charset=" . Kohana::CHARSET);
+  }
+
+  private function _update_graphics_rules() {
+    graphics::remove_rules("watermark");
+    if ($name = module::get_var("watermark", "name")) {
+      foreach (array("thumb", "resize") as $target) {
+        graphics::add_rule(
+          "watermark", $target, "gallery_graphics::composite",
+          array("file" => VARPATH . "modules/watermark/$name",
+                "width" => module::get_var("watermark", "width"),
+                "height" => module::get_var("watermark", "height"),
+                "position" => module::get_var("watermark", "position"),
+                "transparency" => 101 - module::get_var("watermark", "transparency")),
+          1000);
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/modules/watermark/helpers/watermark.php b/modules/watermark/helpers/watermark.php
new file mode 100644
index 0000000..3357c14
--- /dev/null
+++ b/modules/watermark/helpers/watermark.php
@@ -0,0 +1,82 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class watermark_Core {
+  static function get_add_form() {
+    for ($i = 1; $i <= 100; $i++) {
+      $range[$i] = "$i%";
+    }
+
+    $form = new Forge("admin/watermarks/add", "", "post", array("id" => "g-add-watermark-form"));
+    $group = $form->group("add_watermark")->label(t("Upload watermark"));
+    $group->upload("file")->label(t("Watermark"))->rules("allow[jpg,png,gif]|size[1MB]|required")
+      ->error_messages("required", "You must select a watermark")
+      ->error_messages("invalid_type", "The watermark must be a JPG, GIF or PNG")
+      ->error_messages("max_size", "The watermark is too big (1 MB max)");
+    $group->dropdown("position")->label(t("Watermark position"))
+      ->options(self::positions())
+      ->selected("southeast");
+    $group->dropdown("transparency")->label(t("Transparency (100% = completely transparent)"))
+      ->options($range)
+      ->selected(1);
+    $group->submit("")->value(t("Upload"));
+    return $form;
+  }
+
+  static function get_edit_form() {
+    for ($i = 1; $i <= 100; $i++) {
+      $range[$i] = "$i%";
+    }
+
+    $form = new Forge("admin/watermarks/edit", "", "post", array("id" => "g-edit-watermark-form"));
+    $group = $form->group("edit_watermark")->label(t("Edit Watermark"));
+    $group->dropdown("position")->label(t("Watermark Position"))
+      ->options(self::positions())
+      ->selected(module::get_var("watermark", "position"));
+    $group->dropdown("transparency")->label(t("Transparency (100% = completely transparent)"))
+      ->options($range)
+      ->selected(module::get_var("watermark", "transparency"));
+    $group->submit("")->value(t("Save"));
+    return $form;
+  }
+
+  static function get_delete_form() {
+    $form = new Forge("admin/watermarks/delete", "", "post", array("id" => "g-delete-watermark-form"));
+    $group = $form->group("delete_watermark")->label(t("Really delete Watermark?"));
+    $group->submit("")->value(t("Delete"));
+    return $form;
+  }
+
+  static function positions() {
+    return array("northwest" => t("Northwest"),
+                 "north" => t("North"),
+                 "northeast" => t("Northeast"),
+                 "west" => t("West"),
+                 "center" => t("Center"),
+                 "east" => t("East"),
+                 "southwest" => t("Southwest"),
+                 "south" => t("South"),
+                 "southeast" => t("Southeast"));
+  }
+
+  static function position($key) {
+    $positions = self::positions();
+    return $positions[$key];
+  }
+}
\ No newline at end of file
diff --git a/modules/watermark/helpers/watermark_event.php b/modules/watermark/helpers/watermark_event.php
new file mode 100644
index 0000000..7547515
--- /dev/null
+++ b/modules/watermark/helpers/watermark_event.php
@@ -0,0 +1,29 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class watermark_event_Core {
+  static function admin_menu($menu, $theme) {
+    $menu->get("content_menu")
+      ->append(
+        Menu::factory("link")
+        ->id("watermarks")
+        ->label(t("Watermarks"))
+        ->url(url::site("admin/watermarks")));
+  }
+}
diff --git a/modules/watermark/helpers/watermark_installer.php b/modules/watermark/helpers/watermark_installer.php
new file mode 100644
index 0000000..1333891
--- /dev/null
+++ b/modules/watermark/helpers/watermark_installer.php
@@ -0,0 +1,42 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+class watermark_installer {
+  static function install() {
+    $db = Database::instance();
+    $db->query("CREATE TABLE IF NOT EXISTS {watermarks} (
+                 `id` int(9) NOT NULL auto_increment,
+                 `name` varchar(32) NOT NULL,
+                 `width` int(9) NOT NULL,
+                 `height` int(9) NOT NULL,
+                 `active` boolean default 0,
+                 `position` boolean default 0,
+                 `mime_type` varchar(64) default NULL,
+                 PRIMARY KEY (`id`),
+                 UNIQUE KEY(`name`))
+               DEFAULT CHARSET=utf8;");
+
+    @mkdir(VARPATH . "modules/watermark");
+  }
+
+  static function uninstall() {
+    Database::instance()->query("DROP TABLE {watermarks}");
+    dir::unlink(VARPATH . "modules/watermark");
+  }
+}
diff --git a/modules/watermark/module.info b/modules/watermark/module.info
new file mode 100644
index 0000000..e5003cd
--- /dev/null
+++ b/modules/watermark/module.info
@@ -0,0 +1,7 @@
+name = "Watermarks"
+description = "Allows users to watermark their photos"
+version = 2
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:watermark"
+discuss_url = "http://galleryproject.org/forum_module_watermark"
diff --git a/modules/watermark/views/admin_watermarks.html.php b/modules/watermark/views/admin_watermarks.html.php
new file mode 100644
index 0000000..fc634b8
--- /dev/null
+++ b/modules/watermark/views/admin_watermarks.html.php
@@ -0,0 +1,39 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="g-block">
+  <h1> <?= t("Watermarks") ?> </h1>
+  <p>
+    <?= t("You can have one watermark for your Gallery.  This watermark will be applied to all thumbnails and resized images, but it will not be applied to your full size images.  To make sure that your guests can only see watermarked images, you should restrict access to your full size images.") ?>
+  </p>
+
+  <div class="g-block-content">
+    <? if (empty($name)): ?>
+    <a href="<?= url::site("admin/watermarks/form_add") ?>"
+       title="<?= t("Upload a watermark")->for_html_attr() ?>"
+       class="g-dialog-link g-button ui-icon-left ui-state-default ui-corner-all"><span class="ui-icon ui-icon-document-b"></span><?= t("Upload a watermark") ?></a>
+    <? else: ?>
+    <h2> <?= t("Active watermark") ?> </h2>
+    <p>
+      <?= t("Note that changing this watermark will require you to rebuild all of your thumbnails and resized images.") ?>
+    </p>
+    <div>
+      <div class="g-photo">
+        <img width="<?= $width ?>" height="<?= $height ?>" src="<?= $url ?>" />
+        <p>
+          <?= t("Position: %position", array("position" => watermark::position($position))) ?>
+        </p>
+        <p>
+          <?= t("Transparency: %transparency%", array("transparency" => module::get_var("watermark", "transparency"))) ?>
+        </p>
+      </div>
+      <div class="controls">
+        <a href="<?= url::site("admin/watermarks/form_edit") ?>"
+           title="<?= t("Edit watermark")->for_html_attr() ?>"
+           class="g-dialog-link g-button ui-icon-left ui-state-default ui-corner-all"><span class="ui-icon ui-icon-pencil"></span><?= t("edit") ?></a>
+        <a href="<?= url::site("admin/watermarks/form_delete") ?>"
+           title="<?= t("Delete watermark")->for_html_attr() ?>"
+           class="g-dialog-link g-button ui-icon-left ui-state-default ui-corner-all"><span class="ui-icon ui-icon-trash"></span><?= t("delete") ?></a>
+      </div>
+    </div>
+    <? endif ?>
+  </div>
+</div>
diff --git a/php.ini b/php.ini
new file mode 100644
index 0000000..d2f96f5
--- /dev/null
+++ b/php.ini
@@ -0,0 +1,19 @@
+; Set some reasonable defaults for PHP.  Most of these cannot be set
+; inside the script itself.  These settings are mirrored in the
+; .htaccess file for hosts that support .htaccess but not per-dir
+; php.ini files.
+;
+[PHP]
+short_open_tag = On
+magic_quotes_gpc = Off
+magic_quotes_sybase = Off
+magic_quotes_runtime = Off
+register_globals = Off
+upload_max_filesize = 20M
+post_max_size = 100M
+
+[Session]
+session.auto_start = Off
+
+[suhosin]
+suhosin.session.encrypt = Off
diff --git a/robots.txt b/robots.txt
new file mode 100644
index 0000000..000aac9
--- /dev/null
+++ b/robots.txt
@@ -0,0 +1,14 @@
+User-agent: *
+Disallow: /application/
+Disallow: /installer/
+Disallow: /lib/
+Disallow: /modules/
+Disallow: /system/
+Disallow: /themes/
+Disallow: /var/logs/
+Disallow: /var/modules/
+Disallow: /var/resizes/
+Disallow: /var/thumbs/
+Disallow: /var/tmp/
+Disallow: /var/uploads/
+Disallow: /digibug/print_photo/
diff --git a/serveradd/Raphael_2013-10-18_optimiert.mpg b/serveradd/Raphael_2013-10-18_optimiert.mpg
new file mode 100644
index 0000000..5c1cff3
Binary files /dev/null and b/serveradd/Raphael_2013-10-18_optimiert.mpg differ
diff --git a/system/KohanaLicense.html b/system/KohanaLicense.html
new file mode 100644
index 0000000..bc4bce2
--- /dev/null
+++ b/system/KohanaLicense.html
@@ -0,0 +1,30 @@
+<!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" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+<title>Kohana License</title>
+
+</head>
+<body>
+
+<h2>Kohana License Agreement</h2>
+
+<p>This license is a legal agreement between you and the Kohana Software Foundation for the use of Kohana Framework (the "Software"). By obtaining the Software you agree to comply with the terms and conditions of this license.</p>
+
+<p>Copyright (c) 2007-2009 Kohana Team<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>
+
+<ul>
+<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 the Kohana nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.</li>
+</ul>
+
+<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>
+
+<p><small>NOTE: This license is modeled after the BSD software license.</small></p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/system/config/cache.php b/system/config/cache.php
new file mode 100644
index 0000000..6b2f787
--- /dev/null
+++ b/system/config/cache.php
@@ -0,0 +1,37 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Cache settings, defined as arrays, or "groups". If no group name is
+ * used when loading the cache library, the group named "default" will be used.
+ *
+ * Each group can be used independently, and multiple groups can be used at once.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * Group Options:
+ *
+ * - driver   - Cache backend driver. Kohana comes with file, database, and memcache drivers.
+ *  -   File cache is fast and reliable, but requires many filesystem lookups.
+ *  -   Database cache can be used to cache items remotely, but is slower.
+ *  -   Memcache is very high performance, but prevents cache tags from being used.
+ *
+ * - params   - Driver parameters, specific to each driver.
+ *
+ * - lifetime - Default lifetime of caches in seconds. By default caches are stored for
+ *             thirty minutes. Specific lifetime can also be set when creating a new cache.
+ *             Setting this to 0 will never automatically delete caches.
+ *
+ * -  prefix   - Adds a prefix to all keys and tags. This can have a severe performance impact.
+ *
+ */
+$config['default'] = array
+(
+	'driver'   => 'file',
+	'params'   => array('directory' => APPPATH.'cache', 'gc_probability' => 1000),
+	'lifetime' => 1800,
+	'prefix'   => NULL
+);
diff --git a/system/config/cookie.php b/system/config/cookie.php
new file mode 100644
index 0000000..5340f05
--- /dev/null
+++ b/system/config/cookie.php
@@ -0,0 +1,55 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Cookie config settings. These are the default settings used by the [cookie]
+ * helper. You can override these settings by passing parameters to the cookie
+ * helper functions.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * Domain, to restrict the cookie to a specific website domain. For security,
+ * you are encouraged to set this option. An empty setting allows the cookie
+ * to be read by any website domain.
+ * @default ''
+ */
+$config['domain'] = '';
+
+/**
+ * Restrict cookies to a specific path, typically the installation directory.
+ * @default '/'
+ */
+$config['path'] = '/';
+
+/**
+ * Lifetime of the cookie. A setting of 0 makes the cookie active until the
+ * users browser is closed or the cookie is deleted.
+ * @default = 0
+ */
+$config['expire'] = 0;
+
+/**
+ * Enable this option to only allow the cookie to be read when using the a
+ * secure protocol.
+ * @default FALSE
+ */
+$config['secure'] = FALSE;
+
+/**
+ * Enable this option to make the cookie accessible only through the
+ * HTTP protocol (e.g. no javascript access). This is not supported by all browsers.
+ * @default FALSE
+ */
+$config['httponly'] = FALSE;
+
+/**
+ * Cookie salt for signed cookies.
+ * Make sure you change this to a unique value.
+ *
+ * [!!] Changing this value will invalidate all existing cookies!
+ * @default 'K0hAN4 15 Th3 B357'
+ */
+$config['salt'] = 'K0hAN4 15 Th3 B357';
\ No newline at end of file
diff --git a/system/config/credit_cards.php b/system/config/credit_cards.php
new file mode 100644
index 0000000..46c6afb
--- /dev/null
+++ b/system/config/credit_cards.php
@@ -0,0 +1,70 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Credit card validation configuration.
+ *
+ * Options for each credit card:
+ *
+ * - length - All the allowed card number lengths, in a comma separated string
+ * - prefix - The digits the card needs to start with, in regex format
+ * - luhn   - Enable or disable card number validation by the Luhn algorithm
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * Default credit card configuration
+ */
+$config = array
+(
+	'default' => array
+	(
+		'length' => '13,14,15,16,17,18,19',
+		'prefix' => '',
+		'luhn'   => TRUE
+	),
+	'american express' => array
+	(
+		'length' => '15',
+		'prefix' => '3[47]',
+		'luhn'   => TRUE
+	),
+	'diners club' => array
+	(
+		'length' => '14,16',
+		'prefix' => '36|55|30[0-5]',
+		'luhn'   => TRUE
+	),
+	'discover' => array
+	(
+		'length' => '16',
+		'prefix' => '6(?:5|011)',
+		'luhn'   => TRUE,
+	),
+	'jcb' => array
+	(
+		'length' => '15,16',
+		'prefix' => '3|1800|2131',
+		'luhn'   => TRUE
+	),
+	'maestro' => array
+	(
+		'length' => '16,18',
+		'prefix' => '50(?:20|38)|6(?:304|759)',
+		'luhn'   => TRUE
+	),
+	'mastercard' => array
+	(
+		'length' => '16',
+		'prefix' => '5[1-5]',
+		'luhn'   => TRUE
+	),
+	'visa' => array
+	(
+		'length' => '13,16',
+		'prefix' => '4',
+		'luhn'   => TRUE
+	),
+);
\ No newline at end of file
diff --git a/system/config/database.php b/system/config/database.php
new file mode 100644
index 0000000..dd6bf46
--- /dev/null
+++ b/system/config/database.php
@@ -0,0 +1,53 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Database connection settings, defined as arrays, or "groups". If no group
+ * name is used when loading the database library, the group named "default"
+ * will be used.
+ *
+ * Each group can be connected to independently, and multiple groups can be
+ * connected at once. For more information about connecting to a database group
+ * see the [Database] library.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * Group Options:
+ *
+ *  - benchmark     - Enable or disable database benchmarking
+ *  - persistent    - Enable or disable a persistent connection
+ *  - connection    - Array of connection specific parameters; alternatively,
+ *                  you can use a DSN though it is not as fast and certain
+ *                  characters could create problems (like an '@' character
+ *                  in a password):
+ *                  'connection'    => 'mysql://dbuser:secret@localhost/kohana'
+ *  - character_set - Database character set
+ *  - table_prefix  - Database table prefix
+ *  - object        - Enable or disable object results
+ *  - cache         - Enable or disable query caching
+ *  - escape        - Enable automatic query builder escaping
+ */
+$config['default'] = array
+(
+	'benchmark'     => FALSE,
+	'persistent'    => FALSE,
+	'connection'    => array
+	(
+		'type'     => 'mysql',
+		'user'     => 'dbuser',
+		'pass'     => 'p@ssw0rd',
+		'host'     => 'localhost',
+		'port'     => FALSE,
+		'socket'   => FALSE,
+		'database' => 'kohana',
+		'params'   => NULL,
+	),
+	'character_set' => 'utf8',
+	'table_prefix'  => '',
+	'object'        => TRUE,
+	'cache'         => FALSE,
+	'escape'        => TRUE
+);
\ No newline at end of file
diff --git a/system/config/encryption.php b/system/config/encryption.php
new file mode 100644
index 0000000..12ff7ae
--- /dev/null
+++ b/system/config/encryption.php
@@ -0,0 +1,39 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Encrypt configuration is defined in groups which allows you to easily switch
+ * between different encryption settings for different uses.
+ *
+ * [!!] All groups inherit and overwrite the default group.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * Group Options:
+ *
+ *  For best security, your encryption key should be at least 16 characters
+ *  long and contain letters, numbers, and symbols.
+ *
+ * - key    - Encryption key used to do encryption and decryption. The default option
+ *           should never be used for a production website.
+ *
+ *  [!!] Do not use a hash as your key. This significantly lowers encryption entropy.
+ *
+ * - mode   - MCrypt encryption mode. By default, MCRYPT_MODE_NOFB is used. This mode
+ *           offers initialization vector support, is suited to short strings, and
+ *           produces the shortest encrypted output.
+ *
+ * - cipher - MCrypt encryption cipher. By default, the MCRYPT_RIJNDAEL_128 cipher is used.
+ *           This is also known as 128-bit AES.
+ *
+ * 	For more information about mcrypt modes and cipers see the [mcrypt php docs](http://php.net/mcrypt).
+ */
+$config['default'] = array
+(
+	'key'    => 'K0H@NA+PHP_7hE-SW!FtFraM3w0R|<',
+	'mode'   => MCRYPT_MODE_NOFB,
+	'cipher' => MCRYPT_RIJNDAEL_128
+);
diff --git a/system/config/http.php b/system/config/http.php
new file mode 100644
index 0000000..7cc11dd
--- /dev/null
+++ b/system/config/http.php
@@ -0,0 +1,30 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * HTTP Config
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * HTTP-EQUIV type meta tags
+ *
+ */
+$config['meta_equiv'] = array
+(
+	'cache-control',
+	'content-type', 'content-script-type', 'content-style-type',
+	'content-disposition',
+	'content-language',
+	'default-style',
+	'expires',
+	'ext-cache',
+	'pics-label',
+	'pragma',
+	'refresh',
+	'set-cookie',
+	'vary',
+	'window-target',
+);
\ No newline at end of file
diff --git a/system/config/image.php b/system/config/image.php
new file mode 100644
index 0000000..976315c
--- /dev/null
+++ b/system/config/image.php
@@ -0,0 +1,22 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Image library config
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * Image driver
+ *
+ * @default: 'GD'
+ */
+$config['driver'] = 'GD';
+
+/**
+ * Driver parameters:
+ * ImageMagick - set the "directory" parameter to your ImageMagick installation directory
+ */
+$config['params'] = array();
\ No newline at end of file
diff --git a/system/config/inflector.php b/system/config/inflector.php
new file mode 100644
index 0000000..70744f5
--- /dev/null
+++ b/system/config/inflector.php
@@ -0,0 +1,70 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Inflector Config. Lists of words that are uncountable or irregular.
+ * If you would like to add a word to these lists please open a new issue on the
+ * [issue tracker](http://dev.kohanaphp.com/projects/kohana2/issues)
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+$config['uncountable'] = array
+(
+	'access',
+	'advice',
+	'art',
+	'baggage',
+	'dances',
+	'data',
+	'equipment',
+	'fish',
+	'fuel',
+	'furniture',
+	'food',
+	'heat',
+	'honey',
+	'homework',
+	'impatience',
+	'information',
+	'knowledge',
+	'luggage',
+	'metadata',
+	'money',
+	'music',
+	'news',
+	'patience',
+	'progress',
+	'pollution',
+	'research',
+	'rice',
+	'sand',
+	'series',
+	'sheep',
+	'sms',
+	'species',
+	'staff',
+	'toothpaste',
+	'traffic',
+	'understanding',
+	'water',
+	'weather',
+	'work',
+);
+
+$config['irregular'] = array
+(
+	'child' => 'children',
+	'clothes' => 'clothing',
+	'man' => 'men',
+	'movie' => 'movies',
+	'person' => 'people',
+	'woman' => 'women',
+	'mouse' => 'mice',
+	'goose' => 'geese',
+	'ox' => 'oxen',
+	'leaf' => 'leaves',
+	'course' => 'courses',
+	'size' => 'sizes',
+);
diff --git a/system/config/locale.php b/system/config/locale.php
new file mode 100644
index 0000000..3f73b8f
--- /dev/null
+++ b/system/config/locale.php
@@ -0,0 +1,26 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Set your default language and timezone here. For more information about
+ * i18n support see the [i18n] library.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * Default language locale name(s).
+ * First item must be a valid i18n directory name, subsequent items are alternative locales
+ * for OS's that don't support the first (e.g. Windows). The first valid locale in the array will be used.
+ * @see http://php.net/setlocale
+ */
+$config['language'] = array('en_US', 'English_United States');
+
+/**
+ * Locale timezone. Defaults to the timezone you have set in your php config
+ * 
+ * [!!] This cannot be left empty, a valid timezone is required!
+ * @see http://php.net/timezones
+ */
+$config['timezone'] = ini_get('date.timezone');
\ No newline at end of file
diff --git a/system/config/log.php b/system/config/log.php
new file mode 100644
index 0000000..3b43777
--- /dev/null
+++ b/system/config/log.php
@@ -0,0 +1,35 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Log Config
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * Different log levels
+ */
+$config['log_levels'] = array
+(
+	'error' => 1,
+	'alert' => 2,
+	'info'  => 3,
+	'debug' => 4,
+);
+
+/**
+ * See different log levels above
+ */
+$config['log_threshold'] = 1;
+
+/**
+ * Log Date format
+ */
+$config['date_format'] = 'Y-m-d H:i:s P';
+
+/**
+ * We can define multiple logging backends at the same time.
+ */
+$config['drivers'] = array('file');
\ No newline at end of file
diff --git a/system/config/mimes.php b/system/config/mimes.php
new file mode 100644
index 0000000..f8f8aaf
--- /dev/null
+++ b/system/config/mimes.php
@@ -0,0 +1,228 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * A list of mime types. Our list is generally more complete and accurate than
+ * the operating system MIME list.
+ *
+ * If there are any missing options, please create a ticket on our issue tracker,
+ * http://dev.kohanaphp.com/projects/kohana2. Be sure to give the filename and
+ * expected MIME type, as well as any additional information you can provide.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+$config = array
+(
+	'323'   => array('text/h323'),
+	'7z'    => array('application/x-7z-compressed'),
+	'abw'   => array('application/x-abiword'),
+	'acx'   => array('application/internet-property-stream'),
+	'ai'    => array('application/postscript'),
+	'aif'   => array('audio/x-aiff'),
+	'aifc'  => array('audio/x-aiff'),
+	'aiff'  => array('audio/x-aiff'),
+	'asf'   => array('video/x-ms-asf'),
+	'asr'   => array('video/x-ms-asf'),
+	'asx'   => array('video/x-ms-asf'),
+	'atom'  => array('application/atom+xml'),
+	'avi'   => array('video/avi', 'video/msvideo', 'video/x-msvideo'),
+	'bin'   => array('application/octet-stream','application/macbinary'),
+	'bmp'   => array('image/bmp'),
+	'c'     => array('text/x-csrc'),
+	'c++'   => array('text/x-c++src'),
+	'cab'   => array('application/x-cab'),
+	'cc'    => array('text/x-c++src'),
+	'cda'   => array('application/x-cdf'),
+	'class' => array('application/octet-stream'),
+	'cpp'   => array('text/x-c++src'),
+	'cpt'   => array('application/mac-compactpro'),
+	'csh'   => array('text/x-csh'),
+	'css'   => array('text/css'),
+	'csv'   => array('text/x-comma-separated-values', 'application/vnd.ms-excel', 'text/comma-separated-values', 'text/csv'),
+	'dbk'   => array('application/docbook+xml'),
+	'dcr'   => array('application/x-director'),
+	'deb'   => array('application/x-debian-package'),
+	'diff'  => array('text/x-diff'),
+	'dir'   => array('application/x-director'),
+	'divx'  => array('video/divx'),
+	'dll'   => array('application/octet-stream', 'application/x-msdos-program'),
+	'dmg'   => array('application/x-apple-diskimage'),
+	'dms'   => array('application/octet-stream'),
+	'doc'   => array('application/msword'),
+	'dvi'   => array('application/x-dvi'),
+	'dxr'   => array('application/x-director'),
+	'eml'   => array('message/rfc822'),
+	'eps'   => array('application/postscript'),
+	'evy'   => array('application/envoy'),
+	'exe'   => array('application/x-msdos-program', 'application/octet-stream'),
+	'fla'   => array('application/octet-stream'),
+	'flac'  => array('application/x-flac'),
+	'flc'   => array('video/flc'),
+	'fli'   => array('video/fli'),
+	'flv'   => array('video/x-flv'),
+	'gif'   => array('image/gif'),
+	'gtar'  => array('application/x-gtar'),
+	'gz'    => array('application/x-gzip'),
+	'h'     => array('text/x-chdr'),
+	'h++'   => array('text/x-c++hdr'),
+	'hh'    => array('text/x-c++hdr'),
+	'hpp'   => array('text/x-c++hdr'),
+	'hqx'   => array('application/mac-binhex40'),
+	'hs'    => array('text/x-haskell'),
+	'htm'   => array('text/html'),
+	'html'  => array('text/html'),
+	'ico'   => array('image/x-icon'),
+	'ics'   => array('text/calendar'),
+	'iii'   => array('application/x-iphone'),
+	'ins'   => array('application/x-internet-signup'),
+	'iso'   => array('application/x-iso9660-image'),
+	'isp'   => array('application/x-internet-signup'),
+	'jar'   => array('application/java-archive'),
+	'java'  => array('application/x-java-applet'),
+	'jpe'   => array('image/jpeg', 'image/pjpeg'),
+	'jpeg'  => array('image/jpeg', 'image/pjpeg'),
+	'jpg'   => array('image/jpeg', 'image/pjpeg'),
+	'js'    => array('application/x-javascript'),
+	'json'  => array('application/json'),
+	'latex' => array('application/x-latex'),
+	'lha'   => array('application/octet-stream'),
+	'log'   => array('text/plain', 'text/x-log'),
+	'lzh'   => array('application/octet-stream'),
+	'm4a'   => array('audio/mpeg'),
+	'm4p'   => array('video/mp4v-es'),
+	'm4v'   => array('video/mp4'),
+	'man'   => array('application/x-troff-man'),
+	'mdb'   => array('application/x-msaccess'),
+	'midi'  => array('audio/midi'),
+	'mid'   => array('audio/midi'),
+	'mif'   => array('application/vnd.mif'),
+	'mka'   => array('audio/x-matroska'),
+	'mkv'   => array('video/x-matroska'),
+	'mov'   => array('video/quicktime'),
+	'movie' => array('video/x-sgi-movie'),
+	'mp2'   => array('audio/mpeg'),
+	'mp3'   => array('audio/mpeg'),
+	'mp4'   => array('application/mp4','audio/mp4','video/mp4'),
+	'mpa'   => array('video/mpeg'),
+	'mpe'   => array('video/mpeg'),
+	'mpeg'  => array('video/mpeg'),
+	'mpg'   => array('video/mpeg'),
+	'mpg4'  => array('video/mp4'),
+	'mpga'  => array('audio/mpeg'),
+	'mpp'   => array('application/vnd.ms-project'),
+	'mpv'   => array('video/x-matroska'),
+	'mpv2'  => array('video/mpeg'),
+	'ms'    => array('application/x-troff-ms'),
+	'msg'   => array('application/msoutlook','application/x-msg'),
+	'msi'   => array('application/x-msi'),
+	'nws'   => array('message/rfc822'),
+	'oda'   => array('application/oda'),
+	'odb'   => array('application/vnd.oasis.opendocument.database'),
+	'odc'   => array('application/vnd.oasis.opendocument.chart'),
+	'odf'   => array('application/vnd.oasis.opendocument.forumla'),
+	'odg'   => array('application/vnd.oasis.opendocument.graphics'),
+	'odi'   => array('application/vnd.oasis.opendocument.image'),
+	'odm'   => array('application/vnd.oasis.opendocument.text-master'),
+	'odp'   => array('application/vnd.oasis.opendocument.presentation'),
+	'ods'   => array('application/vnd.oasis.opendocument.spreadsheet'),
+	'odt'   => array('application/vnd.oasis.opendocument.text'),
+	'oga'   => array('audio/ogg'),
+	'ogg'   => array('application/ogg'),
+	'ogv'   => array('video/ogg'),
+	'otg'   => array('application/vnd.oasis.opendocument.graphics-template'),
+	'oth'   => array('application/vnd.oasis.opendocument.web'),
+	'otp'   => array('application/vnd.oasis.opendocument.presentation-template'),
+	'ots'   => array('application/vnd.oasis.opendocument.spreadsheet-template'),
+	'ott'   => array('application/vnd.oasis.opendocument.template'),
+	'p'     => array('text/x-pascal'),
+	'pas'   => array('text/x-pascal'),
+	'patch' => array('text/x-diff'),
+	'pbm'   => array('image/x-portable-bitmap'),
+	'pdf'   => array('application/pdf', 'application/x-download'),
+	'php'   => array('application/x-httpd-php'),
+	'php3'  => array('application/x-httpd-php'),
+	'php4'  => array('application/x-httpd-php'),
+	'php5'  => array('application/x-httpd-php'),
+	'phps'  => array('application/x-httpd-php-source'),
+	'phtml' => array('application/x-httpd-php'),
+	'pl'    => array('text/x-perl'),
+	'pm'    => array('text/x-perl'),
+	'png'   => array('image/png', 'image/x-png'),
+	'po'    => array('text/x-gettext-translation'),
+	'pot'   => array('application/vnd.ms-powerpoint'),
+	'pps'   => array('application/vnd.ms-powerpoint'),
+	'ppt'   => array('application/powerpoint'),
+	'ps'    => array('application/postscript'),
+	'psd'   => array('application/x-photoshop', 'image/x-photoshop'),
+	'pub'   => array('application/x-mspublisher'),
+	'py'    => array('text/x-python'),
+	'qt'    => array('video/quicktime'),
+	'ra'    => array('audio/x-realaudio'),
+	'ram'   => array('audio/x-realaudio', 'audio/x-pn-realaudio'),
+	'rar'   => array('application/rar'),
+	'rgb'   => array('image/x-rgb'),
+	'rm'    => array('audio/x-pn-realaudio'),
+	'rpm'   => array('audio/x-pn-realaudio-plugin', 'application/x-redhat-package-manager'),
+	'rss'   => array('application/rss+xml'),
+	'rtf'   => array('text/rtf'),
+	'rtx'   => array('text/richtext'),
+	'rv'    => array('video/vnd.rn-realvideo'),
+	'sea'   => array('application/octet-stream'),
+	'sh'    => array('text/x-sh'),
+	'shtml' => array('text/html'),
+	'sit'   => array('application/x-stuffit'),
+	'smi'   => array('application/smil'),
+	'smil'  => array('application/smil'),
+	'so'    => array('application/octet-stream'),
+	'src'   => array('application/x-wais-source'),
+	'svg'   => array('image/svg+xml'),
+	'swf'   => array('application/x-shockwave-flash'),
+	't'     => array('application/x-troff'),
+	'tar'   => array('application/x-tar'),
+	'tcl'   => array('text/x-tcl'),
+	'tex'   => array('application/x-tex'),
+	'text'  => array('text/plain'),
+	'texti' => array('application/x-texinfo'),
+	'textinfo' => array('application/x-texinfo'),
+	'tgz'   => array('application/x-tar'),
+	'tif'   => array('image/tiff'),
+	'tiff'  => array('image/tiff'),
+	'torrent' => array('application/x-bittorrent'),
+	'tr'    => array('application/x-troff'),
+	'tsv'   => array('text/tab-separated-values'),
+	'txt'   => array('text/plain'),
+	'wav'   => array('audio/x-wav'),
+	'wax'   => array('audio/x-ms-wax'),
+	'wbxml' => array('application/wbxml'),
+	'wm'    => array('video/x-ms-wm'),
+	'wma'   => array('audio/x-ms-wma'),
+	'wmd'   => array('application/x-ms-wmd'),
+	'wmlc'  => array('application/wmlc'),
+	'wmv'   => array('video/x-ms-wmv', 'application/octet-stream'),
+	'wmx'   => array('video/x-ms-wmx'),
+	'wmz'   => array('application/x-ms-wmz'),
+	'word'  => array('application/msword', 'application/octet-stream'),
+	'wp5'   => array('application/wordperfect5.1'),
+	'wpd'   => array('application/vnd.wordperfect'),
+	'wvx'   => array('video/x-ms-wvx'),
+	'xbm'   => array('image/x-xbitmap'),
+	'xcf'   => array('image/xcf'),
+	'xhtml' => array('application/xhtml+xml'),
+	'xht'   => array('application/xhtml+xml'),
+	'xl'    => array('application/excel', 'application/vnd.ms-excel'),
+	'xla'   => array('application/excel', 'application/vnd.ms-excel'),
+	'xlc'   => array('application/excel', 'application/vnd.ms-excel'),
+	'xlm'   => array('application/excel', 'application/vnd.ms-excel'),
+	'xls'   => array('application/excel', 'application/vnd.ms-excel'),
+	'xlt'   => array('application/excel', 'application/vnd.ms-excel'),
+	'xml'   => array('text/xml'),
+	'xof'   => array('x-world/x-vrml'),
+	'xpm'   => array('image/x-xpixmap'),
+	'xsl'   => array('text/xml'),
+	'xvid'  => array('video/x-xvid'),
+	'xwd'   => array('image/x-xwindowdump'),
+	'z'     => array('application/x-compress'),
+	'zip'   => array('application/x-zip', 'application/zip', 'application/x-zip-compressed')
+);
diff --git a/system/config/profiler.php b/system/config/profiler.php
new file mode 100644
index 0000000..d30a1b4
--- /dev/null
+++ b/system/config/profiler.php
@@ -0,0 +1,16 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Array of section names to display in the Profiler, TRUE to display all of them.
+ * Built in sections are benchmarks, database, session, post and cookies, custom sections can be used too.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+$config['show'] = TRUE;
+
+$config['time_decimals'] = 3;
+
+$config['memory_decimals'] = 2;
\ No newline at end of file
diff --git a/system/config/routes.php b/system/config/routes.php
new file mode 100644
index 0000000..fff890c
--- /dev/null
+++ b/system/config/routes.php
@@ -0,0 +1,58 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * ##### Custom Routes
+ * Before changing this file you should copy it to your application/config directory.
+ *
+ * [!!] Routes will run in the order they are defined. Higher routes will always take precedence over lower ones.
+ *
+ * __Default Route__
+ *
+ *     $config['_default'] = 'welcome';
+ *
+ * $config['_default'] specifies the default route. It is used to indicate which controller
+ * should be used when a URI contains no segments. For example, if your web application is at
+ * www.example.com and you visit this address with a web browser, the welcome controller would
+ * be used even though it wasn't specified in the URI. The result would be the same as if the
+ * browser had gone to www.example.com/welcome.
+ *
+ * __Custom Routes__
+ *
+ * In addition to the default route above, you can also specify your own routes. The basic
+ * format for a routing rule is:
+ *
+ *     $config['route'] = 'class/method';
+ *
+ * Where *route* is the URI you want to route, and *class/method* would replace it.
+ *
+ * For example, if your Kohana web application was installed at www.example.com and
+ * you had the following routing rule: `$config['test'] = 'foo/bar';`
+ * Browsing to www.example.com/test would be *internally* redirected to www.example.com/foo/bar.
+ *
+ * __Advanced Routes with Regex__
+ *
+ * The route part of a routing rule is actually a regular expression. If you are unfamiliar
+ * with regular expressions you can read more about them at the PHP website. Using regular expressions,
+ * you can be more selective about which URIs will match your routing rules, and you can make use of the
+ * sub-pattern back referencing technique to re-use parts of the URI in it's replacement.
+ *
+ * This is best described with an example. Suppose we wanted to make the URL www.example.com/article/22
+ * work, we might use a routing rule like this:
+ *
+ *     $config['article/([0-9]+)'] = 'news/show/$1';
+ *
+ * which would match URIs starting with “article/” followed by some numeric digits. If the URI takes this
+ * form, we will use the news controller and call it's show() method passing in the article number as the
+ * first argument. In the www.example.com/article/22 example, it is as if the URL www.example.com/news/show/22
+ * had been visited.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+
+/**
+ * Sets the default route to "welcome"
+ */
+$config['_default'] = 'welcome';
diff --git a/system/config/session.php b/system/config/session.php
new file mode 100644
index 0000000..a758305
--- /dev/null
+++ b/system/config/session.php
@@ -0,0 +1,56 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Session Config
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ *
+ * Session driver name.
+ */
+$config['driver'] = 'cookie';
+
+/**
+ * Session storage parameter, used by drivers.
+ */
+$config['storage'] = '';
+
+/**
+ * Session name.
+ * It must contain only alphanumeric characters and underscores. At least one letter must be present.
+ */
+$config['name'] = 'kohanasession';
+
+/**
+ * Session parameters to validate: user_agent, ip_address, expiration.
+ */
+$config['validate'] = array('user_agent');
+
+/**
+ * Enable or disable session encryption.
+ * Note: this has no effect on the native session driver.
+ */
+$config['encryption'] = FALSE;
+
+/**
+ * Session lifetime. Number of seconds that each session will last.
+ * A value of 0 will keep the session active until the browser is closed (with a limit of 24h).
+ */
+$config['expiration'] = 7200;
+
+/**
+ * Number of page loads before the session id is regenerated.
+ * A value of 0 will disable automatic session id regeneration.
+ * NOTE: Enabling automatic session regeneration can cause a race condition see the
+ * docs for details: http://docs.kohanaphp.com/libraries/session#regenerate
+ */
+$config['regenerate'] = 0;
+
+/**
+ * Percentage probability that the gc (garbage collection) routine is started.
+ */
+$config['gc_probability'] = 2;
\ No newline at end of file
diff --git a/system/config/sql_types.php b/system/config/sql_types.php
new file mode 100644
index 0000000..6a50329
--- /dev/null
+++ b/system/config/sql_types.php
@@ -0,0 +1,99 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * SQL data types. If there are missing values, please report them
+ * at the [issue tracker](http://dev.kohanaphp.com/projects/kohana2/issues)
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * Database sql types
+ */
+$config = array
+(
+	// SQL-92
+	'bit'                   => array('type' => 'string', 'exact' => TRUE),
+	'bit varying'           => array('type' => 'string'),
+	'character'             => array('type' => 'string', 'exact' => TRUE),
+	'character varying'     => array('type' => 'string'),
+	'date'                  => array('type' => 'string'),
+	'decimal'               => array('type' => 'float', 'exact' => TRUE),
+	'double precision'      => array('type' => 'float'),
+	'float'                 => array('type' => 'float'),
+	'integer'               => array('type' => 'int', 'min' => -2147483648, 'max' => 2147483647),
+	'interval'              => array('type' => 'string'),
+	'national character'    => array('type' => 'string', 'exact' => TRUE),
+	'national character varying' => array('type' => 'string'),
+	'numeric'               => array('type' => 'float', 'exact' => TRUE),
+	'real'                  => array('type' => 'float'),
+	'smallint'              => array('type' => 'int', 'min' => -32768, 'max' => 32767),
+	'time'                  => array('type' => 'string'),
+	'time with time zone'   => array('type' => 'string'),
+	'timestamp'             => array('type' => 'string'),
+	'timestamp with time zone' => array('type' => 'string'),
+
+	// SQL:1999
+	//'array','ref','row'
+	'binary large object'   => array('type' => 'string', 'binary' => TRUE),
+	'boolean'               => array('type' => 'boolean'),
+	'character large object' => array('type' => 'string'),
+	'national character large object' => array('type' => 'string'),
+
+	// SQL:2003
+	'bigint'    => array('type' => 'int', 'min' => -9223372036854775808, 'max' => 9223372036854775807),
+
+	// SQL:2008
+	'binary'            => array('type' => 'string', 'binary' => TRUE, 'exact' => TRUE),
+	'binary varying'    => array('type' => 'string', 'binary' => TRUE),
+
+	// MySQL
+	'bigint unsigned'   => array('type' => 'int', 'min' => 0, 'max' => 18446744073709551615),
+	'decimal unsigned'  => array('type' => 'float', 'exact' => TRUE, 'min' => 0.0),
+	'double unsigned'   => array('type' => 'float', 'min' => 0.0),
+	'float unsigned'    => array('type' => 'float', 'min' => 0.0),
+	'integer unsigned'  => array('type' => 'int', 'min' => 0, 'max' => 4294967295),
+	'mediumint'         => array('type' => 'int', 'min' => -8388608, 'max' => 8388607),
+	'mediumint unsigned' => array('type' => 'int', 'min' => 0, 'max' => 16777215),
+	'real unsigned'     => array('type' => 'float', 'min' => 0.0),
+	'smallint unsigned' => array('type' => 'int', 'min' => 0, 'max' => 65535),
+	'text'              => array('type' => 'string'),
+	'tinyint'           => array('type' => 'int', 'min' => -128, 'max' => 127),
+	'tinyint unsigned'  => array('type' => 'int', 'min' => 0, 'max' => 255),
+	'year'              => array('type' => 'string'),
+);
+
+// SQL-92
+$config['char'] = $config['character'];
+$config['char varying'] = $config['character varying'];
+$config['dec'] = $config['decimal'];
+$config['int'] = $config['integer'];
+$config['nchar'] = $config['national char'] = $config['national character'];
+$config['nchar varying'] = $config['national char varying'] = $config['national character varying'];
+$config['varchar'] = $config['character varying'];
+
+// SQL:1999
+$config['blob'] = $config['binary large object'];
+$config['clob'] = $config['char large object'] = $config['character large object'];
+$config['nclob'] = $config['nchar large object'] = $config['national character large object'];
+$config['time without time zone'] = $config['time'];
+$config['timestamp without time zone'] = $config['timestamp'];
+
+// SQL:2008
+$config['varbinary'] = $config['binary varying'];
+
+// MySQL
+$config['bool'] = $config['boolean'];
+$config['datetime'] = $config['timestamp'];
+$config['double'] = $config['double precision'];
+$config['double precision unsigned'] = $config['double unsigned'];
+$config['enum'] = $config['set'] = $config['character varying'];
+$config['fixed'] = $config['decimal'];
+$config['fixed unsigned'] = $config['decimal unsigned'];
+$config['int unsigned'] = $config['integer unsigned'];
+$config['longblob'] = $config['mediumblob'] = $config['tinyblob'] = $config['binary large object'];
+$config['longtext'] = $config['mediumtext'] = $config['tinytext'] = $config['text'];
+$config['numeric unsigned'] = $config['decimal unsigned'];
+$config['nvarchar'] = $config['national varchar'] = $config['national character varying'];
diff --git a/system/config/upload.php b/system/config/upload.php
new file mode 100644
index 0000000..833082c
--- /dev/null
+++ b/system/config/upload.php
@@ -0,0 +1,24 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Upload config
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * This path is relative to your index file. Absolute paths are also supported.
+ */
+$config['directory'] = DOCROOT.'upload';
+
+/**
+ * Enable or disable directory creation.
+ */
+$config['create_directories'] = FALSE;
+
+/**
+ * Remove spaces from uploaded filenames.
+ */
+$config['remove_spaces'] = TRUE;
\ No newline at end of file
diff --git a/system/config/user_agents.php b/system/config/user_agents.php
new file mode 100644
index 0000000..2559e85
--- /dev/null
+++ b/system/config/user_agents.php
@@ -0,0 +1,120 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * This file contains four arrays of user agent data.  It is used by the
+ * User Agent library to help identify browser, platform, robot, and
+ * mobile device data. The array keys are used to identify the device
+ * and the array values are used to set the actual name of the item.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+$config['platform'] = array
+(
+	'windows nt 6.0' => 'Windows Vista',
+	'windows nt 5.2' => 'Windows 2003',
+	'windows nt 5.0' => 'Windows 2000',
+	'windows nt 5.1' => 'Windows XP',
+	'windows nt 4.0' => 'Windows NT',
+	'winnt4.0'       => 'Windows NT',
+	'winnt 4.0'      => 'Windows NT',
+	'winnt'          => 'Windows NT',
+	'windows 98'     => 'Windows 98',
+	'win98'          => 'Windows 98',
+	'windows 95'     => 'Windows 95',
+	'win95'          => 'Windows 95',
+	'windows'        => 'Unknown Windows OS',
+	'os x'           => 'Mac OS X',
+	'intel mac'      => 'Intel Mac',
+	'ppc mac'        => 'PowerPC Mac',
+	'powerpc'        => 'PowerPC',
+	'ppc'            => 'PowerPC',
+	'cygwin'         => 'Cygwin',
+	'linux'          => 'Linux',
+	'debian'         => 'Debian',
+	'openvms'        => 'OpenVMS',
+	'sunos'          => 'Sun Solaris',
+	'amiga'          => 'Amiga',
+	'beos'           => 'BeOS',
+	'apachebench'    => 'ApacheBench',
+	'freebsd'        => 'FreeBSD',
+	'netbsd'         => 'NetBSD',
+	'bsdi'           => 'BSDi',
+	'openbsd'        => 'OpenBSD',
+	'os/2'           => 'OS/2',
+	'warp'           => 'OS/2',
+	'aix'            => 'AIX',
+	'irix'           => 'Irix',
+	'osf'            => 'DEC OSF',
+	'hp-ux'          => 'HP-UX',
+	'hurd'           => 'GNU/Hurd',
+	'unix'           => 'Unknown Unix OS',
+);
+
+/**
+ * The order of this array should NOT be changed. Many browsers return
+ * multiple browser types so we want to identify the sub-type first.
+ */
+$config['browser'] = array
+(
+	'Opera'             => 'Opera',
+	'MSIE'              => 'Internet Explorer',
+	'Internet Explorer' => 'Internet Explorer',
+	'Shiira'            => 'Shiira',
+	'Firefox'           => 'Firefox',
+	'Chimera'           => 'Chimera',
+	'Phoenix'           => 'Phoenix',
+	'Firebird'          => 'Firebird',
+	'Camino'            => 'Camino',
+	'Netscape'          => 'Netscape',
+	'OmniWeb'           => 'OmniWeb',
+	'Chrome'            => 'Chrome',
+	'Safari'            => 'Safari',
+	'Konqueror'         => 'Konqueror',
+	'Epiphany'          => 'Epiphany',
+	'Galeon'            => 'Galeon',
+	'Mozilla'           => 'Mozilla',
+	'icab'              => 'iCab',
+	'lynx'              => 'Lynx',
+	'links'             => 'Links',
+	'hotjava'           => 'HotJava',
+	'amaya'             => 'Amaya',
+	'IBrowse'           => 'IBrowse',
+);
+
+$config['mobile'] = array
+(
+	'mobileexplorer' => 'Mobile Explorer',
+	'openwave'       => 'Open Wave',
+	'opera mini'     => 'Opera Mini',
+	'operamini'      => 'Opera Mini',
+	'elaine'         => 'Palm',
+	'palmsource'     => 'Palm',
+	'digital paths'  => 'Palm',
+	'avantgo'        => 'Avantgo',
+	'xiino'          => 'Xiino',
+	'palmscape'      => 'Palmscape',
+	'nokia'          => 'Nokia',
+	'ericsson'       => 'Ericsson',
+	'blackBerry'     => 'BlackBerry',
+	'motorola'       => 'Motorola',
+	'iphone'         => 'iPhone',
+	'android'        => 'Android',
+);
+
+/**
+ * There are hundreds of bots but these are the most common.
+ */
+$config['robot'] = array
+(
+	'googlebot'   => 'Googlebot',
+	'msnbot'      => 'MSNBot',
+	'slurp'       => 'Inktomi Slurp',
+	'yahoo'       => 'Yahoo',
+	'askjeeves'   => 'AskJeeves',
+	'fastcrawler' => 'FastCrawler',
+	'infoseek'    => 'InfoSeek Robot 1.0',
+	'lycos'       => 'Lycos',
+);
\ No newline at end of file
diff --git a/system/config/view.php b/system/config/view.php
new file mode 100644
index 0000000..b6a25b1
--- /dev/null
+++ b/system/config/view.php
@@ -0,0 +1,25 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * View Config
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+/**
+ * Allowed non-php view types. Most file extensions are supported.
+ * Do not forget to add a valid MIME type in mimes.php
+ */
+$config['allowed_filetypes'] = array
+(
+	'gif',
+	'jpg', 'jpeg',
+	'png',
+	'tif', 'tiff',
+	'swf',
+	'htm', 'html',
+	'css',
+	'js'
+);
diff --git a/system/controllers/template.php b/system/controllers/template.php
new file mode 100644
index 0000000..a9b9934
--- /dev/null
+++ b/system/controllers/template.php
@@ -0,0 +1,54 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Allows a template to be automatically loaded and displayed. Display can be
+ * dynamically turned off in the controller methods, and the template file
+ * can be overloaded.
+ *
+ * To use it, declare your controller to extend this class:
+ * `class Your_Controller extends Template_Controller`
+ *
+ * $Id: template.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+abstract class Template_Controller extends Controller {
+
+	// Template view name
+	public $template = 'template';
+
+	// Default to do auto-rendering
+	public $auto_render = TRUE;
+
+	/**
+	 * Template loading and setup routine.
+	 */
+	public function __construct()
+	{
+		parent::__construct();
+
+		// Load the template
+		$this->template = new View($this->template);
+
+		if ($this->auto_render == TRUE)
+		{
+			// Render the template immediately after the controller method
+			Event::add('system.post_controller', array($this, '_render'));
+		}
+	}
+
+	/**
+	 * Render the loaded template.
+	 */
+	public function _render()
+	{
+		if ($this->auto_render == TRUE)
+		{
+			// Render the template when the class is destroyed
+			$this->template->render(TRUE);
+		}
+	}
+
+} // End Template_Controller
\ No newline at end of file
diff --git a/system/core/Benchmark.php b/system/core/Benchmark.php
new file mode 100644
index 0000000..79fadb6
--- /dev/null
+++ b/system/core/Benchmark.php
@@ -0,0 +1,126 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Simple benchmarking.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+final class Benchmark {
+
+	// Benchmark timestamps
+	private static $marks;
+
+	/**
+	 * Set a benchmark start point.
+	 *
+	 * @param   string  benchmark name
+	 * @return  void
+	 */
+	public static function start($name)
+	{
+		if (isset(self::$marks[$name]) AND self::$marks[$name][0]['stop'] === FALSE)
+			throw new Kohana_Exception('A benchmark named :name is already running.', array(':name' => $name));
+
+		if ( ! isset(self::$marks[$name]))
+		{
+			self::$marks[$name] = array();
+		}
+
+		$mark = array
+		(
+			'start'        => microtime(TRUE),
+			'stop'         => FALSE,
+			'memory_start' => self::memory_usage(),
+			'memory_stop'  => FALSE
+		);
+
+		array_unshift(self::$marks[$name], $mark);
+	}
+
+	/**
+	 * Set a benchmark stop point.
+	 *
+	 * @param   string  benchmark name
+	 * @return  void
+	 */
+	public static function stop($name)
+	{
+		if (isset(self::$marks[$name]) AND self::$marks[$name][0]['stop'] === FALSE)
+		{
+			self::$marks[$name][0]['stop'] = microtime(TRUE);
+			self::$marks[$name][0]['memory_stop'] = self::memory_usage();
+		}
+	}
+
+	/**
+	 * Get the elapsed time between a start and stop.
+	 *
+	 * @param   string   benchmark name, TRUE for all
+	 * @param   integer  number of decimal places to count to
+	 * @return  array
+	 */
+	public static function get($name, $decimals = 4)
+	{
+		if ($name === TRUE)
+		{
+			$times = array();
+			$names = array_keys(self::$marks);
+
+			foreach ($names as $name)
+			{
+				// Get each mark recursively
+				$times[$name] = self::get($name, $decimals);
+			}
+
+			// Return the array
+			return $times;
+		}
+
+		if ( ! isset(self::$marks[$name]))
+			return FALSE;
+
+		if (self::$marks[$name][0]['stop'] === FALSE)
+		{
+			// Stop the benchmark to prevent mis-matched results
+			self::stop($name);
+		}
+
+		// Return a string version of the time between the start and stop points
+		// Properly reading a float requires using number_format or sprintf
+		$time = $memory = 0;
+		for ($i = 0; $i < count(self::$marks[$name]); $i++)
+		{
+			$time += self::$marks[$name][$i]['stop'] - self::$marks[$name][$i]['start'];
+			$memory += self::$marks[$name][$i]['memory_stop'] - self::$marks[$name][$i]['memory_start'];
+		}
+
+		return array
+		(
+			'time'   => number_format($time, $decimals),
+			'memory' => $memory,
+			'count'  => count(self::$marks[$name])
+		);
+	}
+
+	/**
+	 * Returns the current memory usage. This is only possible if the
+	 * memory_get_usage function is supported in PHP.
+	 *
+	 * @return  integer
+	 */
+	private static function memory_usage()
+	{
+		static $func;
+
+		if ($func === NULL)
+		{
+			// Test if memory usage can be seen
+			$func = function_exists('memory_get_usage');
+		}
+
+		return $func ? memory_get_usage() : 0;
+	}
+
+} // End Benchmark
diff --git a/system/core/Event.php b/system/core/Event.php
new file mode 100644
index 0000000..ab839f4
--- /dev/null
+++ b/system/core/Event.php
@@ -0,0 +1,231 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Process queuing/execution class. Allows an unlimited number of callbacks
+ * to be added to 'events'. Events can be run multiple times, and can also
+ * process event-specific data. By default, Kohana has several system events.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ * @link       http://docs.kohanaphp.com/general/events
+ */
+abstract class Event_Core {
+
+	// Event callbacks
+	protected static $events = array();
+
+	// Cache of events that have been run
+	protected static $has_run = array();
+
+	// Data that can be processed during events
+	public static $data;
+
+	/**
+	 * Add a callback to an event queue.
+	 *
+	 * @param   string  event name
+	 * @param   array   http://php.net/callback
+	 * @param   boolean prevent duplicates
+	 * @return  boolean
+	 */
+	public static function add($name, $callback, $unique = FALSE)
+	{
+		if ( ! isset(Event::$events[$name]))
+		{
+			// Create an empty event if it is not yet defined
+			Event::$events[$name] = array();
+		}
+		elseif ($unique AND in_array($callback, Event::$events[$name], TRUE))
+		{
+			// The event already exists
+			return FALSE;
+		}
+
+		// Add the event
+		Event::$events[$name][] = $callback;
+
+		return TRUE;
+	}
+
+	/**
+	 * Add a callback to an event queue, before a given event.
+	 *
+	 * @param   string   event name
+	 * @param   array    existing event callback
+	 * @param   array    event callback
+	 * @return  boolean
+	 */
+	public static function add_before($name, $existing, $callback)
+	{
+		if (empty(Event::$events[$name]) OR ($key = array_search($existing, Event::$events[$name])) === FALSE)
+		{
+			// Just add the event if there are no events
+			return Event::add($name, $callback);
+		}
+		else
+		{
+			// Insert the event immediately before the existing event
+			return Event::insert_event($name, $key, $callback);
+		}
+	}
+
+	/**
+	 * Add a callback to an event queue, after a given event.
+	 *
+	 * @param   string   event name
+	 * @param   array    existing event callback
+	 * @param   array    event callback
+	 * @return  boolean
+	 */
+	public static function add_after($name, $existing, $callback)
+	{
+		if (empty(Event::$events[$name]) OR ($key = array_search($existing, Event::$events[$name])) === FALSE)
+		{
+			// Just add the event if there are no events
+			return Event::add($name, $callback);
+		}
+		else
+		{
+			// Insert the event immediately after the existing event
+			return Event::insert_event($name, $key + 1, $callback);
+		}
+	}
+
+	/**
+	 * Inserts a new event at a specfic key location.
+	 *
+	 * @param   string   event name
+	 * @param   integer  key to insert new event at
+	 * @param   array    event callback
+	 * @return  void
+	 */
+	private static function insert_event($name, $key, $callback)
+	{
+		if (in_array($callback, Event::$events[$name], TRUE))
+			return FALSE;
+
+		// Add the new event at the given key location
+		Event::$events[$name] = array_merge
+		(
+			// Events before the key
+			array_slice(Event::$events[$name], 0, $key),
+			// New event callback
+			array($callback),
+			// Events after the key
+			array_slice(Event::$events[$name], $key)
+		);
+
+		return TRUE;
+	}
+
+	/**
+	 * Replaces an event with another event.
+	 *
+	 * @param   string   event name
+	 * @param   array    event to replace
+	 * @param   array    new callback
+	 * @return  boolean
+	 */
+	public static function replace($name, $existing, $callback)
+	{
+		if (empty(Event::$events[$name]) OR ($key = array_search($existing, Event::$events[$name], TRUE)) === FALSE)
+			return FALSE;
+
+		if ( ! in_array($callback, Event::$events[$name], TRUE))
+		{
+			// Replace the exisiting event with the new event
+			Event::$events[$name][$key] = $callback;
+		}
+		else
+		{
+			// Remove the existing event from the queue
+			unset(Event::$events[$name][$key]);
+
+			// Reset the array so the keys are ordered properly
+			Event::$events[$name] = array_values(Event::$events[$name]);
+		}
+
+		return TRUE;
+	}
+
+	/**
+	 * Get all callbacks for an event.
+	 *
+	 * @param   string  event name
+	 * @return  array
+	 */
+	public static function get($name)
+	{
+		return empty(Event::$events[$name]) ? array() : Event::$events[$name];
+	}
+
+	/**
+	 * Clear some or all callbacks from an event.
+	 *
+	 * @param   string  event name
+	 * @param   array   specific callback to remove, FALSE for all callbacks
+	 * @return  void
+	 */
+	public static function clear($name, $callback = FALSE)
+	{
+		if ($callback === FALSE)
+		{
+			Event::$events[$name] = array();
+		}
+		elseif (isset(Event::$events[$name]))
+		{
+			// Loop through each of the event callbacks and compare it to the
+			// callback requested for removal. The callback is removed if it
+			// matches.
+			foreach (Event::$events[$name] as $i => $event_callback)
+			{
+				if ($callback === $event_callback)
+				{
+					unset(Event::$events[$name][$i]);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Execute all of the callbacks attached to an event.
+	 *
+	 * @param   string   event name
+	 * @param   array    data can be processed as Event::$data by the callbacks
+	 * @return  void
+	 */
+	public static function run($name, & $data = NULL)
+	{
+		if ( ! empty(Event::$events[$name]))
+		{
+			// So callbacks can access Event::$data
+			Event::$data =& $data;
+			$callbacks  =  Event::get($name);
+
+			foreach ($callbacks as $callback)
+			{
+				call_user_func_array($callback, array(&$data));
+			}
+
+			// Do this to prevent data from getting 'stuck'
+			$clear_data = '';
+			Event::$data =& $clear_data;
+		}
+
+		// The event has been run!
+		Event::$has_run[$name] = $name;
+	}
+
+	/**
+	 * Check if a given event has been run.
+	 *
+	 * @param   string   event name
+	 * @return  boolean
+	 */
+	public static function has_run($name)
+	{
+		return isset(Event::$has_run[$name]);
+	}
+
+} // End Event
\ No newline at end of file
diff --git a/system/core/Kohana.php b/system/core/Kohana.php
new file mode 100644
index 0000000..96d969e
--- /dev/null
+++ b/system/core/Kohana.php
@@ -0,0 +1,1118 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Provides Kohana-specific helper functions. This is where the magic happens!
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+// Test of Kohana is running in Windows
+define('KOHANA_IS_WIN', DIRECTORY_SEPARATOR === '\\');
+
+abstract class Kohana_Core {
+
+	const VERSION  = '2.4';
+	const CODENAME = 'no_codename';
+	const CHARSET  = 'UTF-8';
+	const LOCALE = 'en_US';
+
+	// The singleton instance of the controller
+	public static $instance;
+
+	// Output buffering level
+	protected static $buffer_level;
+
+	// The final output that will displayed by Kohana
+	public static $output = '';
+
+	// The current locale
+	public static $locale;
+
+	// Include paths
+	protected static $include_paths;
+	protected static $include_paths_hash = '';
+
+	// Cache lifetime
+	protected static $cache_lifetime;
+
+	// Internal caches and write status
+	protected static $internal_cache = array();
+	protected static $write_cache;
+	protected static $internal_cache_path;
+	protected static $internal_cache_key;
+	protected static $internal_cache_encrypt;
+
+	// Server API that PHP is using. Allows testing of different APIs.
+	public static $server_api = PHP_SAPI;
+
+	/**
+	 * Sets up the PHP environment. Adds error/exception handling, output
+	 * buffering, and adds an auto-loading method for loading classes.
+	 *
+	 * This method is run immediately when this file is loaded, and is
+	 * benchmarked as environment_setup.
+	 *
+	 * For security, this function also destroys the $_REQUEST global variable.
+	 * Using the proper global (GET, POST, COOKIE, etc) is inherently more secure.
+	 * The recommended way to fetch a global variable is using the Input library.
+	 * @see http://www.php.net/globals
+	 *
+	 * @return  void
+	 */
+	public static function setup()
+	{
+		static $run;
+
+		// Only run this function once
+		if ($run === TRUE)
+			return;
+
+		$run = TRUE;
+
+		// Start the environment setup benchmark
+		Benchmark::start(SYSTEM_BENCHMARK.'_environment_setup');
+
+		// Define Kohana error constant
+		define('E_KOHANA', 42);
+
+		// Define 404 error constant
+		define('E_PAGE_NOT_FOUND', 43);
+
+		// Define database error constant
+		define('E_DATABASE_ERROR', 44);
+
+		// Set the default charset for mb_* functions
+		mb_internal_encoding(Kohana::CHARSET);
+
+		if (Kohana_Config::instance()->loaded() === FALSE)
+		{
+			// Re-parse the include paths
+			Kohana::include_paths(TRUE);
+		}
+
+		if (Kohana::$cache_lifetime = Kohana::config('core.internal_cache'))
+		{
+			// Are we using encryption for caches?
+			Kohana::$internal_cache_encrypt	= Kohana::config('core.internal_cache_encrypt');
+
+			if(Kohana::$internal_cache_encrypt===TRUE)
+			{
+				Kohana::$internal_cache_key = Kohana::config('core.internal_cache_key');
+
+				// Be sure the key is of acceptable length for the mcrypt algorithm used
+				Kohana::$internal_cache_key = substr(Kohana::$internal_cache_key, 0, 24);
+			}
+
+			// Set the directory to be used for the internal cache
+			if ( ! Kohana::$internal_cache_path = Kohana::config('core.internal_cache_path'))
+			{
+				Kohana::$internal_cache_path = APPPATH.'cache/';
+			}
+
+			// Load cached configuration and language files
+			Kohana::$internal_cache['configuration'] = Kohana::cache('configuration', Kohana::$cache_lifetime);
+			Kohana::$internal_cache['language']      = Kohana::cache('language', Kohana::$cache_lifetime);
+
+			// Load cached file paths
+			Kohana::$internal_cache['find_file_paths'] = Kohana::cache('find_file_paths', Kohana::$cache_lifetime);
+
+			// Enable cache saving
+			Event::add('system.shutdown', array('Kohana', 'internal_cache_save'));
+		}
+
+		// Start output buffering
+		ob_start(array('Kohana', 'output_buffer'));
+
+		// Save buffering level
+		Kohana::$buffer_level = ob_get_level();
+
+		// Set autoloader
+		spl_autoload_register(array('Kohana', 'auto_load'));
+
+		// Register a shutdown function to handle system.shutdown events
+		register_shutdown_function(array('Kohana', 'shutdown'));
+
+		// Send default text/html UTF-8 header
+		header('Content-Type: text/html; charset='.Kohana::CHARSET);
+
+		// Load i18n
+		new I18n;
+
+		// Enable exception handling
+		Kohana_Exception::enable();
+
+		// Enable error handling
+		Kohana_PHP_Exception::enable();
+
+		// Load locales
+		$locales = Kohana::config('locale.language');
+
+		// Make first locale the defined Kohana charset
+		$locales[0] .= '.'.Kohana::CHARSET;
+
+		// Set locale information
+		Kohana::$locale = setlocale(LC_ALL, $locales);
+
+		// Default to the default locale when none of the user defined ones where accepted
+		Kohana::$locale = ! Kohana::$locale ? Kohana::LOCALE.'.'.Kohana::CHARSET : Kohana::$locale;
+
+		// Set locale for the I18n system
+		I18n::set_locale(Kohana::$locale);
+
+		// Set and validate the timezone
+		date_default_timezone_set(Kohana::config('locale.timezone'));
+
+		// register_globals is enabled
+		if (ini_get('register_globals'))
+		{
+			if (isset($_REQUEST['GLOBALS']))
+			{
+				// Prevent GLOBALS override attacks
+				exit('Global variable overload attack.');
+			}
+
+			// Destroy the REQUEST global
+			$_REQUEST = array();
+
+			// These globals are standard and should not be removed
+			$preserve = array('GLOBALS', '_REQUEST', '_GET', '_POST', '_FILES', '_COOKIE', '_SERVER', '_ENV', '_SESSION');
+
+			// This loop has the same effect as disabling register_globals
+			foreach (array_diff(array_keys($GLOBALS), $preserve) as $key)
+			{
+				global $$key;
+				$$key = NULL;
+
+				// Unset the global variable
+				unset($GLOBALS[$key], $$key);
+			}
+
+			// Warn the developer about register globals
+			Kohana_Log::add('debug', 'Disable register_globals! It is evil and deprecated: http://php.net/register_globals');
+		}
+
+		// Enable Kohana routing
+		Event::add('system.routing', array('Router', 'find_uri'));
+		Event::add('system.routing', array('Router', 'setup'));
+
+		// Enable Kohana controller initialization
+		Event::add('system.execute', array('Kohana', 'instance'));
+
+		// Enable Kohana 404 pages
+		Event::add('system.404', array('Kohana_404_Exception', 'trigger'));
+
+		if (Kohana::config('core.enable_hooks') === TRUE)
+		{
+			// Find all the hook files
+			$hooks = Kohana::list_files('hooks', TRUE);
+
+			foreach ($hooks as $file)
+			{
+				// Load the hook
+				include $file;
+			}
+		}
+
+		// Stop the environment setup routine
+		Benchmark::stop(SYSTEM_BENCHMARK.'_environment_setup');
+	}
+
+	/**
+	 * Cleans up the PHP environment. Disables error/exception handling and the
+	 * auto-loading method and closes the output buffer.
+	 *
+	 * This method does not need to be called during normal system execution,
+	 * however in some advanced situations it can be helpful. @see #1781
+	 *
+	 * @return  void
+	 */
+	public static function cleanup()
+	{
+		static $run;
+
+		// Only run this function once
+		if ($run === TRUE)
+			return;
+
+		$run = TRUE;
+
+		Kohana_Exception::disable();
+
+		Kohana_PHP_Exception::disable();
+
+		spl_autoload_unregister(array('Kohana', 'auto_load'));
+
+		Kohana::close_buffers();
+	}
+
+	/**
+	 * Loads the controller and initializes it. Runs the pre_controller,
+	 * post_controller_constructor, and post_controller events. Triggers
+	 * a system.404 event when the route cannot be mapped to a controller.
+	 *
+	 * This method is benchmarked as controller_setup and controller_execution.
+	 *
+	 * @return  object  instance of controller
+	 */
+	public static function & instance()
+	{
+		if (Kohana::$instance === NULL)
+		{
+			Benchmark::start(SYSTEM_BENCHMARK.'_controller_setup');
+
+			// Include the Controller file
+			require_once Router::$controller_path;
+
+			try
+			{
+				// Start validation of the controller
+				$class = new ReflectionClass(ucfirst(Router::$controller).'_Controller');
+			}
+			catch (ReflectionException $e)
+			{
+				// Controller does not exist
+				Event::run('system.404');
+			}
+
+			if ($class->isAbstract() OR (IN_PRODUCTION AND $class->getConstant('ALLOW_PRODUCTION') == FALSE))
+			{
+				// Controller is not allowed to run in production
+				Event::run('system.404');
+			}
+
+			// Run system.pre_controller
+			Event::run('system.pre_controller');
+
+			// Create a new controller instance
+			$controller = $class->newInstance();
+
+			// Controller constructor has been executed
+			Event::run('system.post_controller_constructor');
+
+			try
+			{
+				// Load the controller method
+				$method = $class->getMethod(Router::$method);
+
+				// Method exists
+				if (Router::$method[0] === '_')
+				{
+					// Do not allow access to hidden methods
+					Event::run('system.404');
+				}
+
+				if ($method->isProtected() or $method->isPrivate())
+				{
+					// Do not attempt to invoke protected methods
+					throw new ReflectionException('protected controller method');
+				}
+
+				// Default arguments
+				$arguments = Router::$arguments;
+			}
+			catch (ReflectionException $e)
+			{
+				// Use __call instead
+				$method = $class->getMethod('__call');
+
+				// Use arguments in __call format
+				$arguments = array(Router::$method, Router::$arguments);
+			}
+
+			// Stop the controller setup benchmark
+			Benchmark::stop(SYSTEM_BENCHMARK.'_controller_setup');
+
+			// Start the controller execution benchmark
+			Benchmark::start(SYSTEM_BENCHMARK.'_controller_execution');
+
+			// Execute the controller method
+			$method->invokeArgs($controller, $arguments);
+
+			// Controller method has been executed
+			Event::run('system.post_controller');
+
+			// Stop the controller execution benchmark
+			Benchmark::stop(SYSTEM_BENCHMARK.'_controller_execution');
+		}
+
+		return Kohana::$instance;
+	}
+
+	/**
+	 * Get all include paths. APPPATH is the first path, followed by module
+	 * paths in the order they are configured, follow by the SYSPATH.
+	 *
+	 * @param   boolean  re-process the include paths
+	 * @return  array
+	 */
+	public static function include_paths($process = FALSE)
+	{
+		if ($process === TRUE)
+		{
+			// Add APPPATH as the first path
+			Kohana::$include_paths = array(APPPATH);
+
+			foreach (Kohana::config('core.modules') as $path)
+			{
+				if ($path = str_replace('\\', '/', realpath($path)))
+				{
+					// Add a valid path
+					Kohana::$include_paths[] = $path.'/';
+				}
+			}
+
+			// Add SYSPATH as the last path
+			Kohana::$include_paths[] = SYSPATH;
+
+			Kohana::$include_paths_hash = md5(serialize(Kohana::$include_paths));
+		}
+
+		return Kohana::$include_paths;
+	}
+
+	/**
+	 * Get a config item or group proxies Kohana_Config.
+	 *
+	 * @param   string   item name
+	 * @param   boolean  force a forward slash (/) at the end of the item
+	 * @param   boolean  is the item required?
+	 * @return  mixed
+	 */
+	public static function config($key, $slash = FALSE, $required = FALSE)
+	{
+		return Kohana_Config::instance()->get($key,$slash,$required);
+	}
+
+	/**
+	 * Load data from a simple cache file. This should only be used internally,
+	 * and is NOT a replacement for the Cache library.
+	 *
+	 * @param   string   unique name of cache
+	 * @param   integer  expiration in seconds
+	 * @return  mixed
+	 */
+	public static function cache($name, $lifetime)
+	{
+		if ($lifetime > 0)
+		{
+			$path = Kohana::$internal_cache_path.'kohana_'.$name;
+
+			if (is_file($path))
+			{
+				// Check the file modification time
+				if ((time() - filemtime($path)) < $lifetime)
+				{
+					// Cache is valid! Now, do we need to decrypt it?
+					if(Kohana::$internal_cache_encrypt===TRUE)
+					{
+						$data		= file_get_contents($path);
+
+						$iv_size	= mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
+						$iv			= mcrypt_create_iv($iv_size, MCRYPT_RAND);
+
+						$decrypted_text	= mcrypt_decrypt(MCRYPT_RIJNDAEL_256, Kohana::$internal_cache_key, $data, MCRYPT_MODE_ECB, $iv);
+
+						$cache	= unserialize($decrypted_text);
+
+						// If the key changed, delete the cache file
+						if(!$cache)
+							unlink($path);
+
+						// If cache is false (as above) return NULL, otherwise, return the cache
+						return ($cache ? $cache : NULL);
+					}
+					else
+					{
+						return unserialize(file_get_contents($path));
+					}
+				}
+				else
+				{
+					// Cache is invalid, delete it
+					unlink($path);
+				}
+			}
+		}
+
+		// No cache found
+		return NULL;
+	}
+
+	/**
+	 * Save data to a simple cache file. This should only be used internally, and
+	 * is NOT a replacement for the Cache library.
+	 *
+	 * @param   string   cache name
+	 * @param   mixed    data to cache
+	 * @param   integer  expiration in seconds
+	 * @return  boolean
+	 */
+	public static function cache_save($name, $data, $lifetime)
+	{
+		if ($lifetime < 1)
+			return FALSE;
+
+		$path = Kohana::$internal_cache_path.'kohana_'.$name;
+
+		if ($data === NULL)
+		{
+			// Delete cache
+			return (is_file($path) and unlink($path));
+		}
+		else
+		{
+			// Using encryption? Encrypt the data when we write it
+			if(Kohana::$internal_cache_encrypt===TRUE)
+			{
+				// Encrypt and write data to cache file
+				$iv_size	= mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
+				$iv			= mcrypt_create_iv($iv_size, MCRYPT_RAND);
+
+				// Serialize and encrypt!
+				$encrypted_text	= mcrypt_encrypt(MCRYPT_RIJNDAEL_256, Kohana::$internal_cache_key, serialize($data), MCRYPT_MODE_ECB, $iv);
+
+				return (bool) file_put_contents($path, $encrypted_text);
+			}
+			else
+			{
+				// Write data to cache file
+				return (bool) file_put_contents($path, serialize($data));
+			}
+		}
+	}
+
+	/**
+	 * Kohana output handler. Called during ob_clean, ob_flush, and their variants.
+	 *
+	 * @param   string  current output buffer
+	 * @return  string
+	 */
+	public static function output_buffer($output)
+	{
+		// Could be flushing, so send headers first
+		if ( ! Event::has_run('system.send_headers'))
+		{
+			// Run the send_headers event
+			Event::run('system.send_headers');
+		}
+
+		// Set final output
+		Kohana::$output = $output;
+
+		// Set and return the final output
+		return Kohana::$output;
+	}
+
+	/**
+	 * Closes all open output buffers, either by flushing or cleaning, and stores
+	 * output buffer for display during shutdown.
+	 *
+	 * @param   boolean  disable to clear buffers, rather than flushing
+	 * @return  void
+	 */
+	public static function close_buffers($flush = TRUE)
+	{
+		if (ob_get_level() >= Kohana::$buffer_level)
+		{
+			// Set the close function
+			$close = ($flush === TRUE) ? 'ob_end_flush' : 'ob_end_clean';
+
+			while (ob_get_level() > Kohana::$buffer_level)
+			{
+				// Flush or clean the buffer
+				$close();
+			}
+
+			// Store the Kohana output buffer.  Apparently there was a change in PHP
+			// 5.4 such that if you call this you wind up with a blank page.
+			// Disabling it for now.  See ticket #1839
+			if (version_compare(PHP_VERSION, "5.4", "<")) {
+				ob_end_clean();
+			}
+		}
+	}
+
+	/**
+	 * Triggers the shutdown of Kohana by closing the output buffer, runs the system.display event.
+	 *
+	 * @return  void
+	 */
+	public static function shutdown()
+	{
+		static $run;
+
+		// Only run this function once
+		if ($run === TRUE)
+			return;
+
+		$run = TRUE;
+
+		// Run system.shutdown event
+		Event::run('system.shutdown');
+
+		// Close output buffers
+		Kohana::close_buffers(TRUE);
+
+		// Run the output event
+		Event::run('system.display', Kohana::$output);
+
+		// Render the final output
+		Kohana::render(Kohana::$output);
+	}
+
+	/**
+	 * Inserts global Kohana variables into the generated output and prints it.
+	 *
+	 * @param   string  final output that will displayed
+	 * @return  void
+	 */
+	public static function render($output)
+	{
+		if (Kohana::config('core.render_stats') === TRUE)
+		{
+			// Fetch memory usage in MB
+			$memory = function_exists('memory_get_usage') ? (memory_get_usage() / 1024 / 1024) : 0;
+
+			// Fetch benchmark for page execution time
+			$benchmark = Benchmark::get(SYSTEM_BENCHMARK.'_total_execution');
+
+			// Replace the global template variables
+			$output = str_replace(
+				array
+				(
+					'{kohana_version}',
+					'{kohana_codename}',
+					'{execution_time}',
+					'{memory_usage}',
+					'{included_files}',
+				),
+				array
+				(
+					KOHANA::VERSION,
+					KOHANA::CODENAME,
+					$benchmark['time'],
+					number_format($memory, 2).'MB',
+					count(get_included_files()),
+				),
+				$output
+			);
+		}
+
+		if ($level = Kohana::config('core.output_compression') AND ini_get('output_handler') !== 'ob_gzhandler' AND (int) ini_get('zlib.output_compression') === 0)
+		{
+			if ($compress = request::preferred_encoding(array('gzip','deflate'), TRUE))
+			{
+				if ($level < 1 OR $level > 9)
+				{
+					// Normalize the level to be an integer between 1 and 9. This
+					// step must be done to prevent gzencode from triggering an error
+					$level = max(1, min($level, 9));
+				}
+
+				if ($compress === 'gzip')
+				{
+					// Compress output using gzip
+					$output = gzencode($output, $level);
+				}
+				elseif ($compress === 'deflate')
+				{
+					// Compress output using zlib (HTTP deflate)
+					$output = gzdeflate($output, $level);
+				}
+
+				// This header must be sent with compressed content to prevent
+				// browser caches from breaking
+				header('Vary: Accept-Encoding');
+
+				// Send the content encoding header
+				header('Content-Encoding: '.$compress);
+
+				// Sending Content-Length in CGI can result in unexpected behavior
+				if (stripos(Kohana::$server_api, 'cgi') === FALSE)
+				{
+					header('Content-Length: '.strlen($output));
+				}
+			}
+		}
+
+		echo $output;
+	}
+
+	/**
+	 * Provides class auto-loading.
+	 *
+	 * @throws  Kohana_Exception
+	 * @param   string  name of class
+	 * @return  bool
+	 */
+	public static function auto_load($class)
+	{
+		if (class_exists($class, FALSE) OR interface_exists($class, FALSE))
+			return TRUE;
+
+		if (($suffix = strrpos($class, '_')) > 0)
+		{
+			// Find the class suffix
+			$suffix = substr($class, $suffix + 1);
+		}
+		else
+		{
+			// No suffix
+			$suffix = FALSE;
+		}
+
+		if ($suffix === 'Core')
+		{
+			$type = 'libraries';
+			$file = substr($class, 0, -5);
+		}
+		elseif ($suffix === 'Controller')
+		{
+			$type = 'controllers';
+			// Lowercase filename
+			$file = strtolower(substr($class, 0, -11));
+		}
+		elseif ($suffix === 'Model')
+		{
+			$type = 'models';
+			// Lowercase filename
+			$file = strtolower(substr($class, 0, -6));
+		}
+		elseif ($suffix === 'Driver')
+		{
+			$type = 'libraries/drivers';
+			$file = str_replace('_', '/', substr($class, 0, -7));
+		}
+		else
+		{
+			// This could be either a library or a helper, but libraries must
+			// always be capitalized, so we check if the first character is
+			// uppercase. If it is, we are loading a library, not a helper.
+			$type = ($class[0] < 'a') ? 'libraries' : 'helpers';
+			$file = $class;
+		}
+
+		if ($filename = Kohana::find_file($type, $file))
+		{
+			// Load the class
+			require $filename;
+		}
+		else
+		{
+			// The class could not be found
+			return FALSE;
+		}
+
+		if ($filename = Kohana::find_file($type, Kohana::config('core.extension_prefix').$class))
+		{
+			// Load the class extension
+			require $filename;
+		}
+		elseif ($suffix !== 'Core' AND class_exists($class.'_Core', FALSE))
+		{
+			// Class extension to be evaluated
+			$extension = 'class '.$class.' extends '.$class.'_Core { }';
+
+			// Start class analysis
+			$core = new ReflectionClass($class.'_Core');
+
+			if ($core->isAbstract())
+			{
+				// Make the extension abstract
+				$extension = 'abstract '.$extension;
+			}
+
+			// Transparent class extensions are handled using eval. This is
+			// a disgusting hack, but it gets the job done.
+			eval($extension);
+		}
+
+		return TRUE;
+	}
+
+	/**
+	 * Find a resource file in a given directory. Files will be located according
+	 * to the order of the include paths. Configuration and i18n files will be
+	 * returned in reverse order.
+	 *
+	 * @throws  Kohana_Exception  if file is required and not found
+	 * @param   string   directory to search in
+	 * @param   string   filename to look for (without extension)
+	 * @param   boolean  file required
+	 * @param   string   file extension
+	 * @return  array    if the type is config, i18n or l10n
+	 * @return  string   if the file is found
+	 * @return  FALSE    if the file is not found
+	 */
+	public static function find_file($directory, $filename, $required = FALSE, $ext = FALSE)
+	{
+		// NOTE: This test MUST be not be a strict comparison (===), or empty
+		// extensions will be allowed!
+		if ($ext == '')
+		{
+			// Use the default extension
+			$ext = EXT;
+		}
+		else
+		{
+			// Add a period before the extension
+			$ext = '.'.$ext;
+		}
+
+		// Search path
+		$search = $directory.'/'.$filename.$ext;
+
+		if (isset(Kohana::$internal_cache['find_file_paths'][Kohana::$include_paths_hash][$search]))
+			return Kohana::$internal_cache['find_file_paths'][Kohana::$include_paths_hash][$search];
+
+		// Load include paths
+		$paths = Kohana::$include_paths;
+
+		// Nothing found, yet
+		$found = NULL;
+
+		if ($directory === 'config' OR $directory === 'messages' OR $directory === 'i18n')
+		{
+			// Search in reverse, for merging
+			$paths = array_reverse($paths);
+
+			foreach ($paths as $path)
+			{
+				if (is_file($path.$search))
+				{
+					// A matching file has been found
+					$found[] = $path.$search;
+				}
+			}
+		}
+		else
+		{
+			foreach ($paths as $path)
+			{
+				if (is_file($path.$search))
+				{
+					// A matching file has been found
+					$found = $path.$search;
+
+					// Stop searching
+					break;
+				}
+			}
+		}
+
+		if ($found === NULL)
+		{
+			if ($required === TRUE)
+			{
+				// If the file is required, throw an exception
+				throw new Kohana_Exception('The requested :resource:, :file:, could not be found', array(':resource:' => __($directory), ':file:' =>$filename));
+			}
+			else
+			{
+				// Nothing was found, return FALSE
+				$found = FALSE;
+			}
+		}
+
+		if ( ! isset(Kohana::$write_cache['find_file_paths']))
+		{
+			// Write cache at shutdown
+			Kohana::$write_cache['find_file_paths'] = TRUE;
+		}
+
+		return Kohana::$internal_cache['find_file_paths'][Kohana::$include_paths_hash][$search] = $found;
+	}
+
+	/**
+	 * Lists all files and directories in a resource path.
+	 *
+	 * @param   string   directory to search
+	 * @param   boolean  list all files to the maximum depth?
+	 * @param   string   list all files having extension $ext
+	 * @param   string   full path to search (used for recursion, *never* set this manually)
+	 * @return  array    filenames and directories
+	 */
+	public static function list_files($directory, $recursive = FALSE, $ext = EXT, $path = FALSE)
+	{
+		$files = array();
+
+		if ($path === FALSE)
+		{
+			$paths = array_reverse(Kohana::include_paths());
+
+			foreach ($paths as $path)
+			{
+				// Recursively get and merge all files
+				$files = array_merge($files, Kohana::list_files($directory, $recursive, $ext, $path.$directory));
+			}
+		}
+		else
+		{
+			$path = rtrim($path, '/').'/';
+
+			if (is_readable($path) AND $items = glob($path.'*'))
+			{
+				$ext_pos = 0 - strlen($ext);
+
+				foreach ($items as $index => $item)
+				{
+					$item = str_replace('\\', '/', $item);
+
+					if (is_dir($item))
+					{
+						// Handle recursion
+						if ($recursive === TRUE)
+						{
+							// Filename should only be the basename
+							$item = pathinfo($item, PATHINFO_BASENAME);
+
+							// Append sub-directory search
+							$files = array_merge($files, Kohana::list_files($directory, TRUE, $ext, $path.$item));
+						}
+					}
+					else
+					{
+						// File extension must match
+						if ($ext_pos === 0 OR substr($item, $ext_pos) === $ext)
+						{
+							$files[] = $item;
+						}
+					}
+				}
+			}
+		}
+
+		return $files;
+	}
+
+
+	/**
+	 * Fetch a message item.
+	 *
+	 * @param   string  language key to fetch
+	 * @param   array   additional information to insert into the line
+	 * @return  string  i18n language string, or the requested key if the i18n item is not found
+	 */
+	public static function message($key, $args = array())
+	{
+		// Extract the main group from the key
+		$group = explode('.', $key, 2);
+		$group = $group[0];
+
+		if ( ! isset(Kohana::$internal_cache['messages'][$group]))
+		{
+			// Messages for this group
+			$messages = array();
+
+			if ($file = Kohana::find_file('messages', $group))
+			{
+				include $file[0];
+			}
+
+			if ( ! isset(Kohana::$write_cache['messages']))
+			{
+				// Write language cache
+				Kohana::$write_cache['messages'] = TRUE;
+			}
+
+			Kohana::$internal_cache['messages'][$group] = $messages;
+		}
+
+		// Get the line from cache
+		$line = Kohana::key_string(Kohana::$internal_cache['messages'], $key);
+
+		if ($line === NULL)
+		{
+			Kohana_Log::add('error', 'Missing messages entry '.$key.' for message '.$group);
+
+			// Return the key string as fallback
+			return $key;
+		}
+
+		if (is_string($line) AND func_num_args() > 1)
+		{
+			$args = array_slice(func_get_args(), 1);
+
+			// Add the arguments into the line
+			$line = vsprintf($line, is_array($args[0]) ? $args[0] : $args);
+		}
+
+		return $line;
+	}
+
+	/**
+	 * Returns the value of a key, defined by a 'dot-noted' string, from an array.
+	 *
+	 * @param   array   array to search
+	 * @param   string  dot-noted string: foo.bar.baz
+	 * @return  string  if the key is found
+	 * @return  void    if the key is not found
+	 */
+	public static function key_string($array, $keys)
+	{
+		if (empty($array))
+			return NULL;
+
+		// Prepare for loop
+		$keys = explode('.', $keys);
+
+		do
+		{
+			// Get the next key
+			$key = array_shift($keys);
+
+			if (isset($array[$key]))
+			{
+				if (is_array($array[$key]) AND ! empty($keys))
+				{
+					// Dig down to prepare the next loop
+					$array = $array[$key];
+				}
+				else
+				{
+					// Requested key was found
+					return $array[$key];
+				}
+			}
+			else
+			{
+				// Requested key is not set
+				break;
+			}
+		}
+		while ( ! empty($keys));
+
+		return NULL;
+	}
+
+	/**
+	 * Sets values in an array by using a 'dot-noted' string.
+	 *
+	 * @param   array   array to set keys in (reference)
+	 * @param   string  dot-noted string: foo.bar.baz
+	 * @return  mixed   fill value for the key
+	 * @return  void
+	 */
+	public static function key_string_set( & $array, $keys, $fill = NULL)
+	{
+		if (is_object($array) AND ($array instanceof ArrayObject))
+		{
+			// Copy the array
+			$array_copy = $array->getArrayCopy();
+
+			// Is an object
+			$array_object = TRUE;
+		}
+		else
+		{
+			if ( ! is_array($array))
+			{
+				// Must always be an array
+				$array = (array) $array;
+			}
+
+			// Copy is a reference to the array
+			$array_copy =& $array;
+		}
+
+		if (empty($keys))
+			return $array;
+
+		// Create keys
+		$keys = explode('.', $keys);
+
+		// Create reference to the array
+		$row =& $array_copy;
+
+		for ($i = 0, $end = count($keys) - 1; $i <= $end; $i++)
+		{
+			// Get the current key
+			$key = $keys[$i];
+
+			if ( ! isset($row[$key]))
+			{
+				if (isset($keys[$i + 1]))
+				{
+					// Make the value an array
+					$row[$key] = array();
+				}
+				else
+				{
+					// Add the fill key
+					$row[$key] = $fill;
+				}
+			}
+			elseif (isset($keys[$i + 1]))
+			{
+				// Make the value an array
+				$row[$key] = (array) $row[$key];
+			}
+
+			// Go down a level, creating a new row reference
+			$row =& $row[$key];
+		}
+
+		if (isset($array_object))
+		{
+			// Swap the array back in
+			$array->exchangeArray($array_copy);
+		}
+	}
+
+	/**
+	 * Quick debugging of any variable. Any number of parameters can be set.
+	 *
+	 * @return  string
+	 */
+	public static function debug()
+	{
+		if (func_num_args() === 0)
+			return;
+
+		// Get params
+		$params = func_get_args();
+		$output = array();
+
+		foreach ($params as $var)
+		{
+			$value = is_bool($var) ? ($var ? 'true' : 'false') : print_r($var, TRUE);
+			$output[] = '<pre>('.gettype($var).') '.htmlspecialchars($value, ENT_QUOTES, Kohana::CHARSET).'</pre>';
+		}
+
+		return implode("\n", $output);
+	}
+
+	/**
+	 * Saves the internal caches: configuration, include paths, etc.
+	 *
+	 * @return  boolean
+	 */
+	public static function internal_cache_save()
+	{
+		if ( ! is_array(Kohana::$write_cache))
+			return FALSE;
+
+		// Get internal cache names
+		$caches = array_keys(Kohana::$write_cache);
+
+		// Nothing written
+		$written = FALSE;
+
+		foreach ($caches as $cache)
+		{
+			if (isset(Kohana::$internal_cache[$cache]))
+			{
+				// Write the cache file
+				Kohana::cache_save($cache, Kohana::$internal_cache[$cache], Kohana::config('core.internal_cache'));
+
+				// A cache has been written
+				$written = TRUE;
+			}
+		}
+
+		return $written;
+	}
+
+} // End Kohana
diff --git a/system/core/Kohana_Config.php b/system/core/Kohana_Config.php
new file mode 100644
index 0000000..9abc5b6
--- /dev/null
+++ b/system/core/Kohana_Config.php
@@ -0,0 +1,329 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Provides a driver-based interface for setting and getting
+ * configuration options for the Kohana environment
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Kohana_Config_Core implements ArrayAccess {
+
+	/**
+	 * The default Kohana_Config driver
+	 * to use for system setup
+	 *
+	 * @var     string
+	 * @static
+	 */
+	public static $default_driver = 'array';
+
+	/**
+	 * Kohana_Config instance
+	 *
+	 * @var     array
+	 * @static
+	 */
+	protected static $instance;
+
+	/**
+	 * Returns a new instance of the Kohana_Config library
+	 * based on the singleton pattern
+	 *
+	 * @param   string       driver
+	 * @return  Kohana_Config
+	 * @access  public
+	 * @static
+	 */
+	public static function & instance()
+	{
+		// If the driver has not been initialised, intialise it
+		if ( empty(Kohana_Config::$instance))
+		{
+			//call a 1 time non singleton of Kohana_Config to get a list of drivers
+			$config = new Kohana_Config(array(
+				'config_drivers'=>array(
+				), 'internal_cache'=>FALSE
+			));
+			$core_config = $config->get('core');
+			Kohana_Config::$instance = new Kohana_Config($core_config);
+		}
+
+		// Return the Kohana_Config driver requested
+		return Kohana_Config::$instance;
+	}
+
+	/**
+	 * The drivers for this object
+	 *
+	 * @var     Kohana_Config_Driver
+	 */
+	protected $drivers;
+
+	/**
+	 * Kohana_Config constructor to load the supplied driver.
+	 * Enforces the singleton pattern.
+	 *
+	 * @param   string       driver
+	 * @access  protected
+	 */
+	protected function __construct(array $core_config)
+	{
+		$drivers = $core_config['config_drivers'];
+
+		//remove array if it's found in config
+		if (in_array('array', $drivers))
+			unset($drivers[array_search('array', $drivers)]);
+
+		//add array at the very end
+		$this->drivers = $drivers = array_merge($drivers, array(
+			'array'
+		));
+
+		foreach ($this->drivers as & $driver)
+		{
+			// Create the driver name
+			$driver = 'Config_'.ucfirst($driver).'_Driver';
+
+			// Ensure the driver loads correctly
+			if (!Kohana::auto_load($driver))
+				throw new Kohana_Exception('The :driver: driver for the :library: library could not be found.', array(
+					':driver:' => $driver, ':library:' => get_class($this)
+				));
+
+			// Load the new driver
+			$driver = new $driver($core_config);
+
+			// Ensure the new driver is valid
+			if (!$driver instanceof Config_Driver)
+				throw new Kohana_Exception('The :driver: driver for the :library: library must implement the :interface: interface', array(
+					':driver:' => $driver, ':library:' => get_class($this), ':interface:' => 'Config_Driver'
+				));
+		}
+	}
+
+	/**
+	 * Gets a value from the configuration driver
+	 *
+	 * @param   string       key
+	 * @param   bool         slash
+	 * @param   bool         required
+	 * @return  mixed
+	 * @access  public
+	 */
+	public function get($key, $slash = FALSE, $required = FALSE)
+	{
+		foreach ($this->drivers as $driver)
+		{
+			try
+			{
+				return $driver->get($key, $slash, $required);
+			}
+			catch (Kohana_Config_Exception $e)
+			{
+				//if it's the last driver in the list and it threw an exception, re throw it
+				if ($driver === $this->drivers[(count($this->drivers) - 1)])
+					throw $e;
+			}
+		}
+	}
+
+	/**
+	 * Sets a value to the configuration drivers
+	 *
+	 * @param   string       key
+	 * @param   mixed        value
+	 * @return  bool
+	 * @access  public
+	 */
+	public function set($key, $value)
+	{
+		foreach ($this->drivers as $driver)
+		{
+			try
+			{
+				$driver->set($key, $value);
+			}
+			catch (Kohana_Config_Exception $e)
+			{
+				//if it's the last driver in the list and it threw an exception, re throw it
+				if ($driver === $this->drivers[(count($this->drivers) - 1)])
+					throw $e;
+			}
+		}
+		return TRUE;
+	}
+
+	/**
+	 * Clears a group from configuration
+	 *
+	 * @param   string       group
+	 * @return  bool
+	 * @access  public
+	 */
+	public function clear($group)
+	{
+		foreach ($this->drivers as $driver)
+		{
+			try
+			{
+				$driver->clear($group);
+			}
+			catch (Kohana_Config_Exception $e)
+			{
+				//if it's the last driver in the list and it threw an exception, re throw it
+				if ($driver === $this->drivers[(count($this->drivers) - 1)])
+					throw $e;
+			}
+		}
+		return TRUE;
+	}
+
+	/**
+	 * Loads a configuration group
+	 *
+	 * @param   string       group
+	 * @param   bool         required
+	 * @return  array
+	 * @access  public
+	 */
+	public function load($group, $required = FALSE)
+	{
+		foreach ($this->drivers as $driver)
+		{
+			try
+			{
+				return $driver->load($group, $required);
+			}
+			catch (Kohana_Config_Exception $e)
+			{
+				//if it's the last driver in the list and it threw an exception, re throw it
+				if ($driver === $this->drivers[(count($this->drivers) - 1)])
+					throw $e;
+			}
+		}
+	}
+
+	/**
+	 * Returns true or false if any config has been loaded(either manually or from cache)
+	 *
+	 * @return boolean
+	 */
+	public function loaded()
+	{
+		return $this->drivers[(count($this->drivers) - 1)]->loaded;
+	}
+
+	/**
+	 * The following allows access using
+	 * array syntax.
+	 *
+	 * @example  $config['core.site_domain']
+	 */
+
+	 /**
+	 * Allows access to configuration settings
+	 * using the ArrayAccess interface
+	 *
+	 * @param   string       key
+	 * @return  mixed
+	 * @access  public
+	 */
+	public function offsetGet($key)
+	{
+		foreach ($this->drivers as $driver)
+		{
+			try
+			{
+				return $driver->get($key);
+			}
+			catch (Kohana_Config_Exception $e)
+			{
+				//if it's the last driver in the list and it threw an exception, re throw it
+				if ($driver === $this->drivers[(count($this->drivers) - 1)])
+					throw $e;
+			}
+		}
+	}
+
+	/**
+	 * Allows access to configuration settings
+	 * using the ArrayAccess interface
+	 *
+	 * @param   string       key
+	 * @param   mixed        value
+	 * @return  bool
+	 * @access  public
+	 */
+	public function offsetSet($key, $value)
+	{
+		foreach ($this->drivers as $driver)
+		{
+			try
+			{
+				$driver->set($key, $value);
+			}
+			catch (Kohana_Config_Exception $e)
+			{
+				//if it's the last driver in the list and it threw an exception, re throw it
+				if ($driver === $this->drivers[(count($this->drivers) - 1)])
+					throw $e;
+			}
+		}
+		return TRUE;
+	}
+
+	/**
+	 * Allows access to configuration settings
+	 * using the ArrayAccess interface
+	 *
+	 * @param   string       key
+	 * @return  bool
+	 * @access  public
+	 */
+	public function offsetExists($key)
+	{
+		foreach ($this->drivers as $driver)
+		{
+			try
+			{
+				return $driver->setting_exists($key);
+			}
+			catch (Kohana_Config_Exception $e)
+			{
+				//if it's the last driver in the list and it threw an exception, re throw it
+				if ($driver === $this->drivers[(count($this->drivers) - 1)])
+					throw $e;
+			}
+		}
+	}
+
+	/**
+	 * Allows access to configuration settings
+	 * using the ArrayAccess interface
+	 *
+	 * @param   string       key
+	 * @return  bool
+	 * @access  public
+	 */
+	public function offsetUnset($key)
+	{
+		foreach ($this->drivers as $driver)
+		{
+			try
+			{
+				return $driver->set($key, NULL);
+			}
+			catch (Kohana_Config_Exception $e)
+			{
+				//if it's the last driver in the list and it threw an exception, re throw it
+				if ($driver === $this->drivers[(count($this->drivers) - 1)])
+					throw $e;
+			}
+		}
+		return TRUE;
+	}
+} // End KohanaConfig
+
+class Kohana_Config_Exception extends Kohana_Exception {}
diff --git a/system/core/Kohana_Exception.php b/system/core/Kohana_Exception.php
new file mode 100644
index 0000000..bc0efd1
--- /dev/null
+++ b/system/core/Kohana_Exception.php
@@ -0,0 +1,622 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Kohana Exceptions
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+class Kohana_Exception_Core extends Exception {
+
+	public static $enabled = FALSE;
+
+	// Template file
+	public static $template = 'kohana/error';
+
+	// Show stack traces in errors
+	public static $trace_output = TRUE;
+
+	// Show source code in errors
+	public static $source_output = TRUE;
+
+	// To hold unique identifier to distinguish error output
+	protected $instance_identifier;
+
+	// Error code
+	protected $code = E_KOHANA;
+
+	/**
+	 * Creates a new translated exception.
+	 *
+	 * @param string error message
+	 * @param array translation variables
+	 * @return void
+	 */
+	public function __construct($message, array $variables = NULL, $code = 0)
+	{
+		$this->instance_identifier = uniqid();
+
+		// Translate the error message
+		$message = __($message, $variables);
+
+		// Sets $this->message the proper way
+		parent::__construct($message, $code);
+	}
+
+	/**
+	 * Enable Kohana exception handling.
+	 *
+	 * @uses    Kohana_Exception::$template
+	 * @return  void
+	 */
+	public static function enable()
+	{
+		if ( ! Kohana_Exception::$enabled)
+		{
+			set_exception_handler(array('Kohana_Exception', 'handle'));
+
+			Kohana_Exception::$enabled = TRUE;
+		}
+	}
+
+	/**
+	 * Disable Kohana exception handling.
+	 *
+	 * @return  void
+	 */
+	public static function disable()
+	{
+		if (Kohana_Exception::$enabled)
+		{
+			restore_exception_handler();
+
+			Kohana_Exception::$enabled = FALSE;
+		}
+	}
+
+	/**
+	 * Get a single line of text representing the exception:
+	 *
+	 * Error [ Code ]: Message ~ File [ Line ]
+	 *
+	 * @param   object  Exception
+	 * @return  string
+	 */
+	public static function text($e)
+	{
+		return sprintf('%s [ %s ]: %s ~ %s [ %d ]',
+			get_class($e), $e->getCode(), strip_tags($e->getMessage()), Kohana_Exception::debug_path($e->getFile()), $e->getLine());
+	}
+
+	/**
+	 * exception handler, displays the error message, source of the
+	 * exception, and the stack trace of the error.
+	 *
+	 * @uses    Kohana::message()
+	 * @uses    Kohana_Exception::text()
+	 * @param   object   exception object
+	 * @return  void
+	 */
+	public static function handle(Exception $e)
+	{
+		try
+		{
+			// Get the exception information
+			$type    = get_class($e);
+			$code    = $e->getCode();
+			$message = $e->getMessage();
+
+			// Create a text version of the exception
+			$error = Kohana_Exception::text($e);
+
+			// Add this exception to the log
+			Kohana_Log::add('error', $error);
+
+			// Manually save logs after exceptions
+			Kohana_Log::save();
+
+			if (Kohana::config('kohana/core.display_errors') === FALSE)
+			{
+				// Do not show the details
+				$file = $line = NULL;
+				$trace = array();
+
+				$template = '_disabled';
+			}
+			else
+			{
+				$file = $e->getFile();
+				$line = $e->getLine();
+				$trace = $e->getTrace();
+
+				$template = '';
+			}
+
+			if ($e instanceof Kohana_Exception)
+			{
+				$template = $e->getTemplate().$template;
+
+				if ( ! headers_sent())
+				{
+					$e->sendHeaders();
+				}
+
+				// Use the human-readable error name
+				$code = Kohana::message('kohana/core.errors.'.$code);
+			}
+			else
+			{
+				$template = Kohana_Exception::$template.$template;
+
+				if ( ! headers_sent())
+				{
+					header('HTTP/1.1 500 Internal Server Error');
+				}
+
+				if ($e instanceof ErrorException)
+				{
+					// Use the human-readable error name
+					$code = Kohana::message('kohana/core.errors.'.$e->getSeverity());
+
+					if (version_compare(PHP_VERSION, '5.3', '<'))
+					{
+						// Workaround for a bug in ErrorException::getTrace() that exists in
+						// all PHP 5.2 versions. @see http://bugs.php.net/45895
+						for ($i = count($trace) - 1; $i > 0; --$i)
+						{
+							if (isset($trace[$i - 1]['args']))
+							{
+								// Re-position the arguments
+								$trace[$i]['args'] = $trace[$i - 1]['args'];
+
+								unset($trace[$i - 1]['args']);
+							}
+						}
+					}
+				}
+			}
+
+			// Clean the output buffer if one exists
+			ob_get_level() and ob_clean();
+
+			if ($template = Kohana::find_file('views', $template))
+			{
+				include $template;
+			}
+		}
+		catch (Exception $e)
+		{
+			// Clean the output buffer if one exists
+			ob_get_level() and ob_clean();
+
+			// Display the exception text
+			echo Kohana_Exception::text($e), "\n";
+		}
+
+		if (Kohana::$server_api === 'cli')
+		{
+			// Exit with an error status
+			exit(1);
+		}
+	}
+
+	/**
+	 * Returns the template for this exception.
+	 *
+	 * @uses    Kohana_Exception::$template
+	 * @return  string
+	 */
+	public function getTemplate()
+	{
+		return Kohana_Exception::$template;
+	}
+
+	/**
+	 * Sends an Internal Server Error header.
+	 *
+	 * @return  void
+	 */
+	public function sendHeaders()
+	{
+		// Send the 500 header
+		header('HTTP/1.1 500 Internal Server Error');
+	}
+
+	/**
+	 * Returns an HTML string of information about a single variable.
+	 *
+	 * Borrows heavily on concepts from the Debug class of {@link http://nettephp.com/ Nette}.
+	 *
+	 * @param   mixed    variable to dump
+	 * @param   integer  maximum length of strings
+	 * @param   integer  maximum levels of recursion
+	 * @return  string
+	 */
+	public static function dump($value, $length = 128, $max_level = 5)
+	{
+		return Kohana_Exception::_dump($value, $length, $max_level);
+	}
+
+	/**
+	 * Helper for Kohana_Exception::dump(), handles recursion in arrays and objects.
+	 *
+	 * @param   mixed    variable to dump
+	 * @param   integer  maximum length of strings
+	 * @param   integer  maximum levels of recursion
+	 * @param   integer  current recursion level (internal)
+	 * @return  string
+	 */
+	private static function _dump( & $var, $length = 128, $max_level = 5, $level = 0)
+	{
+		if ($var === NULL)
+		{
+			return '<small>NULL</small>';
+		}
+		elseif (is_bool($var))
+		{
+			return '<small>bool</small> '.($var ? 'TRUE' : 'FALSE');
+		}
+		elseif (is_float($var))
+		{
+			return '<small>float</small> '.$var;
+		}
+		elseif (is_resource($var))
+		{
+			if (($type = get_resource_type($var)) === 'stream' AND $meta = stream_get_meta_data($var))
+			{
+				$meta = stream_get_meta_data($var);
+
+				if (isset($meta['uri']))
+				{
+					$file = $meta['uri'];
+
+					if (function_exists('stream_is_local'))
+					{
+						// Only exists on PHP >= 5.2.4
+						if (stream_is_local($file))
+						{
+							$file = Kohana_Exception::debug_path($file);
+						}
+					}
+
+					return '<small>resource</small><span>('.$type.')</span> '.htmlspecialchars($file, ENT_NOQUOTES, Kohana::CHARSET);
+				}
+			}
+			else
+			{
+				return '<small>resource</small><span>('.$type.')</span>';
+			}
+		}
+		elseif (is_string($var))
+		{
+			if (strlen($var) > $length)
+			{
+				// Encode the truncated string
+				$str = htmlspecialchars(substr($var, 0, $length), ENT_NOQUOTES, Kohana::CHARSET).'&nbsp;&hellip;';
+			}
+			else
+			{
+				// Encode the string
+				$str = htmlspecialchars($var, ENT_NOQUOTES, Kohana::CHARSET);
+			}
+
+			return '<small>string</small><span>('.strlen($var).')</span> "'.$str.'"';
+		}
+		elseif (is_array($var))
+		{
+			$output = array();
+
+			// Indentation for this variable
+			$space = str_repeat($s = '    ', $level);
+
+			static $marker;
+
+			if ($marker === NULL)
+			{
+				// Make a unique marker
+				$marker = uniqid("\x00");
+			}
+
+			if (empty($var))
+			{
+				// Do nothing
+			}
+			elseif (isset($var[$marker]))
+			{
+				$output[] = "(\n$space$s*RECURSION*\n$space)";
+			}
+			elseif ($level <= $max_level)
+			{
+				$output[] = "<span>(";
+
+				$var[$marker] = TRUE;
+				foreach ($var as $key => & $val)
+				{
+					if ($key === $marker) continue;
+					if ( ! is_int($key))
+					{
+						$key = '"'.$key.'"';
+					}
+
+					$output[] = "$space$s$key => ".Kohana_Exception::_dump($val, $length, $max_level, $level + 1);
+				}
+				unset($var[$marker]);
+
+				$output[] = "$space)</span>";
+			}
+			else
+			{
+				// Depth too great
+				$output[] = "(\n$space$s...\n$space)";
+			}
+
+			return '<small>array</small><span>('.count($var).')</span> '.implode("\n", $output);
+		}
+		elseif (is_object($var))
+		{
+			// Copy the object as an array
+			$array = (array) $var;
+
+			$output = array();
+
+			// Indentation for this variable
+			$space = str_repeat($s = '    ', $level);
+
+			$hash = spl_object_hash($var);
+
+			// Objects that are being dumped
+			static $objects = array();
+
+			if (empty($var))
+			{
+				// Do nothing
+			}
+			elseif (isset($objects[$hash]))
+			{
+				$output[] = "{\n$space$s*RECURSION*\n$space}";
+			}
+			elseif ($level <= $max_level)
+			{
+				$output[] = "<code>{";
+
+				$objects[$hash] = TRUE;
+				foreach ($array as $key => & $val)
+				{
+					if ($key[0] === "\x00")
+					{
+						// Determine if the access is private or protected
+						$access = '<small>'.($key[1] === '*' ? 'protected' : 'private').'</small>';
+
+						// Remove the access level from the variable name
+						$key = substr($key, strrpos($key, "\x00") + 1);
+					}
+					else
+					{
+						$access = '<small>public</small>';
+					}
+
+					$output[] = "$space$s$access $key => ".Kohana_Exception::_dump($val, $length, $max_level, $level + 1);
+				}
+				unset($objects[$hash]);
+
+				$output[] = "$space}</code>";
+			}
+			else
+			{
+				// Depth too great
+				$output[] = "{\n$space$s...\n$space}";
+			}
+
+			return '<small>object</small> <span>'.get_class($var).'('.count($array).')</span> '.implode("\n", $output);
+		}
+		else
+		{
+			return '<small>'.gettype($var).'</small> '.htmlspecialchars(print_r($var, TRUE), ENT_NOQUOTES, Kohana::CHARSET);
+		}
+	}
+
+	/**
+	 * Removes APPPATH, SYSPATH, MODPATH, and DOCROOT from filenames, replacing
+	 * them with the plain text equivalents.
+	 *
+	 * @param   string  path to sanitize
+	 * @return  string
+	 */
+	public static function debug_path($file)
+	{
+		// Normalize directory separator
+		$file = str_replace('\\', '/', $file);
+
+		if (strpos($file, APPPATH) === 0)
+		{
+			$file = 'APPPATH/'.substr($file, strlen(APPPATH));
+		}
+		elseif (strpos($file, SYSPATH) === 0)
+		{
+			$file = 'SYSPATH/'.substr($file, strlen(SYSPATH));
+		}
+		elseif (strpos($file, MODPATH) === 0)
+		{
+			$file = 'MODPATH/'.substr($file, strlen(MODPATH));
+		}
+		elseif (strpos($file, DOCROOT) === 0)
+		{
+			$file = 'DOCROOT/'.substr($file, strlen(DOCROOT));
+		}
+
+		return $file;
+	}
+
+	/**
+	 * Returns an array of lines from a file.
+	 *
+	 *     // Returns the current line of the current file
+	 *     echo Kohana_Exception::debug_source(__FILE__, __LINE__);
+	 *
+	 * @param   string   file to open
+	 * @param   integer  line number to find
+	 * @param   integer  number of padding lines
+	 * @return  array
+	 */
+	public static function debug_source($file, $line_number, $padding = 5)
+	{
+		// Make sure we can read the source file
+		if ( ! is_readable($file))
+			return array();
+
+		// Open the file and set the line position
+		$file = fopen($file, 'r');
+		$line = 0;
+
+		// Set the reading range
+		$range = array('start' => $line_number - $padding, 'end' => $line_number + $padding);
+
+		// Set the zero-padding amount for line numbers
+		$format = '% '.strlen($range['end']).'d';
+
+		$source = array();
+		while (($row = fgets($file)) !== FALSE)
+		{
+			// Increment the line number
+			if (++$line > $range['end'])
+				break;
+
+			if ($line >= $range['start'])
+			{
+				$source[sprintf($format, $line)] = $row;
+			}
+		}
+
+		// Close the file
+		fclose($file);
+
+		return $source;
+	}
+
+	/**
+	 * Returns an array of strings that represent each step in the backtrace.
+	 *
+	 * @param   array  trace to analyze
+	 * @return  array
+	 */
+	public static function trace($trace = NULL)
+	{
+		if ($trace === NULL)
+		{
+			// Start a new trace
+			$trace = debug_backtrace();
+		}
+
+		// Non-standard function calls
+		$statements = array('include', 'include_once', 'require', 'require_once');
+
+		$output = array();
+		foreach ($trace as $step)
+		{
+			if ( ! isset($step['function']))
+			{
+				// Invalid trace step
+				continue;
+			}
+
+			if (isset($step['file']) AND isset($step['line']))
+			{
+				// Include the source of this step
+				$source = Kohana_Exception::debug_source($step['file'], $step['line']);
+			}
+
+			if (isset($step['file']))
+			{
+				$file = $step['file'];
+
+				if (isset($step['line']))
+				{
+					$line = $step['line'];
+				}
+			}
+
+			// function()
+			$function = $step['function'];
+
+			if (in_array($step['function'], $statements))
+			{
+				if (empty($step['args']))
+				{
+					// No arguments
+					$args = array();
+				}
+				else
+				{
+					// Sanitize the file path
+					$args = array($step['args'][0]);
+				}
+			}
+			elseif (isset($step['args']))
+			{
+				if ($step['function'] === '{closure}')
+				{
+					// Introspection on closures in a stack trace is impossible
+					$params = NULL;
+				}
+				else
+				{
+					if (isset($step['class']))
+					{
+						if (method_exists($step['class'], $step['function']))
+						{
+							$reflection = new ReflectionMethod($step['class'], $step['function']);
+						}
+						else
+						{
+							$reflection = new ReflectionMethod($step['class'], '__call');
+						}
+					}
+					else
+					{
+						$reflection = new ReflectionFunction($step['function']);
+					}
+
+					// Get the function parameters
+					$params = $reflection->getParameters();
+				}
+
+				$args = array();
+
+				foreach ($step['args'] as $i => $arg)
+				{
+					if (isset($params[$i]))
+					{
+						// Assign the argument by the parameter name
+						$args[$params[$i]->name] = $arg;
+					}
+					else
+					{
+						// Assign the argument by number
+						$args[$i] = $arg;
+					}
+				}
+			}
+
+			if (isset($step['class']))
+			{
+				// Class->method() or Class::method()
+				$function = $step['class'].$step['type'].$step['function'];
+			}
+
+			$output[] = array(
+				'function' => $function,
+				'args'     => isset($args)   ? $args : NULL,
+				'file'     => isset($file)   ? $file : NULL,
+				'line'     => isset($line)   ? $line : NULL,
+				'source'   => isset($source) ? $source : NULL,
+			);
+
+			unset($function, $args, $file, $line, $source);
+		}
+
+		return $output;
+	}
+
+} // End Kohana Exception
diff --git a/system/helpers/arr.php b/system/helpers/arr.php
new file mode 100644
index 0000000..19026fa
--- /dev/null
+++ b/system/helpers/arr.php
@@ -0,0 +1,273 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Array helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class arr_Core {
+
+	/**
+	 * Return a callback array from a string, eg: limit[10,20] would become
+	 * array('limit', array('10', '20'))
+	 *
+	 * @param   string  callback string
+	 * @return  array
+	 */
+	public static function callback_string($str)
+	{
+		// command[param,param]
+		if (preg_match('/([^\[]*+)\[(.+)\]/', (string) $str, $match))
+		{
+			// command
+			$command = $match[1];
+
+			// param,param
+			$params = preg_split('/(?<!\\\\),/', $match[2]);
+			$params = str_replace('\,', ',', $params);
+		}
+		else
+		{
+			// command
+			$command = $str;
+
+			// No params
+			$params = NULL;
+		}
+
+		return array($command, $params);
+	}
+
+	/**
+	 * Rotates a 2D array clockwise.
+	 * Example, turns a 2x3 array into a 3x2 array.
+	 *
+	 * @param   array    array to rotate
+	 * @param   boolean  keep the keys in the final rotated array. the sub arrays of the source array need to have the same key values.
+	 *                   if your subkeys might not match, you need to pass FALSE here!
+	 * @return  array
+	 */
+	public static function rotate($source_array, $keep_keys = TRUE)
+	{
+		$new_array = array();
+		foreach ($source_array as $key => $value)
+		{
+			$value = ($keep_keys === TRUE) ? $value : array_values($value);
+			foreach ($value as $k => $v)
+			{
+				$new_array[$k][$key] = $v;
+			}
+		}
+
+		return $new_array;
+	}
+
+	/**
+	 * Removes a key from an array and returns the value.
+	 *
+	 * @param   string  key to return
+	 * @param   array   array to work on
+	 * @return  mixed   value of the requested array key
+	 */
+	public static function remove($key, & $array)
+	{
+		if ( ! array_key_exists($key, $array))
+			return NULL;
+
+		$val = $array[$key];
+		unset($array[$key]);
+
+		return $val;
+	}
+
+
+	/**
+	 * Extract one or more keys from an array. Each key given after the first
+	 * argument (the array) will be extracted. Keys that do not exist in the
+	 * search array will be NULL in the extracted data.
+	 *
+	 * @param   array   array to search
+	 * @param   string  key name
+	 * @return  array
+	 */
+	public static function extract(array $search, $keys)
+	{
+		// Get the keys, removing the $search array
+		$keys = array_slice(func_get_args(), 1);
+
+		$found = array();
+		foreach ($keys as $key)
+		{
+			$found[$key] = isset($search[$key]) ? $search[$key] : NULL;
+		}
+
+		return $found;
+	}
+
+	/**
+	 * Get the value of array[key]. If it doesn't exist, return default.
+	 *
+	 * @param   array   array to search
+	 * @param   string  key name
+	 * @param   mixed   default value
+	 * @return  mixed
+	 */
+	public static function get(array $array, $key, $default = NULL)
+	{
+		return isset($array[$key]) ? $array[$key] : $default;
+	}
+
+	/**
+	 * Because PHP does not have this function.
+	 *
+	 * @param   array   array to unshift
+	 * @param   string  key to unshift
+	 * @param   mixed   value to unshift
+	 * @return  array
+	 */
+	public static function unshift_assoc( array & $array, $key, $val)
+	{
+		$array = array_reverse($array, TRUE);
+		$array[$key] = $val;
+		$array = array_reverse($array, TRUE);
+
+		return $array;
+	}
+
+	/**
+	 * Because PHP does not have this function, and array_walk_recursive creates
+	 * references in arrays and is not truly recursive.
+	 *
+	 * @param   mixed  callback to apply to each member of the array
+	 * @param   array  array to map to
+	 * @return  array
+	 */
+	public static function map_recursive($callback, array $array)
+	{
+		foreach ($array as $key => $val)
+		{
+			// Map the callback to the key
+			$array[$key] = is_array($val) ? arr::map_recursive($callback, $val) : call_user_func($callback, $val);
+		}
+
+		return $array;
+	}
+
+	/**
+	 * Emulates array_merge_recursive, but appends numeric keys and replaces
+	 * associative keys, instead of appending all keys.
+	 *
+	 * @param   array  any number of arrays
+	 * @return  array
+	 */
+	public static function merge()
+	{
+		$total = func_num_args();
+
+		$result = array();
+		for ($i = 0; $i < $total; $i++)
+		{
+			foreach (func_get_arg($i) as $key => $val)
+			{
+				if (isset($result[$key]))
+				{
+					if (is_array($val))
+					{
+						// Arrays are merged recursively
+						$result[$key] = arr::merge($result[$key], $val);
+					}
+					elseif (is_int($key))
+					{
+						// Indexed arrays are appended
+						array_push($result, $val);
+					}
+					else
+					{
+						// Associative arrays are replaced
+						$result[$key] = $val;
+					}
+				}
+				else
+				{
+					// New values are added
+					$result[$key] = $val;
+				}
+			}
+		}
+
+		return $result;
+	}
+
+	/**
+	 * Overwrites an array with values from input array(s).
+	 * Non-existing keys will not be appended!
+	 *
+	 * @param   array   key array
+	 * @param   array   input array(s) that will overwrite key array values
+	 * @return  array
+	 */
+	public static function overwrite($array1, $array2)
+	{
+		foreach (array_intersect_key($array2, $array1) as $key => $value)
+		{
+			$array1[$key] = $value;
+		}
+
+		if (func_num_args() > 2)
+		{
+			foreach (array_slice(func_get_args(), 2) as $array2)
+			{
+				foreach (array_intersect_key($array2, $array1) as $key => $value)
+				{
+					$array1[$key] = $value;
+				}
+			}
+		}
+
+		return $array1;
+	}
+
+	/**
+	 * Recursively convert an array to an object.
+	 *
+	 * @param   array   array to convert
+	 * @return  object
+	 */
+	public static function to_object(array $array, $class = 'stdClass')
+	{
+		$object = new $class;
+
+		foreach ($array as $key => $value)
+		{
+			if (is_array($value))
+			{
+				// Convert the array to an object
+				$value = arr::to_object($value, $class);
+			}
+
+			// Add the value to the object
+			$object->{$key} = $value;
+		}
+
+		return $object;
+	}
+
+	/**
+	 * Returns specific key/column from an array of objects.
+	 *
+	 * @param string|integer $key The key or column number to pluck from each object.
+	 * @param array $array        The array of objects to pluck from.
+	 * @return array
+	 */
+	public static function pluck($key, $array)
+	{
+		$result = array();
+		foreach ($array as $i => $object)
+		{
+			$result[$i] = isset($object[$key]) ? $object[$key] : NULL;
+		}
+		return $result;
+	}
+} // End arr
diff --git a/system/helpers/cookie.php b/system/helpers/cookie.php
new file mode 100644
index 0000000..3680ae3
--- /dev/null
+++ b/system/helpers/cookie.php
@@ -0,0 +1,149 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Cookie helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class cookie_Core {
+
+	/**
+	 * Sets a cookie with the given parameters.
+	 *
+	 * @param   string   cookie name or array of config options
+	 * @param   string   cookie value
+	 * @param   integer  number of seconds before the cookie expires
+	 * @param   string   URL path to allow
+	 * @param   string   URL domain to allow
+	 * @param   boolean  HTTPS only
+	 * @param   boolean  HTTP only (requires PHP 5.2 or higher)
+	 * @return  boolean
+	 */
+	public static function set($name, $value = NULL, $expire = NULL, $path = NULL, $domain = NULL, $secure = NULL, $httponly = NULL)
+	{
+		if (headers_sent())
+			return FALSE;
+
+		// If the name param is an array, we import it
+		is_array($name) and extract($name, EXTR_OVERWRITE);
+
+		// Fetch default options
+		$config = Kohana::config('cookie');
+
+		foreach (array('value', 'expire', 'domain', 'path', 'secure', 'httponly') as $item)
+		{
+			if ($$item === NULL AND isset($config[$item]))
+			{
+				$$item = $config[$item];
+			}
+		}
+
+		if ($expire !== 0)
+		{
+			 // The expiration is expected to be a UNIX timestamp
+			$expire += time();
+		}
+
+		$value = cookie::salt($name, $value).'~'.$value;
+
+		return setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
+	}
+
+	/**
+	 * Fetch a cookie value, using the Input library.
+	 *
+	 * @param   string   cookie name
+	 * @param   mixed    default value
+	 * @param   boolean  use XSS cleaning on the value
+	 * @return  string
+	 */
+	public static function get($name = NULL, $default = NULL, $xss_clean = FALSE)
+	{
+		// Return an array of all the cookies if we don't have a name
+		if ($name === NULL)
+		{
+			$cookies = array();
+
+			foreach($_COOKIE AS $key => $value)
+			{
+				$cookies[$key] = cookie::get($key, $default, $xss_clean);
+			}
+			return $cookies;
+		}
+
+		if ( ! isset($_COOKIE[$name]))
+		{
+			return $default;
+		}
+
+		// Get the cookie value
+		$cookie = $_COOKIE[$name];
+
+		// Find the position of the split between salt and contents
+		$split = strlen(cookie::salt($name, NULL));
+
+		if (isset($cookie[$split]) AND $cookie[$split] === '~')
+		{
+			 // Separate the salt and the value
+			list ($hash, $value) = explode('~', $cookie, 2);
+
+			if (cookie::salt($name, $value) === $hash)
+			{
+				if ($xss_clean === TRUE AND Kohana::config('core.global_xss_filtering') === FALSE)
+				{
+					return Input::instance()->xss_clean($value);
+				}
+				// Cookie signature is valid
+				return $value;
+			}
+
+			 // The cookie signature is invalid, delete it
+			cookie::delete($name);
+		}
+
+		return $default;
+	}
+
+	/**
+	 * Nullify and unset a cookie.
+	 *
+	 * @param   string   cookie name
+	 * @param   string   URL path
+	 * @param   string   URL domain
+	 * @return  boolean
+	 */
+	public static function delete($name, $path = NULL, $domain = NULL)
+	{
+		// Delete the cookie from globals
+		unset($_COOKIE[$name]);
+
+		// Sets the cookie value to an empty string, and the expiration to 24 hours ago
+		return cookie::set($name, '', -86400, $path, $domain, FALSE, FALSE);
+	}
+
+	/**
+	 * Generates a salt string for a cookie based on the name and value.
+	 *
+	 * @param	string $name name of cookie
+	 * @param	string $value value of cookie
+	 * @return	string sha1 hash
+	 */
+	public static function salt($name, $value)
+	{
+		// Determine the user agent
+		$agent = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USER_AGENT']) : 'unknown';
+
+		// Cookie salt.
+		$salt = Kohana::config('cookie.salt');
+
+		return sha1($agent.$name.$value.$salt);
+	}
+
+	final private function __construct()
+ 	{
+		// Static class.
+	}
+
+} // End cookie
\ No newline at end of file
diff --git a/system/helpers/date.php b/system/helpers/date.php
new file mode 100644
index 0000000..0b29d28
--- /dev/null
+++ b/system/helpers/date.php
@@ -0,0 +1,395 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Date helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class date_Core {
+
+	/**
+	 * Converts a UNIX timestamp to DOS format.
+	 *
+	 * @param   integer  UNIX timestamp
+	 * @return  integer
+	 */
+	public static function unix2dos($timestamp = FALSE)
+	{
+		$timestamp = ($timestamp === FALSE) ? getdate() : getdate($timestamp);
+
+		if ($timestamp['year'] < 1980)
+		{
+			return (1 << 21 | 1 << 16);
+		}
+
+		$timestamp['year'] -= 1980;
+
+		// What voodoo is this? I have no idea... Geert can explain it though,
+		// and that's good enough for me.
+		return ($timestamp['year']    << 25 | $timestamp['mon']     << 21 |
+		        $timestamp['mday']    << 16 | $timestamp['hours']   << 11 |
+		        $timestamp['minutes'] << 5  | $timestamp['seconds'] >> 1);
+	}
+
+	/**
+	 * Converts a DOS timestamp to UNIX format.
+	 *
+	 * @param   integer  DOS timestamp
+	 * @return  integer
+	 */
+	public static function dos2unix($timestamp = FALSE)
+	{
+		$sec  = 2 * ($timestamp & 0x1f);
+		$min  = ($timestamp >>  5) & 0x3f;
+		$hrs  = ($timestamp >> 11) & 0x1f;
+		$day  = ($timestamp >> 16) & 0x1f;
+		$mon  = ($timestamp >> 21) & 0x0f;
+		$year = ($timestamp >> 25) & 0x7f;
+
+		return mktime($hrs, $min, $sec, $mon, $day, $year + 1980);
+	}
+
+	/**
+	 * Returns the offset (in seconds) between two time zones.
+	 * @see     http://php.net/timezones
+	 *
+	 * @param   string          timezone to find the offset of
+	 * @param   string|boolean  timezone used as the baseline
+	 * @param   string          time at which to calculate
+	 * @return  integer
+	 */
+	public static function offset($remote, $local = TRUE, $when = 'now')
+	{
+		if ($local === TRUE)
+		{
+			$local = date_default_timezone_get();
+		}
+
+		// Create timezone objects
+		$remote = new DateTimeZone($remote);
+		$local  = new DateTimeZone($local);
+
+		// Create date objects from timezones
+		$time_there = new DateTime($when, $remote);
+		$time_here  = new DateTime($when, $local);
+
+		// Find the offset
+		return $remote->getOffset($time_there) - $local->getOffset($time_here);
+	}
+
+	/**
+	 * Number of seconds in a minute, incrementing by a step.
+	 *
+	 * @param   integer  amount to increment each step by, 1 to 30
+	 * @param   integer  start value
+	 * @param   integer  end value
+	 * @return  array    A mirrored (foo => foo) array from 1-60.
+	 */
+	public static function seconds($step = 1, $start = 0, $end = 60)
+	{
+		// Always integer
+		$step = (int) $step;
+
+		$seconds = array();
+
+		for ($i = $start; $i < $end; $i += $step)
+		{
+			$seconds[$i] = ($i < 10) ? '0'.$i : $i;
+		}
+
+		return $seconds;
+	}
+
+	/**
+	 * Number of minutes in an hour, incrementing by a step.
+	 *
+	 * @param   integer  amount to increment each step by, 1 to 30
+	 * @return  array    A mirrored (foo => foo) array from 1-60.
+	 */
+	public static function minutes($step = 5)
+	{
+		// Because there are the same number of minutes as seconds in this set,
+		// we choose to re-use seconds(), rather than creating an entirely new
+		// function. Shhhh, it's cheating! ;) There are several more of these
+		// in the following methods.
+		return date::seconds($step);
+	}
+
+	/**
+	 * Number of hours in a day.
+	 *
+	 * @param   integer  amount to increment each step by
+	 * @param   boolean  use 24-hour time
+	 * @param   integer  the hour to start at
+	 * @return  array    A mirrored (foo => foo) array from start-12 or start-23.
+	 */
+	public static function hours($step = 1, $long = FALSE, $start = NULL)
+	{
+		// Default values
+		$step = (int) $step;
+		$long = (bool) $long;
+		$hours = array();
+
+		// Set the default start if none was specified.
+		if ($start === NULL)
+		{
+			$start = ($long === FALSE) ? 1 : 0;
+		}
+
+		$hours = array();
+
+		// 24-hour time has 24 hours, instead of 12
+		$size = ($long === TRUE) ? 23 : 12;
+
+		for ($i = $start; $i <= $size; $i += $step)
+		{
+			$hours[$i] = $i;
+		}
+
+		return $hours;
+	}
+
+	/**
+	 * Returns AM or PM, based on a given hour.
+	 *
+	 * @param   integer  number of the hour
+	 * @return  string
+	 */
+	public static function ampm($hour)
+	{
+		// Always integer
+		$hour = (int) $hour;
+
+		return ($hour > 11) ? 'PM' : 'AM';
+	}
+
+	/**
+	 * Adjusts a non-24-hour number into a 24-hour number.
+	 *
+	 * @param   integer  hour to adjust
+	 * @param   string   AM or PM
+	 * @return  string
+	 */
+	public static function adjust($hour, $ampm)
+	{
+		$hour = (int) $hour;
+		$ampm = strtolower($ampm);
+
+		switch ($ampm)
+		{
+			case 'am':
+				if ($hour == 12)
+					$hour = 0;
+			break;
+			case 'pm':
+				if ($hour < 12)
+					$hour += 12;
+			break;
+		}
+
+		return sprintf('%02s', $hour);
+	}
+
+	/**
+	 * Number of days in month.
+	 *
+	 * @param   integer  number of month
+	 * @param   integer  number of year to check month, defaults to the current year
+	 * @return  array    A mirrored (foo => foo) array of the days.
+	 */
+	public static function days($month, $year = FALSE)
+	{
+		static $months;
+
+		// Always integers
+		$month = (int) $month;
+		$year  = (int) $year;
+
+		// Use the current year by default
+		$year  = ($year == FALSE) ? date('Y') : $year;
+
+		// We use caching for months, because time functions are used
+		if (empty($months[$year][$month]))
+		{
+			$months[$year][$month] = array();
+
+			// Use date to find the number of days in the given month
+			$total = date('t', mktime(1, 0, 0, $month, 1, $year)) + 1;
+
+			for ($i = 1; $i < $total; $i++)
+			{
+				$months[$year][$month][$i] = $i;
+			}
+		}
+
+		return $months[$year][$month];
+	}
+
+	/**
+	 * Number of months in a year
+	 *
+	 * @return  array  A mirrored (foo => foo) array from 1-12.
+	 */
+	public static function months()
+	{
+		return date::hours();
+	}
+
+	/**
+	 * Returns an array of years between a starting and ending year.
+	 * Uses the current year +/- 5 as the max/min.
+	 *
+	 * @param   integer  starting year
+	 * @param   integer  ending year
+	 * @return  array
+	 */
+	public static function years($start = FALSE, $end = FALSE)
+	{
+		// Default values
+		$start = ($start === FALSE) ? date('Y') - 5 : (int) $start;
+		$end   = ($end   === FALSE) ? date('Y') + 5 : (int) $end;
+
+		$years = array();
+
+		// Add one, so that "less than" works
+		$end += 1;
+
+		for ($i = $start; $i < $end; $i++)
+		{
+			$years[$i] = $i;
+		}
+
+		return $years;
+	}
+
+	/**
+	 * Returns time difference between two timestamps, in human readable format.
+	 *
+	 * @param   integer       timestamp
+	 * @param   integer       timestamp, defaults to the current time
+	 * @param   string        formatting string
+	 * @return  string|array
+	 */
+	public static function timespan($time1, $time2 = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
+	{
+		// Array with the output formats
+		$output = preg_split('/[^a-z]+/', strtolower((string) $output));
+
+		// Invalid output
+		if (empty($output))
+			return FALSE;
+
+		// Make the output values into keys
+		extract(array_flip($output), EXTR_SKIP);
+
+		// Default values
+		$time1  = max(0, (int) $time1);
+		$time2  = empty($time2) ? time() : max(0, (int) $time2);
+
+		// Calculate timespan (seconds)
+		$timespan = abs($time1 - $time2);
+
+		// All values found using Google Calculator.
+		// Years and months do not match the formula exactly, due to leap years.
+
+		// Years ago, 60 * 60 * 24 * 365
+		isset($years) and $timespan -= 31556926 * ($years = (int) floor($timespan / 31556926));
+
+		// Months ago, 60 * 60 * 24 * 30
+		isset($months) and $timespan -= 2629744 * ($months = (int) floor($timespan / 2629743.83));
+
+		// Weeks ago, 60 * 60 * 24 * 7
+		isset($weeks) and $timespan -= 604800 * ($weeks = (int) floor($timespan / 604800));
+
+		// Days ago, 60 * 60 * 24
+		isset($days) and $timespan -= 86400 * ($days = (int) floor($timespan / 86400));
+
+		// Hours ago, 60 * 60
+		isset($hours) and $timespan -= 3600 * ($hours = (int) floor($timespan / 3600));
+
+		// Minutes ago, 60
+		isset($minutes) and $timespan -= 60 * ($minutes = (int) floor($timespan / 60));
+
+		// Seconds ago, 1
+		isset($seconds) and $seconds = $timespan;
+
+		// Remove the variables that cannot be accessed
+		unset($timespan, $time1, $time2);
+
+		// Deny access to these variables
+		$deny = array_flip(array('deny', 'key', 'difference', 'output'));
+
+		// Return the difference
+		$difference = array();
+		foreach ($output as $key)
+		{
+			if (isset($$key) AND ! isset($deny[$key]))
+			{
+				// Add requested key to the output
+				$difference[$key] = $$key;
+			}
+		}
+
+		// Invalid output formats string
+		if (empty($difference))
+			return FALSE;
+
+		// If only one output format was asked, don't put it in an array
+		if (count($difference) === 1)
+			return current($difference);
+
+		// Return array
+		return $difference;
+	}
+
+	/**
+	 * Returns time difference between two timestamps, in the format:
+	 * N year, N months, N weeks, N days, N hours, N minutes, and N seconds ago
+	 *
+	 * @param   integer       timestamp
+	 * @param   integer       timestamp, defaults to the current time
+	 * @param   string        formatting string
+	 * @return  string
+	 */
+	public static function timespan_string($time1, $time2 = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
+	{
+		if ($difference = date::timespan($time1, $time2, $output) AND is_array($difference))
+		{
+			// Determine the key of the last item in the array
+			$last = end($difference);
+			$last = key($difference);
+
+			$span = array();
+			foreach ($difference as $name => $amount)
+			{
+				if ($amount === 0)
+				{
+					// Skip empty amounts
+					continue;
+				}
+
+				// Add the amount to the span
+				$span[] = ($name === $last ? ' and ' : ', ').$amount.' '.($amount === 1 ? inflector::singular($name) : $name);
+			}
+
+			// If the difference is less than 60 seconds, remove the preceding and.
+			if (count($span) === 1)
+			{
+				$span[0] = ltrim($span[0], 'and ');
+			}
+
+			// Replace difference by making the span into a string
+			$difference = trim(implode('', $span), ',');
+		}
+		elseif (is_int($difference))
+		{
+			// Single-value return
+			$difference = $difference.' '.($difference === 1 ? inflector::singular($output) : $output);
+		}
+
+		return $difference;
+	}
+
+} // End date
\ No newline at end of file
diff --git a/system/helpers/db.php b/system/helpers/db.php
new file mode 100644
index 0000000..941bb2e
--- /dev/null
+++ b/system/helpers/db.php
@@ -0,0 +1,47 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Database helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+ class db_Core {
+
+	public static function query($sql)
+	{
+		return new Database_Query($sql);
+	}
+
+	public static function build($database = 'default')
+	{
+		return new Database_Builder($database);
+	}
+
+	public static function select($columns = NULL)
+	{
+		return db::build()->select($columns);
+	}
+
+	public static function insert($table = NULL, $set = NULL)
+	{
+		return db::build()->insert($table, $set);
+	}
+
+	public static function update($table = NULL, $set = NULL, $where = NULL)
+	{
+		return db::build()->update($table, $set, $where);
+	}
+
+	public static function delete($table = NULL, $where = NULL)
+	{
+		return db::build()->delete($table, $where);
+	}
+
+	public static function expr($expression)
+	{
+		return new Database_Expression($expression);
+	}
+
+} // End db
diff --git a/system/helpers/download.php b/system/helpers/download.php
new file mode 100644
index 0000000..0bdb04d
--- /dev/null
+++ b/system/helpers/download.php
@@ -0,0 +1,135 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Download helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class download_Core {
+
+	/**
+	 * Send headers necessary to invoke a "Save As" dialog
+	 *
+	 * @link http://support.microsoft.com/kb/260519
+	 * @link http://greenbytes.de/tech/tc2231/
+	 *
+	 * @param   string  file name
+	 * @return  string  file name as it was sent
+	 */
+	public static function dialog($filename)
+	{
+		$filename = basename($filename);
+
+		header('Content-Disposition: attachment; filename="'.$filename.'"');
+
+		return $filename;
+	}
+
+	/**
+	 * Send the contents of a file or a data string with the proper MIME type and exit.
+	 *
+	 * @uses exit()
+	 * @uses Kohana::close_buffers()
+	 *
+	 * @param   string  a file path or file name
+	 * @param   string  optional data to send
+	 * @return  void
+	 */
+	public static function send($filename, $data = NULL)
+	{
+		if ($data === NULL)
+		{
+			$filepath = realpath($filename);
+
+			$filename = basename($filepath);
+			$filesize = filesize($filepath);
+		}
+		else
+		{
+			$filename = basename($filename);
+			$filesize = strlen($data);
+		}
+
+		// Retrieve MIME type by extension
+		$mime = Kohana::config('mimes.'.strtolower(substr(strrchr($filename, '.'), 1)));
+		$mime = empty($mime) ? 'application/octet-stream' : $mime[0];
+
+		// Close output buffers
+		Kohana::close_buffers(FALSE);
+
+		// Clear any output
+		Event::add('system.display', create_function('', 'Kohana::$output = "";'));
+
+		// Send headers
+		header("Content-Type: $mime");
+		header('Content-Length: '.sprintf('%d', $filesize));
+		header('Content-Transfer-Encoding: binary');
+
+		// Send data
+		if ($data === NULL)
+		{
+			$handle = fopen($filepath, 'rb');
+
+			fpassthru($handle);
+			fclose($handle);
+		}
+		else
+		{
+			echo $data;
+		}
+
+		exit;
+	}
+
+	/**
+	 * Force the download of a file by the user's browser by preventing any
+	 * caching. Contains a workaround for Internet Explorer.
+	 *
+	 * @link http://support.microsoft.com/kb/316431
+	 * @link http://support.microsoft.com/kb/812935
+	 *
+	 * @uses download::dialog()
+	 * @uses download::send()
+	 *
+	 * @param   string  a file path or file name
+	 * @param   mixed   data to be sent if the filename does not exist
+	 * @param   string  suggested filename to display in the download
+	 * @return  void
+	 */
+	public static function force($filename = NULL, $data = NULL, $nicename = NULL)
+	{
+		download::dialog(empty($nicename) ? $filename : $nicename);
+
+		// Prevent caching
+		header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
+
+		if (request::user_agent('browser') === 'Internet Explorer' AND request::user_agent('version') <= '6.0')
+		{
+			// HTTP 1.0
+			header('Pragma:');
+
+			// HTTP 1.1 with IE extensions
+			header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+		}
+		else
+		{
+			// HTTP 1.0
+			header('Pragma: no-cache');
+
+			// HTTP 1.1
+			header('Cache-Control: no-cache, max-age=0');
+		}
+
+		if (is_file($filename))
+		{
+			download::send($filename);
+		}
+		else
+		{
+			download::send($filename, $data);
+		}
+	}
+
+} // End download
diff --git a/system/helpers/expires.php b/system/helpers/expires.php
new file mode 100644
index 0000000..a3e01b8
--- /dev/null
+++ b/system/helpers/expires.php
@@ -0,0 +1,129 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Controls headers that effect client caching of pages
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class expires_Core {
+
+	/**
+	 * Sets the amount of time before content expires
+	 *
+	 * @param   integer Seconds before the content expires
+	 * @param   integer Last modified timestamp in seconds(optional)
+ 	 * @return  integer Timestamp when the content expires
+	 */
+	public static function set($seconds = 60, $last_modified=null)
+	{
+		$now = time();
+		$expires = $now + $seconds;
+ 		if (empty($last_modified))
+ 		{
+ 			$last_modified = $now;
+ 		}
+
+ 		 header('Last-Modified: '.gmdate('D, d M Y H:i:s T', $last_modified));
+
+		// HTTP 1.0
+		header('Expires: '.gmdate('D, d M Y H:i:s T', $expires));
+
+		// HTTP 1.1
+		header('Cache-Control: public,max-age='.$seconds);
+
+		return $expires;
+	}
+
+	/**
+	 * Parses the If-Modified-Since header
+	 *
+	 * @return  integer|boolean Timestamp or FALSE when header is lacking or malformed
+	 */
+	public static function get()
+	{
+		if ( ! empty($_SERVER['HTTP_IF_MODIFIED_SINCE']))
+		{
+			// Some versions of IE6 append "; length=####"
+			if (($strpos = strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], ';')) !== FALSE)
+			{
+				$mod_time = substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, $strpos);
+			}
+			else
+			{
+				$mod_time = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
+			}
+
+			return strtotime($mod_time);
+		}
+
+		return FALSE;
+	}
+
+	/**
+	 * Checks to see if content should be updated otherwise sends Not Modified status
+	 * and exits.
+	 *
+	 * @uses    exit()
+	 * @uses    expires::get()
+	 *
+	 * @param   integer         Maximum age of the content in seconds
+	 * @param   integer Last modified timestamp in seconds(optional)
+	 * @return  integer|boolean Timestamp of the If-Modified-Since header or FALSE when header is lacking or malformed
+	 */
+	public static function check($seconds = 60, $modified=null)
+	{
+		if ($last_modified = expires::get())
+		{
+			$now = time();
+
+ 			if (empty($last_modified))
+ 			{
+ 				$last_modified = $now;
+ 			}
+
+			if ($modified <= $last_modified)
+			{
+				// Content has not expired
+				header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
+				header('Last-Modified: '.gmdate('D, d M Y H:i:s T', $last_modified));
+
+				$expires = $now + $seconds;
+				// HTTP 1.0
+				header('Expires: '.gmdate('D, d M Y H:i:s T', $expires));
+
+				// HTTP 1.1
+				header('Cache-Control: public,max-age='.$seconds);
+
+				// Clear any output
+				Event::add('system.display', create_function('', 'Kohana::$output = "";'));
+
+				exit;
+			}
+		}
+
+		return $last_modified;
+	}
+
+	/**
+	 * Check if expiration headers are already set
+	 *
+	 * @return boolean
+	 */
+	public static function headers_set()
+	{
+		foreach (headers_list() as $header)
+		{
+			if (strncasecmp($header, 'Expires:', 8) === 0
+				OR strncasecmp($header, 'Cache-Control:', 14) === 0
+				OR strncasecmp($header, 'Last-Modified:', 14) === 0)
+			{
+				return TRUE;
+			}
+		}
+
+		return FALSE;
+	}
+
+} // End expires
diff --git a/system/helpers/feed.php b/system/helpers/feed.php
new file mode 100644
index 0000000..9831812
--- /dev/null
+++ b/system/helpers/feed.php
@@ -0,0 +1,120 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Feed helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class feed_Core {
+
+	/**
+	 * Parses a remote feed into an array.
+	 *
+	 * @param   string   remote feed URL
+	 * @param   integer  item limit to fetch
+	 * @return  array
+	 */
+	public static function parse($feed, $limit = 0)
+	{
+		// Check if SimpleXML is installed
+		if( ! function_exists('simplexml_load_file'))
+			throw new Kohana_User_Exception('Feed Error', 'SimpleXML must be installed!');
+
+		// Make limit an integer
+		$limit = (int) $limit;
+
+		// Disable error reporting while opening the feed
+		$ER = error_reporting(0);
+
+		// Allow loading by filename or raw XML string
+		$load = (is_file($feed) OR valid::url($feed)) ? 'simplexml_load_file' : 'simplexml_load_string';
+
+		// Load the feed
+		$feed = $load($feed, 'SimpleXMLElement', LIBXML_NOCDATA);
+
+		// Restore error reporting
+		error_reporting($ER);
+
+		// Feed could not be loaded
+		if ($feed === FALSE)
+			return array();
+
+		// Detect the feed type. RSS 1.0/2.0 and Atom 1.0 are supported.
+		$feed = isset($feed->channel) ? $feed->xpath('//item') : $feed->entry;
+
+		$i = 0;
+		$items = array();
+
+		foreach ($feed as $item)
+		{
+			if ($limit > 0 AND $i++ === $limit)
+				break;
+
+			$items[] = (array) $item;
+		}
+
+		return $items;
+	}
+
+	/**
+	 * Creates a feed from the given parameters.
+	 *
+	 * @param   array   feed information
+	 * @param   array   items to add to the feed
+	 * @param   string  define which format to use
+	 * @param   string  define which encoding to use
+	 * @return  string
+	 */
+	public static function create($info, $items, $format = 'rss2', $encoding = 'UTF-8')
+	{
+		$info += array('title' => 'Generated Feed', 'link' => '', 'generator' => 'KohanaPHP');
+
+		$feed = '<?xml version="1.0" encoding="'.$encoding.'"?><rss version="2.0"><channel></channel></rss>';
+		$feed = simplexml_load_string($feed);
+
+		foreach ($info as $name => $value)
+		{
+			if (($name === 'pubDate' OR $name === 'lastBuildDate') AND (is_int($value) OR ctype_digit($value)))
+			{
+				// Convert timestamps to RFC 822 formatted dates
+				$value = date(DATE_RFC822, $value);
+			}
+			elseif (($name === 'link' OR $name === 'docs') AND strpos($value, '://') === FALSE)
+			{
+				// Convert URIs to URLs
+				$value = url::site($value, 'http');
+			}
+
+			// Add the info to the channel
+			$feed->channel->addChild($name, $value);
+		}
+
+		foreach ($items as $item)
+		{
+			// Add the item to the channel
+			$row = $feed->channel->addChild('item');
+
+			foreach ($item as $name => $value)
+			{
+				if ($name === 'pubDate' AND (is_int($value) OR ctype_digit($value)))
+				{
+					// Convert timestamps to RFC 822 formatted dates
+					$value = date(DATE_RFC822, $value);
+				}
+				elseif (($name === 'link' OR $name === 'guid') AND strpos($value, '://') === FALSE)
+				{
+					// Convert URIs to URLs
+					$value = url::site($value, 'http');
+				}
+
+				// Add the info to the row
+				$row->addChild($name, $value);
+			}
+		}
+
+		return $feed->asXML();
+	}
+
+} // End feed
\ No newline at end of file
diff --git a/system/helpers/file.php b/system/helpers/file.php
new file mode 100644
index 0000000..48fbfc1
--- /dev/null
+++ b/system/helpers/file.php
@@ -0,0 +1,184 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * File helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class file_Core {
+
+	/**
+	 * Attempt to get the mime type from a file. This method is horribly
+	 * unreliable, due to PHP being horribly unreliable when it comes to
+	 * determining the mime-type of a file.
+	 *
+	 * @param   string   filename
+	 * @return  string   mime-type, if found
+	 * @return  boolean  FALSE, if not found
+	 */
+	public static function mime($filename)
+	{
+		// Make sure the file is readable
+		if ( ! (is_file($filename) AND is_readable($filename)))
+			return FALSE;
+
+		// Get the extension from the filename
+		$extension = strtolower(substr(strrchr($filename, '.'), 1));
+
+		if (preg_match('/^(?:jpe?g|png|[gt]if|bmp|swf)$/', $extension))
+		{
+			// Disable error reporting
+			$ER = error_reporting(0);
+
+			// Use getimagesize() to find the mime type on images
+			$mime = getimagesize($filename);
+
+			// Turn error reporting back on
+			error_reporting($ER);
+
+			// Return the mime type
+			if (isset($mime['mime']))
+				return $mime['mime'];
+		}
+
+		if (function_exists('finfo_open'))
+		{
+			// Use the fileinfo extension
+			$finfo = finfo_open(FILEINFO_MIME);
+			$mime  = finfo_file($finfo, $filename);
+			finfo_close($finfo);
+
+			// Return the mime type
+			return $mime;
+		}
+
+		if (ini_get('mime_magic.magicfile') AND function_exists('mime_content_type'))
+		{
+			// Return the mime type using mime_content_type
+			return mime_content_type($filename);
+		}
+
+		if ( ! KOHANA_IS_WIN)
+		{
+			// Attempt to locate use the file command, checking the return value
+			if ($command = trim(exec('which file', $output, $return)) AND $return === 0)
+			{
+				return trim(exec($command.' -bi '.escapeshellarg($filename)));
+			}
+		}
+
+		if ( ! empty($extension) AND is_array($mime = Kohana::config('mimes.'.$extension)))
+		{
+			// Return the mime-type guess, based on the extension
+			return $mime[0];
+		}
+
+		// Unable to find the mime-type
+		return FALSE;
+	}
+
+	/**
+	 * Split a file into pieces matching a specific size.
+	 *
+	 * @param   string   file to be split
+	 * @param   string   directory to output to, defaults to the same directory as the file
+	 * @param   integer  size, in MB, for each chunk to be
+	 * @return  integer  The number of pieces that were created.
+	 */
+	public static function split($filename, $output_dir = FALSE, $piece_size = 10)
+	{
+		// Find output dir
+		$output_dir = ($output_dir == FALSE) ? pathinfo(str_replace('\\', '/', realpath($filename)), PATHINFO_DIRNAME) : str_replace('\\', '/', realpath($output_dir));
+		$output_dir = rtrim($output_dir, '/').'/';
+
+		// Open files for writing
+		$input_file = fopen($filename, 'rb');
+
+		// Change the piece size to bytes
+		$piece_size = 1024 * 1024 * (int) $piece_size; // Size in bytes
+
+		// Set up reading variables
+		$read  = 0; // Number of bytes read
+		$piece = 1; // Current piece
+		$chunk = 1024 * 8; // Chunk size to read
+
+		// Split the file
+		while ( ! feof($input_file))
+		{
+			// Open a new piece
+			$piece_name = $filename.'.'.str_pad($piece, 3, '0', STR_PAD_LEFT);
+			$piece_open = @fopen($piece_name, 'wb+') or die('Could not write piece '.$piece_name);
+
+			// Fill the current piece
+			while ($read < $piece_size AND $data = fread($input_file, $chunk))
+			{
+				fwrite($piece_open, $data) or die('Could not write to open piece '.$piece_name);
+				$read += $chunk;
+			}
+
+			// Close the current piece
+			fclose($piece_open);
+
+			// Prepare to open a new piece
+			$read = 0;
+			$piece++;
+
+			// Make sure that piece is valid
+			($piece < 999) or die('Maximum of 999 pieces exceeded, try a larger piece size');
+		}
+
+		// Close input file
+		fclose($input_file);
+
+		// Returns the number of pieces that were created
+		return ($piece - 1);
+	}
+
+	/**
+	 * Join a split file into a whole file.
+	 *
+	 * @param   string   split filename, without .000 extension
+	 * @param   string   output filename, if different then an the filename
+	 * @return  integer  The number of pieces that were joined.
+	 */
+	public static function join($filename, $output = FALSE)
+	{
+		if ($output == FALSE)
+			$output = $filename;
+
+		// Set up reading variables
+		$piece = 1; // Current piece
+		$chunk = 1024 * 8; // Chunk size to read
+
+		// Open output file
+		$output_file = @fopen($output, 'wb+') or die('Could not open output file '.$output);
+
+		// Read each piece
+		while ($piece_open = @fopen(($piece_name = $filename.'.'.str_pad($piece, 3, '0', STR_PAD_LEFT)), 'rb'))
+		{
+			// Write the piece into the output file
+			while ( ! feof($piece_open))
+			{
+				fwrite($output_file, fread($piece_open, $chunk));
+			}
+
+			// Close the current piece
+			fclose($piece_open);
+
+			// Prepare for a new piece
+			$piece++;
+
+			// Make sure piece is valid
+			($piece < 999) or die('Maximum of 999 pieces exceeded');
+		}
+
+		// Close the output file
+		fclose($output_file);
+
+		// Return the number of pieces joined
+		return ($piece - 1);
+	}
+
+} // End file
\ No newline at end of file
diff --git a/system/helpers/form.php b/system/helpers/form.php
new file mode 100644
index 0000000..3d4f8ad
--- /dev/null
+++ b/system/helpers/form.php
@@ -0,0 +1,466 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Form helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class form_Core {
+
+	/**
+	 * Generates an opening HTML form tag.
+	 *
+	 * @param   string  form action attribute
+	 * @param   array   extra attributes
+	 * @param   array   hidden fields to be created immediately after the form tag
+	 * @param   string  non-default protocol, eg: https
+	 * @return  string
+	 */
+	public static function open($action = NULL, $attr = array(), $hidden = NULL, $protocol = NULL)
+	{
+		// Make sure that the method is always set
+		empty($attr['method']) and $attr['method'] = 'post';
+
+		if ($attr['method'] !== 'post' AND $attr['method'] !== 'get')
+		{
+			// If the method is invalid, use post
+			$attr['method'] = 'post';
+		}
+
+		if ($action === NULL)
+		{
+			// Use the current URL as the default action
+			$action = url::site(Router::$complete_uri, $protocol);
+		}
+		elseif (strpos($action, '://') === FALSE)
+		{
+			// Make the action URI into a URL
+			$action = url::site($action, $protocol);
+		}
+
+		// Set action
+		$attr['action'] = $action;
+
+		// Form opening tag
+		$form = '<form'.form::attributes($attr).'>'."\n";
+
+		// Add hidden fields immediate after opening tag
+		empty($hidden) or $form .= form::hidden($hidden);
+
+		return $form;
+	}
+
+	/**
+	 * Generates an opening HTML form tag that can be used for uploading files.
+	 *
+	 * @param   string  form action attribute
+	 * @param   array   extra attributes
+	 * @param   array   hidden fields to be created immediately after the form tag
+	 * @return  string
+	 */
+	public static function open_multipart($action = NULL, $attr = array(), $hidden = array())
+	{
+		// Set multi-part form type
+		$attr['enctype'] = 'multipart/form-data';
+
+		return form::open($action, $attr, $hidden);
+	}
+
+	/**
+	 * Creates a HTML form hidden input tag.
+	 *
+	 * @param   string|array  input name or an array of HTML attributes
+	 * @param   string        input value, when using a name
+	 * @param   string        a string to be attached to the end of the attributes
+	 * @return  string
+	 */
+	public static function hidden($data, $value = '', $extra = '')
+	{
+		if ( ! is_array($data))
+		{
+			$data = array('name' => $data);
+		}
+
+		$data['type'] = 'hidden';
+
+		return form::input($data, $value, $extra);
+	}
+
+	/**
+	 * Creates an HTML form input tag. Defaults to a text type.
+	 *
+	 * @param   string|array  input name or an array of HTML attributes
+	 * @param   string        input value, when using a name
+	 * @param   string        a string to be attached to the end of the attributes
+	 * @return  string
+	 */
+	public static function input($data, $value = '', $extra = '')
+	{
+		if ( ! is_array($data))
+		{
+			$data = array('name' => $data);
+		}
+
+		// Type and value are required attributes
+		$data += array
+		(
+			'type'  => 'text',
+			'value' => $value
+		);
+
+		return '<input'.form::attributes($data).' '.$extra.' />';
+	}
+
+	/**
+	 * Creates a HTML form password input tag.
+	 *
+	 * @param   string|array  input name or an array of HTML attributes
+	 * @param   string        input value, when using a name
+	 * @param   string        a string to be attached to the end of the attributes
+	 * @return  string
+	 */
+	public static function password($data, $value = '', $extra = '')
+	{
+		if ( ! is_array($data))
+		{
+			$data = array('name' => $data);
+		}
+
+		$data['type'] = 'password';
+
+		return form::input($data, $value, $extra);
+	}
+
+	/**
+	 * Creates an HTML form upload input tag.
+	 *
+	 * @param   string|array  input name or an array of HTML attributes
+	 * @param   string        input value, when using a name
+	 * @param   string        a string to be attached to the end of the attributes
+	 * @return  string
+	 */
+	public static function upload($data, $value = '', $extra = '')
+	{
+		if ( ! is_array($data))
+		{
+			$data = array('name' => $data);
+		}
+
+		$data['type'] = 'file';
+
+		return form::input($data, $value, $extra);
+	}
+
+	/**
+	 * Creates an HTML form textarea tag.
+	 *
+	 * @param   string|array  input name or an array of HTML attributes
+	 * @param   string        input value, when using a name
+	 * @param   string        a string to be attached to the end of the attributes
+	 * @param   boolean       encode existing entities
+	 * @return  string
+	 */
+	public static function textarea($data, $value = '', $extra = '', $double_encode = TRUE)
+	{
+		if ( ! is_array($data))
+		{
+			$data = array('name' => $data);
+		}
+
+		if ( ! isset($data['rows']))
+		{
+			$data['rows'] = '';
+		}
+
+		if ( ! isset($data['cols']))
+		{
+			$data['cols'] = '';
+		}
+
+		// Use the value from $data if possible, or use $value
+		$value = isset($data['value']) ? $data['value'] : $value;
+
+		// Value is not part of the attributes
+		unset($data['value']);
+
+		return '<textarea'.form::attributes($data, 'textarea').' '.$extra.'>'.htmlspecialchars($value, ENT_QUOTES, Kohana::CHARSET, $double_encode).'</textarea>';
+	}
+
+	/**
+	 * Creates an HTML form select tag, or "dropdown menu".
+	 *
+	 * @param   string|array  input name or an array of HTML attributes
+	 * @param   array         select options, when using a name
+	 * @param   string|array  option key(s) that should be selected by default
+	 * @param   string        a string to be attached to the end of the attributes
+	 * @return  string
+	 */
+	public static function dropdown($data, $options = NULL, $selected = NULL, $extra = '')
+	{
+		if ( ! is_array($data))
+		{
+			$data = array('name' => $data);
+		}
+		else
+		{
+			if (isset($data['options']))
+			{
+				// Use data options
+				$options = $data['options'];
+			}
+
+			if (isset($data['selected']))
+			{
+				// Use data selected
+				$selected = $data['selected'];
+			}
+		}
+
+		if (is_array($selected))
+		{
+			// Multi-select box
+			$data['multiple'] = 'multiple';
+		}
+		else
+		{
+			// Single selection (but converted to an array)
+			$selected = array($selected);
+		}
+
+		$input = '<select'.form::attributes($data, 'select').' '.$extra.'>'."\n";
+		foreach ((array) $options as $key => $val)
+		{
+			// Key should always be a string
+			$key = (string) $key;
+
+			if (is_array($val))
+			{
+				$input .= '<optgroup label="'.$key.'">'."\n";
+				foreach ($val as $inner_key => $inner_val)
+				{
+					// Inner key should always be a string
+					$inner_key = (string) $inner_key;
+
+					$sel = in_array($inner_key, $selected) ? ' selected="selected"' : '';
+					$input .= '<option value="'.$inner_key.'"'.$sel.'>'.htmlspecialchars($inner_val, ENT_QUOTES, Kohana::CHARSET, FALSE).'</option>'."\n";
+				}
+				$input .= '</optgroup>'."\n";
+			}
+			else
+			{
+				$sel = in_array($key, $selected) ? ' selected="selected"' : '';
+				$input .= '<option value="'.$key.'"'.$sel.'>'.htmlspecialchars($val, ENT_QUOTES, Kohana::CHARSET, FALSE).'</option>'."\n";
+			}
+		}
+		$input .= '</select>';
+
+		return $input;
+	}
+
+	/**
+	 * Creates an HTML form checkbox input tag.
+	 *
+	 * @param   string|array  input name or an array of HTML attributes
+	 * @param   string        input value, when using a name
+	 * @param   boolean       make the checkbox checked by default
+	 * @param   string        a string to be attached to the end of the attributes
+	 * @return  string
+	 */
+	public static function checkbox($data, $value = '', $checked = FALSE, $extra = '')
+	{
+		if ( ! is_array($data))
+		{
+			$data = array('name' => $data);
+		}
+
+		$data['type'] = 'checkbox';
+
+		if ($checked == TRUE OR (isset($data['checked']) AND $data['checked'] == TRUE))
+		{
+			$data['checked'] = 'checked';
+		}
+		else
+		{
+			unset($data['checked']);
+		}
+
+		return form::input($data, $value, $extra);
+	}
+
+	/**
+	 * Creates an HTML form radio input tag.
+	 *
+	 * @param   string|array  input name or an array of HTML attributes
+	 * @param   string        input value, when using a name
+	 * @param   boolean       make the radio selected by default
+	 * @param   string        a string to be attached to the end of the attributes
+	 * @return  string
+	 */
+	public static function radio($data = '', $value = '', $checked = FALSE, $extra = '')
+	{
+		if ( ! is_array($data))
+		{
+			$data = array('name' => $data);
+		}
+
+		$data['type'] = 'radio';
+
+		if ($checked == TRUE OR (isset($data['checked']) AND $data['checked'] == TRUE))
+		{
+			$data['checked'] = 'checked';
+		}
+		else
+		{
+			unset($data['checked']);
+		}
+
+		return form::input($data, $value, $extra);
+	}
+
+	/**
+	 * Creates an HTML form submit input tag.
+	 *
+	 * @param   string|array  input name or an array of HTML attributes
+	 * @param   string        input value, when using a name
+	 * @param   string        a string to be attached to the end of the attributes
+	 * @return  string
+	 */
+	public static function submit($data = '', $value = '', $extra = '')
+	{
+		if ( ! is_array($data))
+		{
+			$data = array('name' => $data);
+		}
+
+		if (empty($data['name']))
+		{
+			// Remove the name if it is empty
+			unset($data['name']);
+		}
+
+		$data['type'] = 'submit';
+
+		return form::input($data, $value, $extra);
+	}
+
+	/**
+	 * Creates an HTML form button input tag.
+	 *
+	 * @param   string|array  input name or an array of HTML attributes
+	 * @param   string        input value, when using a name
+	 * @param   string        a string to be attached to the end of the attributes
+	 * @return  string
+	 */
+	public static function button($data = '', $value = '', $extra = '')
+	{
+		if ( ! is_array($data))
+		{
+			$data = array('name' => $data);
+		}
+
+		if (empty($data['name']))
+		{
+			// Remove the name if it is empty
+			unset($data['name']);
+		}
+
+		if (isset($data['value']) AND empty($value))
+		{
+			$value = arr::remove('value', $data);
+		}
+
+		return '<button'.form::attributes($data, 'button').' '.$extra.'>'.$value.'</button>';
+	}
+
+	/**
+	 * Creates an HTML form label tag.
+	 *
+	 * @param   string|array  label "for" name or an array of HTML attributes
+	 * @param   string        label text or HTML
+	 * @param   string        a string to be attached to the end of the attributes
+	 * @return  string
+	 */
+	public static function label($data = '', $text = NULL, $extra = '')
+	{
+		if ( ! is_array($data))
+		{
+			if (is_string($data))
+			{
+				// Specify the input this label is for
+				$data = array('for' => $data);
+			}
+			else
+			{
+				// No input specified
+				$data = array();
+			}
+		}
+
+		if ($text === NULL AND isset($data['for']))
+		{
+			// Make the text the human-readable input name
+			$text = ucwords(inflector::humanize($data['for']));
+		}
+
+		return '<label'.form::attributes($data).' '.$extra.'>'.$text.'</label>';
+	}
+
+	/**
+	 * Sorts a key/value array of HTML attributes, putting form attributes first,
+	 * and returns an attribute string.
+	 *
+	 * @param   array   HTML attributes array
+	 * @return  string
+	 */
+	public static function attributes($attr, $type = NULL)
+	{
+		if (empty($attr))
+			return '';
+
+		$order = array
+		(
+			'action',
+			'method',
+			'type',
+			'id',
+			'name',
+			'value',
+			'src',
+			'size',
+			'maxlength',
+			'rows',
+			'cols',
+			'accept',
+			'tabindex',
+			'accesskey',
+			'align',
+			'alt',
+			'title',
+			'class',
+			'style',
+			'selected',
+			'checked',
+			'readonly',
+			'disabled'
+		);
+
+		$sorted = array();
+		foreach ($order as $key)
+		{
+			if (isset($attr[$key]))
+			{
+				// Move the attribute to the sorted array
+				$sorted[$key] = $attr[$key];
+
+				// Remove the attribute from unsorted array
+				unset($attr[$key]);
+			}
+		}
+
+		// Combine the sorted and unsorted attributes and create an HTML string
+		return html::attributes(array_merge($sorted, $attr));
+	}
+
+} // End form
diff --git a/system/helpers/format.php b/system/helpers/format.php
new file mode 100644
index 0000000..7494046
--- /dev/null
+++ b/system/helpers/format.php
@@ -0,0 +1,112 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Format helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class format_Core {
+
+	/**
+	 * Formats a number according to the current locale.
+	 *
+	 * @param   float
+	 * @param   int|boolean number of fractional digits or TRUE to use the locale default
+	 * @return  string
+	 */
+	public static function number($number, $decimals = 0)
+	{
+		$locale = localeconv();
+
+		if ($decimals === TRUE)
+			return number_format($number, $locale['frac_digits'], $locale['decimal_point'], $locale['thousands_sep']);
+
+		return number_format($number, $decimals, $locale['decimal_point'], $locale['thousands_sep']);
+	}
+
+	/**
+	 * Formats a phone number according to the specified format.
+	 *
+	 * @param   string  phone number
+	 * @param   string  format string
+	 * @return  string
+	 */
+	public static function phone($number, $format = '3-3-4')
+	{
+		// Get rid of all non-digit characters in number string
+		$number_clean = preg_replace('/\D+/', '', (string) $number);
+
+		// Array of digits we need for a valid format
+		$format_parts = preg_split('/[^1-9][^0-9]*/', $format, -1, PREG_SPLIT_NO_EMPTY);
+
+		// Number must match digit count of a valid format
+		if (strlen($number_clean) !== array_sum($format_parts))
+			return $number;
+
+		// Build regex
+		$regex = '(\d{'.implode('})(\d{', $format_parts).'})';
+
+		// Build replace string
+		for ($i = 1, $c = count($format_parts); $i <= $c; $i++)
+		{
+			$format = preg_replace('/(?<!\$)[1-9][0-9]*/', '\$'.$i, $format, 1);
+		}
+
+		// Hocus pocus!
+		return preg_replace('/^'.$regex.'$/', $format, $number_clean);
+	}
+
+	/**
+	 * Formats a URL to contain a protocol at the beginning.
+	 *
+	 * @param   string  possibly incomplete URL
+	 * @return  string
+	 */
+	public static function url($str = '')
+	{
+		// Clear protocol-only strings like "http://"
+		if ($str === '' OR substr($str, -3) === '://')
+			return '';
+
+		// If no protocol given, prepend "http://" by default
+		if (strpos($str, '://') === FALSE)
+			return 'http://'.$str;
+
+		// Return the original URL
+		return $str;
+	}
+
+	/**
+	 * Normalizes a hexadecimal HTML color value. All values will be converted
+	 * to lowercase, have a "#" prepended and contain six characters.
+	 *
+	 * @param   string  hexadecimal HTML color value
+	 * @return  string
+	 */
+	public static function color($str = '')
+	{
+		// Reject invalid values
+		if ( ! valid::color($str))
+			return '';
+
+		// Convert to lowercase
+		$str = strtolower($str);
+
+		// Prepend "#"
+		if ($str[0] !== '#')
+		{
+			$str = '#'.$str;
+		}
+
+		// Expand short notation
+		if (strlen($str) === 4)
+		{
+			$str = '#'.$str[1].$str[1].$str[2].$str[2].$str[3].$str[3];
+		}
+
+		return $str;
+	}
+
+} // End format
\ No newline at end of file
diff --git a/system/helpers/html.php b/system/helpers/html.php
new file mode 100644
index 0000000..c16031d
--- /dev/null
+++ b/system/helpers/html.php
@@ -0,0 +1,364 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * HTML helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class html_Core {
+
+	// Enable or disable automatic setting of target="_blank"
+	public static $windowed_urls = FALSE;
+
+	/**
+	 * Convert special characters to HTML entities
+	 *
+	 * @param   string   string to convert
+	 * @param   boolean  encode existing entities
+	 * @return  string
+	 */
+	public static function chars($str, $double_encode = TRUE)
+	{
+		// Return HTML entities using the Kohana charset
+		return htmlspecialchars($str, ENT_QUOTES, Kohana::CHARSET, $double_encode);
+	}
+
+	/**
+	 * Create HTML link anchors.
+	 *
+	 * @param   string  URL or URI string
+	 * @param   string  link text
+	 * @param   array   HTML anchor attributes
+	 * @param   string  non-default protocol, eg: https
+	 * @param   boolean option to escape the title that is output
+	 * @return  string
+	 */
+	public static function anchor($uri, $title = NULL, $attributes = NULL, $protocol = NULL, $escape_title = FALSE)
+	{
+		if ($uri === '')
+		{
+			$site_url = url::base(FALSE);
+		}
+		elseif (strpos($uri, '#') === 0)
+		{
+			// This is an id target link, not a URL
+			$site_url = $uri;
+		}
+		elseif (strpos($uri, '://') === FALSE)
+		{
+			$site_url = url::site($uri, $protocol);
+		}
+		else
+		{
+			if (html::$windowed_urls === TRUE AND empty($attributes['target']))
+			{
+				$attributes['target'] = '_blank';
+			}
+
+			$site_url = $uri;
+		}
+
+		return
+		// Parsed URL
+		'<a href="'.htmlspecialchars($site_url, ENT_QUOTES, Kohana::CHARSET, FALSE).'"'
+		// Attributes empty? Use an empty string
+		.(is_array($attributes) ? html::attributes($attributes) : '').'>'
+		// Title empty? Use the parsed URL
+		.($escape_title ? htmlspecialchars((($title === NULL) ? $site_url : $title), ENT_QUOTES, Kohana::CHARSET, FALSE) : (($title === NULL) ? $site_url : $title)).'</a>';
+	}
+
+	/**
+	 * Creates an HTML anchor to a file.
+	 *
+	 * @param   string  name of file to link to
+	 * @param   string  link text
+	 * @param   array   HTML anchor attributes
+	 * @param   string  non-default protocol, eg: ftp
+	 * @return  string
+	 */
+	public static function file_anchor($file, $title = NULL, $attributes = NULL, $protocol = NULL)
+	{
+		return
+		// Base URL + URI = full URL
+		'<a href="'.htmlspecialchars(url::base(FALSE, $protocol).$file, ENT_QUOTES, Kohana::CHARSET, FALSE).'"'
+		// Attributes empty? Use an empty string
+		.(is_array($attributes) ? html::attributes($attributes) : '').'>'
+		// Title empty? Use the filename part of the URI
+		.(($title === NULL) ? end(explode('/', $file)) : $title) .'</a>';
+	}
+
+	/**
+	 * Generates an obfuscated version of an email address.
+	 *
+	 * @param   string  email address
+	 * @return  string
+	 */
+	public static function email($email)
+	{
+		$safe = '';
+		foreach (str_split($email) as $letter)
+		{
+			switch (($letter === '@') ? rand(1, 2) : rand(1, 3))
+			{
+				// HTML entity code
+				case 1: $safe .= '&#'.ord($letter).';'; break;
+				// Hex character code
+				case 2: $safe .= '&#x'.dechex(ord($letter)).';'; break;
+				// Raw (no) encoding
+				case 3: $safe .= $letter;
+			}
+		}
+
+		return $safe;
+	}
+
+	/**
+	 * Creates an email anchor.
+	 *
+	 * @param   string  email address to send to
+	 * @param   string  link text
+	 * @param   array   HTML anchor attributes
+	 * @return  string
+	 */
+	public static function mailto($email, $title = NULL, $attributes = NULL)
+	{
+		if (empty($email))
+			return $title;
+
+		// Remove the subject or other parameters that do not need to be encoded
+		if (strpos($email, '?') !== FALSE)
+		{
+			// Extract the parameters from the email address
+			list ($email, $params) = explode('?', $email, 2);
+
+			// Make the params into a query string, replacing spaces
+			$params = '?'.str_replace(' ', '%20', $params);
+		}
+		else
+		{
+			// No parameters
+			$params = '';
+		}
+
+		// Obfuscate email address
+		$safe = html::email($email);
+
+		// Title defaults to the encoded email address
+		empty($title) and $title = $safe;
+
+		// Parse attributes
+		empty($attributes) or $attributes = html::attributes($attributes);
+
+		// Encoded start of the href="" is a static encoded version of 'mailto:'
+		return '<a href="&#109;&#097;&#105;&#108;&#116;&#111;&#058;'.$safe.$params.'"'.$attributes.'>'.$title.'</a>';
+	}
+
+	/**
+	 * Generate a "breadcrumb" list of anchors representing the URI.
+	 *
+	 * @param   array   segments to use as breadcrumbs, defaults to using Router::$segments
+	 * @return  string
+	 */
+	public static function breadcrumb($segments = NULL)
+	{
+		empty($segments) and $segments = Router::$segments;
+
+		$array = array();
+		while ($segment = array_pop($segments))
+		{
+			$array[] = html::anchor
+			(
+				// Complete URI for the URL
+				implode('/', $segments).'/'.$segment,
+				// Title for the current segment
+				ucwords(inflector::humanize($segment))
+			);
+		}
+
+		// Retrun the array of all the segments
+		return array_reverse($array);
+	}
+
+	/**
+	 * Creates a meta tag.
+	 *
+	 * @param   string|array   tag name, or an array of tags
+	 * @param   string         tag "content" value
+	 * @return  string
+	 */
+	public static function meta($tag, $value = NULL)
+	{
+		if (is_array($tag))
+		{
+			$tags = array();
+			foreach ($tag as $t => $v)
+			{
+				// Build each tag and add it to the array
+				$tags[] = html::meta($t, $v);
+			}
+
+			// Return all of the tags as a string
+			return implode("\n", $tags);
+		}
+
+		// Set the meta attribute value
+		$attr = in_array(strtolower($tag), Kohana::config('http.meta_equiv')) ? 'http-equiv' : 'name';
+
+		return '<meta '.$attr.'="'.$tag.'" content="'.$value.'" />';
+	}
+
+	/**
+	 * Creates a stylesheet link.
+	 *
+	 * @param   string|array  filename, or array of filenames to match to array of medias
+	 * @param   string|array  media type of stylesheet, or array to match filenames
+	 * @param   boolean       include the index_page in the link
+	 * @return  string
+	 */
+	public static function stylesheet($style, $media = FALSE, $index = FALSE)
+	{
+		return html::link($style, 'stylesheet', 'text/css', $media, $index);
+	}
+
+	/**
+	 * Creates a link tag.
+	 *
+	 * @param   string|array  filename
+	 * @param   string|array  relationship
+	 * @param   string|array  mimetype
+	 * @param   string|array  specifies on what device the document will be displayed
+	 * @param   boolean       include the index_page in the link
+	 * @return  string
+	 */
+	public static function link($href, $rel, $type, $media = FALSE, $index = FALSE)
+	{
+		$compiled = '';
+
+		if (is_array($href))
+		{
+			foreach ($href as $_href)
+			{
+				$_rel   = is_array($rel) ? array_shift($rel) : $rel;
+				$_type  = is_array($type) ? array_shift($type) : $type;
+				$_media = is_array($media) ? array_shift($media) : $media;
+
+				$compiled .= html::link($_href, $_rel, $_type, $_media, $index);
+			}
+		}
+		else
+		{
+			if (strpos($href, '://') === FALSE)
+			{
+				// Make the URL absolute
+				$href = url::base($index).$href;
+			}
+
+			$attr = array
+			(
+				'rel' => $rel,
+				'type' => $type,
+				'href' => $href,
+			);
+
+			if ( ! empty($media))
+			{
+				// Add the media type to the attributes
+				$attr['media'] = $media;
+			}
+
+			$compiled = '<link'.html::attributes($attr).' />';
+		}
+
+		return $compiled."\n";
+	}
+
+	/**
+	 * Creates a script link.
+	 *
+	 * @param   string|array  filename
+	 * @param   boolean       include the index_page in the link
+	 * @return  string
+	 */
+	public static function script($script, $index = FALSE)
+	{
+		$compiled = '';
+
+		if (is_array($script))
+		{
+			foreach ($script as $name)
+			{
+				$compiled .= html::script($name, $index);
+			}
+		}
+		else
+		{
+			if (strpos($script, '://') === FALSE)
+			{
+				// Add the suffix only when it's not already present
+				$script = url::base((bool) $index).$script;
+			}
+
+			$compiled = '<script type="text/javascript" src="'.$script.'"></script>';
+		}
+
+		return $compiled."\n";
+	}
+
+	/**
+	 * Creates a image link.
+	 *
+	 * @param   string        image source, or an array of attributes
+	 * @param   string|array  image alt attribute, or an array of attributes
+	 * @param   boolean       include the index_page in the link
+	 * @return  string
+	 */
+	public static function image($src = NULL, $alt = NULL, $index = FALSE)
+	{
+		// Create attribute list
+		$attributes = is_array($src) ? $src : array('src' => $src);
+
+		if (is_array($alt))
+		{
+			$attributes += $alt;
+		}
+		elseif ( ! empty($alt))
+		{
+			// Add alt to attributes
+			$attributes['alt'] = $alt;
+		}
+
+		if (strpos($attributes['src'], '://') === FALSE)
+		{
+			// Make the src attribute into an absolute URL
+			$attributes['src'] = url::base($index).$attributes['src'];
+		}
+
+		return '<img'.html::attributes($attributes).' />';
+	}
+
+	/**
+	 * Compiles an array of HTML attributes into an attribute string.
+	 *
+	 * @param   string|array  array of attributes
+	 * @return  string
+	 */
+	public static function attributes($attrs)
+	{
+		if (empty($attrs))
+			return '';
+
+		if (is_string($attrs))
+			return ' '.$attrs;
+
+		$compiled = '';
+		foreach ($attrs as $key => $val)
+		{
+			$compiled .= ' '.$key.'="'.htmlspecialchars($val, ENT_QUOTES, Kohana::CHARSET).'"';
+		}
+
+		return $compiled;
+	}
+
+} // End html
diff --git a/system/helpers/inflector.php b/system/helpers/inflector.php
new file mode 100644
index 0000000..e723707
--- /dev/null
+++ b/system/helpers/inflector.php
@@ -0,0 +1,252 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Inflector helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class inflector_Core {
+
+	// Cached inflections
+	protected static $cache = array();
+
+	// Uncountable and irregular words
+	protected static $uncountable;
+	protected static $irregular;
+
+	/**
+	 * Checks if a word is defined as uncountable.
+	 *
+	 * @param   string   word to check
+	 * @return  boolean
+	 */
+	public static function uncountable($str)
+	{
+		if (inflector::$uncountable === NULL)
+		{
+			// Cache uncountables
+			inflector::$uncountable = Kohana::config('inflector.uncountable');
+
+			// Make uncountables mirroed
+			inflector::$uncountable = array_combine(inflector::$uncountable, inflector::$uncountable);
+		}
+
+		return isset(inflector::$uncountable[strtolower($str)]);
+	}
+
+	/**
+	 * Makes a plural word singular.
+	 *
+	 * @param   string   word to singularize
+	 * @param   integer  number of things
+	 * @return  string
+	 */
+	public static function singular($str, $count = NULL) {
+		$parts = explode('_', $str);
+
+		$last = inflector::_singular(array_pop($parts), $count);
+
+		$pre = implode('_', $parts);
+		if (strlen($pre))
+			$pre .= '_';
+
+		return $pre.$last;
+	}
+
+
+	/**
+	 * Makes a plural word singular.
+	 *
+	 * @param   string   word to singularize
+	 * @param   integer  number of things
+	 * @return  string
+	 */
+	public static function _singular($str, $count = NULL)
+	{
+		// Remove garbage
+		$str = strtolower(trim($str));
+
+		if (is_string($count))
+		{
+			// Convert to integer when using a digit string
+			$count = (int) $count;
+		}
+
+		// Do nothing with a single count
+		if ($count === 0 OR $count > 1)
+			return $str;
+
+		// Cache key name
+		$key = 'singular_'.$str.$count;
+
+		if (isset(inflector::$cache[$key]))
+			return inflector::$cache[$key];
+
+		if (inflector::uncountable($str))
+			return inflector::$cache[$key] = $str;
+
+		if (empty(inflector::$irregular))
+		{
+			// Cache irregular words
+			inflector::$irregular = Kohana::config('inflector.irregular');
+		}
+
+		if ($irregular = array_search($str, inflector::$irregular))
+		{
+			$str = $irregular;
+		}
+		elseif (preg_match('/[sxz]es$/', $str) OR preg_match('/[^aeioudgkprt]hes$/', $str))
+		{
+			// Remove "es"
+			$str = substr($str, 0, -2);
+		}
+		elseif (preg_match('/[^aeiou]ies$/', $str))
+		{
+			$str = substr($str, 0, -3).'y';
+		}
+		elseif (substr($str, -1) === 's' AND substr($str, -2) !== 'ss')
+		{
+			$str = substr($str, 0, -1);
+		}
+
+		return inflector::$cache[$key] = $str;
+	}
+
+	/**
+	 * Makes a singular word plural.
+	 *
+	 * @param   string  word to pluralize
+	 * @return  string
+	 */
+	public static function plural($str, $count = NULL)
+	{
+		if ( ! $str)
+			return $str;
+
+		$parts = explode('_', $str);
+
+		$last = inflector::_plural(array_pop($parts), $count);
+
+		$pre = implode('_', $parts);
+		if (strlen($pre))
+			$pre .= '_';
+
+		return $pre.$last;
+	}
+
+
+	/**
+	 * Makes a singular word plural.
+	 *
+	 * @param   string  word to pluralize
+	 * @return  string
+	 */
+	public static function _plural($str, $count = NULL)
+	{
+		// Remove garbage
+		$str = strtolower(trim($str));
+
+		if (is_string($count))
+		{
+			// Convert to integer when using a digit string
+			$count = (int) $count;
+		}
+
+		// Do nothing with singular
+		if ($count === 1)
+			return $str;
+
+		// Cache key name
+		$key = 'plural_'.$str.$count;
+
+		if (isset(inflector::$cache[$key]))
+			return inflector::$cache[$key];
+
+		if (inflector::uncountable($str))
+			return inflector::$cache[$key] = $str;
+
+		if (empty(inflector::$irregular))
+		{
+			// Cache irregular words
+			inflector::$irregular = Kohana::config('inflector.irregular');
+		}
+
+		if (isset(inflector::$irregular[$str]))
+		{
+			$str = inflector::$irregular[$str];
+		}
+		elseif (preg_match('/[sxz]$/', $str) OR preg_match('/[^aeioudgkprt]h$/', $str))
+		{
+			$str .= 'es';
+		}
+		elseif (preg_match('/[^aeiou]y$/', $str))
+		{
+			// Change "y" to "ies"
+			$str = substr_replace($str, 'ies', -1);
+		}
+		else
+		{
+			$str .= 's';
+		}
+
+		// Set the cache and return
+		return inflector::$cache[$key] = $str;
+	}
+
+	/**
+	 * Makes a word possessive.
+	 *
+	 * @param   string  word to to make possessive
+	 * @return  string
+	 */
+	public static function possessive($string)
+	{
+		$length = strlen($string);
+
+		if (substr($string, $length - 1, $length) == 's')
+		{
+			return $string.'\'';
+		}
+
+		return $string.'\'s';
+	}
+
+	/**
+	 * Makes a phrase camel case.
+	 *
+	 * @param   string  phrase to camelize
+	 * @return  string
+	 */
+	public static function camelize($str)
+	{
+		$str = 'x'.strtolower(trim($str));
+		$str = ucwords(preg_replace('/[\s_]+/', ' ', $str));
+
+		return substr(str_replace(' ', '', $str), 1);
+	}
+
+	/**
+	 * Makes a phrase underscored instead of spaced.
+	 *
+	 * @param   string  phrase to underscore
+	 * @return  string
+	 */
+	public static function underscore($str)
+	{
+		return trim(preg_replace('/[\s_]+/', '_', $str), '_');
+	}
+
+	/**
+	 * Makes an underscored or dashed phrase human-readable.
+	 *
+	 * @param   string  phrase to make human-readable
+	 * @return  string
+	 */
+	public static function humanize($str)
+	{
+		return trim(preg_replace('/[_-\s]+/', ' ', $str));
+	}
+
+} // End inflector
\ No newline at end of file
diff --git a/system/helpers/num.php b/system/helpers/num.php
new file mode 100644
index 0000000..c9e9843
--- /dev/null
+++ b/system/helpers/num.php
@@ -0,0 +1,24 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Number helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class num_Core {
+
+	/**
+	 * Round a number to the nearest nth
+	 *
+	 * @param   integer  number to round
+	 * @param   integer  number to round to
+	 * @return  integer
+	 */
+	public static function round($number, $nearest = 5)
+	{
+		return round($number / $nearest) * $nearest;
+	}
+
+} // End num
\ No newline at end of file
diff --git a/system/helpers/remote.php b/system/helpers/remote.php
new file mode 100644
index 0000000..e6edb9c
--- /dev/null
+++ b/system/helpers/remote.php
@@ -0,0 +1,64 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Remote url/file helper.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class remote_Core {
+
+	public static function status($url)
+	{
+		if ( ! valid::url($url))
+			return FALSE;
+
+		// Get the hostname and path
+		$url = parse_url($url);
+
+		if (empty($url['path']))
+		{
+			// Request the root document
+			$url['path'] = '/';
+		}
+
+		// Open a remote connection
+		$remote = fsockopen($url['host'], 80, $errno, $errstr, 5);
+
+		if ( ! is_resource($remote))
+			return FALSE;
+
+		// Set CRLF
+		$CRLF = "\r\n";
+
+		// Send request
+		fwrite($remote, 'HEAD '.$url['path'].(isset($url['query']) ? '?'.$url['query'] : '').' HTTP/1.0'.$CRLF);
+		fwrite($remote, 'Host: '.$url['host'].$CRLF);
+		fwrite($remote, 'Connection: close'.$CRLF);
+		fwrite($remote, 'User-Agent: Kohana Framework (+http://kohanaphp.com/)'.$CRLF);
+
+		// Send one more CRLF to terminate the headers
+		fwrite($remote, $CRLF);
+
+		while ( ! feof($remote))
+		{
+			// Get the line
+			$line = trim(fgets($remote, 512));
+
+			if ($line !== '' AND preg_match('#^HTTP/1\.[01] (\d{3})#', $line, $matches))
+			{
+				// Response code found
+				$response = (int) $matches[1];
+
+				break;
+			}
+		}
+
+		// Close the connection
+		fclose($remote);
+
+		return isset($response) ? $response : FALSE;
+	}
+
+} // End remote
diff --git a/system/helpers/request.php b/system/helpers/request.php
new file mode 100644
index 0000000..c04a2fa
--- /dev/null
+++ b/system/helpers/request.php
@@ -0,0 +1,618 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Request helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class request_Core {
+
+	// Possible HTTP methods
+	protected static $http_methods = array('get', 'head', 'options', 'post', 'put', 'delete');
+
+	// Character sets from client's HTTP Accept-Charset request header
+	protected static $accept_charsets;
+
+	// Content codings from client's HTTP Accept-Encoding request header
+	protected static $accept_encodings;
+
+	// Language tags from client's HTTP Accept-Language request header
+	protected static $accept_languages;
+
+	// Content types from client's HTTP Accept request header
+	protected static $accept_types;
+
+	// The current user agent and its parsed attributes
+	protected static $user_agent;
+
+	/**
+	 * Returns the HTTP referrer, or the default if the referrer is not set.
+	 *
+	 * @param   mixed   default to return
+	 * @param   bool    Remove base URL
+	 * @return  string
+	 */
+	public static function referrer($default = FALSE, $remove_base = FALSE)
+	{
+		if ( ! empty($_SERVER['HTTP_REFERER']))
+		{
+			// Set referrer
+			$ref = $_SERVER['HTTP_REFERER'];
+
+			if ($remove_base === TRUE AND (strpos($ref, url::base(FALSE)) === 0))
+			{
+				// Remove the base URL from the referrer
+				$ref = substr($ref, strlen(url::base(FALSE)));
+			}
+		}
+
+		return isset($ref) ? $ref : $default;
+	}
+
+	/**
+	 * Returns the current request protocol, based on $_SERVER['https']. In CLI
+	 * mode, NULL will be returned.
+	 *
+	 * @return  string
+	 */
+	public static function protocol()
+	{
+		if (Kohana::$server_api === 'cli')
+		{
+			return NULL;
+		}
+		elseif ( ! empty($_SERVER['HTTPS']) AND $_SERVER['HTTPS'] === 'on')
+		{
+			return 'https';
+		}
+		else
+		{
+			return 'http';
+		}
+	}
+
+	/**
+	 * Tests if the current request is an AJAX request by checking the X-Requested-With HTTP
+	 * request header that most popular JS frameworks now set for AJAX calls.
+	 *
+	 * @return  boolean
+	 */
+	public static function is_ajax()
+	{
+		return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) AND strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
+	}
+
+	/**
+	 * Returns current request method.
+	 *
+	 * @throws  Kohana_Exception in case of an unknown request method
+	 * @return  string
+	 */
+	public static function method()
+	{
+		$method = strtolower($_SERVER['REQUEST_METHOD']);
+
+		if ( ! in_array($method, request::$http_methods))
+			throw new Kohana_Exception('Invalid request method :method:', array(':method:' => $method));
+
+		return $method;
+	}
+
+	/**
+	 * Retrieves current user agent information
+	 * keys:  browser, version, platform, mobile, robot
+	 *
+	 * @param   string  key
+	 * @return  mixed   NULL or the parsed value
+	 */
+	public static function user_agent($key = 'agent')
+	{
+		// Retrieve raw user agent without parsing
+		if ($key === 'agent')
+		{
+			if (request::$user_agent === NULL)
+				return request::$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? trim($_SERVER['HTTP_USER_AGENT']) : '';
+
+			if (is_array(request::$user_agent))
+				return request::$user_agent['agent'];
+
+			return request::$user_agent;
+		}
+
+		if ( ! is_array(request::$user_agent))
+		{
+			request::$user_agent = array();
+			request::$user_agent['agent'] = isset($_SERVER['HTTP_USER_AGENT']) ? trim($_SERVER['HTTP_USER_AGENT']) : '';
+
+			// Parse the user agent and extract basic information
+			foreach (Kohana::config('user_agents') as $type => $data)
+			{
+				foreach ($data as $fragment => $name)
+				{
+					if (stripos(request::$user_agent['agent'], $fragment) !== FALSE)
+					{
+						if ($type === 'browser' AND preg_match('|'.preg_quote($fragment).'[^0-9.]*+([0-9.][0-9.a-z]*)|i', request::$user_agent['agent'], $match))
+						{
+							// Set the browser version
+							request::$user_agent['version'] = $match[1];
+						}
+
+						// Set the agent name
+						request::$user_agent[$type] = $name;
+						break;
+					}
+				}
+			}
+		}
+
+		return isset(request::$user_agent[$key]) ? request::$user_agent[$key] : NULL;
+	}
+
+	/**
+	 * Returns boolean of whether client accepts content type.
+	 *
+	 * @param   string   content type
+	 * @param   boolean  set to TRUE to disable wildcard checking
+	 * @return  boolean
+	 */
+	public static function accepts($type = NULL, $explicit_check = FALSE)
+	{
+		request::parse_accept_content_header();
+
+		if ($type === NULL)
+			return request::$accept_types;
+
+		return (request::accepts_at_quality($type, $explicit_check) > 0);
+	}
+
+	/**
+	 * Returns boolean indicating if the client accepts a charset
+	 *
+	 * @param   string
+	 * @return  boolean
+	 */
+	public static function accepts_charset($charset = NULL)
+	{
+		request::parse_accept_charset_header();
+
+		if ($charset === NULL)
+			return request::$accept_charsets;
+
+		return (request::accepts_charset_at_quality($charset) > 0);
+	}
+
+	/**
+	 * Returns boolean indicating if the client accepts an encoding
+	 *
+	 * @param   string
+	 * @param   boolean set to TRUE to disable wildcard checking
+	 * @return  boolean
+	 */
+	public static function accepts_encoding($encoding = NULL, $explicit_check = FALSE)
+	{
+		request::parse_accept_encoding_header();
+
+		if ($encoding === NULL)
+			return request::$accept_encodings;
+
+		return (request::accepts_encoding_at_quality($encoding, $explicit_check) > 0);
+	}
+
+	/**
+	 * Returns boolean indicating if the client accepts a language tag
+	 *
+	 * @param   string  language tag
+	 * @param   boolean set to TRUE to disable prefix and wildcard checking
+	 * @return  boolean
+	 */
+	public static function accepts_language($tag = NULL, $explicit_check = FALSE)
+	{
+		request::parse_accept_language_header();
+
+		if ($tag === NULL)
+			return request::$accept_languages;
+
+		return (request::accepts_language_at_quality($tag, $explicit_check) > 0);
+	}
+
+	/**
+	 * Compare the q values for given array of content types and return the one with the highest value.
+	 * If items are found to have the same q value, the first one encountered in the given array wins.
+	 * If all items in the given array have a q value of 0, FALSE is returned.
+	 *
+	 * @param   array    content types
+	 * @param   boolean  set to TRUE to disable wildcard checking
+	 * @return  mixed    string mime type with highest q value, FALSE if none of the given types are accepted
+	 */
+	public static function preferred_accept($types, $explicit_check = FALSE)
+	{
+		$max_q = 0;
+		$preferred = FALSE;
+
+		foreach ($types as $type)
+		{
+			$q = request::accepts_at_quality($type, $explicit_check);
+
+			if ($q > $max_q)
+			{
+				$max_q = $q;
+				$preferred = $type;
+			}
+		}
+
+		return $preferred;
+	}
+
+	/**
+	 * Compare the q values for a given array of character sets and return the
+	 * one with the highest value. If items are found to have the same q value,
+	 * the first one encountered takes precedence. If all items in the given
+	 * array have a q value of 0, FALSE is returned.
+	 *
+	 * @param   array   character sets
+	 * @return  mixed
+	 */
+	public static function preferred_charset($charsets)
+	{
+		$max_q = 0;
+		$preferred = FALSE;
+
+		foreach ($charsets as $charset)
+		{
+			$q = request::accepts_charset_at_quality($charset);
+
+			if ($q > $max_q)
+			{
+				$max_q = $q;
+				$preferred = $charset;
+			}
+		}
+
+		return $preferred;
+	}
+
+	/**
+	 * Compare the q values for a given array of encodings and return the one with
+	 * the highest value. If items are found to have the same q value, the first
+	 * one encountered takes precedence. If all items in the given array have
+	 * a q value of 0, FALSE is returned.
+	 *
+	 * @param   array   encodings
+	 * @param   boolean set to TRUE to disable wildcard checking
+	 * @return  mixed
+	 */
+	public static function preferred_encoding($encodings, $explicit_check = FALSE)
+	{
+		$max_q = 0;
+		$preferred = FALSE;
+
+		foreach ($encodings as $encoding)
+		{
+			$q = request::accepts_encoding_at_quality($encoding, $explicit_check);
+
+			if ($q > $max_q)
+			{
+				$max_q = $q;
+				$preferred = $encoding;
+			}
+		}
+
+		return $preferred;
+	}
+
+	/**
+	 * Compare the q values for a given array of language tags and return the
+	 * one with the highest value. If items are found to have the same q value,
+	 * the first one encountered takes precedence. If all items in the given
+	 * array have a q value of 0, FALSE is returned.
+	 *
+	 * @param   array   language tags
+	 * @param   boolean set to TRUE to disable prefix and wildcard checking
+	 * @return  mixed
+	 */
+	public static function preferred_language($tags, $explicit_check = FALSE)
+	{
+		$max_q = 0;
+		$preferred = FALSE;
+
+		foreach ($tags as $tag)
+		{
+			$q = request::accepts_language_at_quality($tag, $explicit_check);
+
+			if ($q > $max_q)
+			{
+				$max_q = $q;
+				$preferred = $tag;
+			}
+		}
+
+		return $preferred;
+	}
+
+	/**
+	 * Returns quality factor at which the client accepts content type
+	 *
+	 * @param   string   content type (e.g. "image/jpg", "jpg")
+	 * @param   boolean  set to TRUE to disable wildcard checking
+	 * @return  integer|float
+	 */
+	public static function accepts_at_quality($type, $explicit_check = FALSE)
+	{
+		request::parse_accept_content_header();
+
+		// Normalize type
+		$type = strtolower($type);
+
+		// General content type (e.g. "jpg")
+		if (strpos($type, '/') === FALSE)
+		{
+			// Don't accept anything by default
+			$q = 0;
+
+			// Look up relevant mime types
+			foreach ((array) Kohana::config('mimes.'.$type) as $type)
+			{
+				$q2 = request::accepts_at_quality($type, $explicit_check);
+				$q = ($q2 > $q) ? $q2 : $q;
+			}
+
+			return $q;
+		}
+
+		// Content type with subtype given (e.g. "image/jpg")
+		$type = explode('/', $type, 2);
+
+		// Exact match
+		if (isset(request::$accept_types[$type[0]][$type[1]]))
+			return request::$accept_types[$type[0]][$type[1]];
+
+		if ($explicit_check === FALSE)
+		{
+			// Wildcard match
+			if (isset(request::$accept_types[$type[0]]['*']))
+				return request::$accept_types[$type[0]]['*'];
+
+			// Catch-all wildcard match
+			if (isset(request::$accept_types['*']['*']))
+				return request::$accept_types['*']['*'];
+		}
+
+		// Content type not accepted
+		return 0;
+	}
+
+	/**
+	 * Returns quality factor at which the client accepts a charset
+	 *
+	 * @param   string  charset (e.g., "ISO-8859-1", "utf-8")
+	 * @return  integer|float
+	 */
+	public static function accepts_charset_at_quality($charset)
+	{
+		request::parse_accept_charset_header();
+
+		// Normalize charset
+		$charset = strtolower($charset);
+
+		// Exact match
+		if (isset(request::$accept_charsets[$charset]))
+			return request::$accept_charsets[$charset];
+
+		if (isset(request::$accept_charsets['*']))
+			return request::$accept_charsets['*'];
+
+		if ($charset === 'iso-8859-1')
+			return 1;
+
+		return 0;
+	}
+
+	/**
+	 * Returns quality factor at which the client accepts an encoding
+	 *
+	 * @param   string  encoding (e.g., "gzip", "deflate")
+	 * @param   boolean set to TRUE to disable wildcard checking
+	 * @return  integer|float
+	 */
+	public static function accepts_encoding_at_quality($encoding, $explicit_check = FALSE)
+	{
+		request::parse_accept_encoding_header();
+
+		// Normalize encoding
+		$encoding = strtolower($encoding);
+
+		// Exact match
+		if (isset(request::$accept_encodings[$encoding]))
+			return request::$accept_encodings[$encoding];
+
+		if ($explicit_check === FALSE)
+		{
+			if (isset(request::$accept_encodings['*']))
+				return request::$accept_encodings['*'];
+
+			if ($encoding === 'identity')
+				return 1;
+		}
+
+		return 0;
+	}
+
+	/**
+	 * Returns quality factor at which the client accepts a language
+	 *
+	 * @param   string  tag (e.g., "en", "en-us", "fr-ca")
+	 * @param   boolean set to TRUE to disable prefix and wildcard checking
+	 * @return  integer|float
+	 */
+	public static function accepts_language_at_quality($tag, $explicit_check = FALSE)
+	{
+		request::parse_accept_language_header();
+
+		$tag = explode('-', strtolower($tag), 2);
+
+		if (isset(request::$accept_languages[$tag[0]]))
+		{
+			if (isset($tag[1]))
+			{
+				// Exact match
+				if (isset(request::$accept_languages[$tag[0]][$tag[1]]))
+					return request::$accept_languages[$tag[0]][$tag[1]];
+
+				// A prefix matches
+				if ($explicit_check === FALSE AND isset(request::$accept_languages[$tag[0]]['*']))
+					return request::$accept_languages[$tag[0]]['*'];
+			}
+			else
+			{
+				// No subtags
+				if (isset(request::$accept_languages[$tag[0]]['*']))
+					return request::$accept_languages[$tag[0]]['*'];
+			}
+		}
+
+		if ($explicit_check === FALSE AND isset(request::$accept_languages['*']))
+			return request::$accept_languages['*'];
+
+		return 0;
+	}
+
+	/**
+	 * Parses a HTTP Accept or Accept-* header for q values
+	 *
+	 * @param   string  header data
+	 * @return  array
+	 */
+	protected static function parse_accept_header($header)
+	{
+		$result = array();
+
+		// Remove linebreaks and parse the HTTP Accept header
+		foreach (explode(',', str_replace(array("\r", "\n"), '', strtolower($header))) as $entry)
+		{
+			// Explode each entry in content type and possible quality factor
+			$entry = explode(';', trim($entry), 2);
+
+			$q = (isset($entry[1]) AND preg_match('~\bq\s*+=\s*+([.0-9]+)~', $entry[1], $match)) ? (float) $match[1] : 1;
+
+			// Overwrite entries with a smaller q value
+			if ( ! isset($result[$entry[0]]) OR $q > $result[$entry[0]])
+			{
+				$result[$entry[0]] = $q;
+			}
+		}
+
+		return $result;
+	}
+
+	/**
+	 * Parses a client's HTTP Accept-Charset header
+	 */
+	protected static function parse_accept_charset_header()
+	{
+		// Run this function just once
+		if (request::$accept_charsets !== NULL)
+			return;
+
+		// No HTTP Accept-Charset header found
+		if (empty($_SERVER['HTTP_ACCEPT_CHARSET']))
+		{
+			// Accept everything
+			request::$accept_charsets['*'] = 1;
+		}
+		else
+		{
+			request::$accept_charsets = request::parse_accept_header($_SERVER['HTTP_ACCEPT_CHARSET']);
+		}
+	}
+
+	/**
+	 * Parses a client's HTTP Accept header
+	 */
+	protected static function parse_accept_content_header()
+	{
+		// Run this function just once
+		if (request::$accept_types !== NULL)
+			return;
+
+		// No HTTP Accept header found
+		if (empty($_SERVER['HTTP_ACCEPT']))
+		{
+			// Accept everything
+			request::$accept_types['*']['*'] = 1;
+		}
+		else
+		{
+			request::$accept_types = array();
+
+			foreach (request::parse_accept_header($_SERVER['HTTP_ACCEPT']) as $type => $q)
+			{
+				// Explode each content type (e.g. "text/html")
+				$type = explode('/', $type, 2);
+
+				// Skip invalid content types
+				if ( ! isset($type[1]))
+					continue;
+
+				request::$accept_types[$type[0]][$type[1]] = $q;
+			}
+		}
+	}
+
+	/**
+	 * Parses a client's HTTP Accept-Encoding header
+	 */
+	protected static function parse_accept_encoding_header()
+	{
+		// Run this function just once
+		if (request::$accept_encodings !== NULL)
+			return;
+
+		// No HTTP Accept-Encoding header found
+		if ( ! isset($_SERVER['HTTP_ACCEPT_ENCODING']))
+		{
+			// Accept everything
+			request::$accept_encodings['*'] = 1;
+		}
+		elseif ($_SERVER['HTTP_ACCEPT_ENCODING'] === '')
+		{
+			// Accept only identity
+			request::$accept_encodings['identity'] = 1;
+		}
+		else
+		{
+			request::$accept_encodings = request::parse_accept_header($_SERVER['HTTP_ACCEPT_ENCODING']);
+		}
+	}
+
+	/**
+	 * Parses a client's HTTP Accept-Language header
+	 */
+	protected static function parse_accept_language_header()
+	{
+		// Run this function just once
+		if (request::$accept_languages !== NULL)
+			return;
+
+		// No HTTP Accept-Language header found
+		if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE']))
+		{
+			// Accept everything
+			request::$accept_languages['*'] = 1;
+		}
+		else
+		{
+			request::$accept_languages = array();
+
+			foreach (request::parse_accept_header($_SERVER['HTTP_ACCEPT_LANGUAGE']) as $tag => $q)
+			{
+				// Explode each language (e.g. "en-us")
+				$tag = explode('-', $tag, 2);
+
+				request::$accept_languages[$tag[0]][isset($tag[1]) ? $tag[1] : '*'] = $q;
+			}
+		}
+	}
+
+} // End request
diff --git a/system/helpers/security.php b/system/helpers/security.php
new file mode 100644
index 0000000..7103bd1
--- /dev/null
+++ b/system/helpers/security.php
@@ -0,0 +1,35 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Security helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class security_Core {
+
+	/**
+	 * Sanitize a string with the xss_clean method.
+	 *
+	 * @param   string  string to sanitize
+	 * @param   string  xss_clean method to use ('htmlpurifier' or defaults to built-in method)
+	 * @return  string
+	 */
+	public static function xss_clean($str, $tool = NULL)
+	{
+		return Input::instance()->xss_clean($str, $tool);
+	}
+
+	/**
+	 * Remove image tags from a string.
+	 *
+	 * @param   string  string to sanitize
+	 * @return  string
+	 */
+	public static function strip_image_tags($str)
+	{
+		return preg_replace('#<img\s.*?(?:src\s*=\s*["\']?([^"\'<>\s]*)["\']?[^>]*)?>#is', '$1', $str);
+	}
+
+} // End security
\ No newline at end of file
diff --git a/system/helpers/text.php b/system/helpers/text.php
new file mode 100644
index 0000000..f7f040c
--- /dev/null
+++ b/system/helpers/text.php
@@ -0,0 +1,596 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Text helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class text_Core {
+
+	/**
+	 * Limits a phrase to a given number of words.
+	 *
+	 * @param   string   phrase to limit words of
+	 * @param   integer  number of words to limit to
+	 * @param   string   end character or entity
+	 * @return  string
+	 */
+	public static function limit_words($str, $limit = 100, $end_char = NULL)
+	{
+		$limit = (int) $limit;
+		$end_char = ($end_char === NULL) ? '…' : $end_char;
+
+		if (trim($str) === '')
+			return $str;
+
+		if ($limit <= 0)
+			return $end_char;
+
+		preg_match('/^\s*+(?:\S++\s*+){1,'.$limit.'}/u', $str, $matches);
+
+		// Only attach the end character if the matched string is shorter
+		// than the starting string.
+		return rtrim($matches[0]).(strlen($matches[0]) === strlen($str) ? '' : $end_char);
+	}
+
+	/**
+	 * Limits a phrase to a given number of characters.
+	 *
+	 * @param   string   phrase to limit characters of
+	 * @param   integer  number of characters to limit to
+	 * @param   string   end character or entity
+	 * @param   boolean  enable or disable the preservation of words while limiting
+	 * @return  string
+	 */
+	public static function limit_chars($str, $limit = 100, $end_char = NULL, $preserve_words = FALSE)
+	{
+		$end_char = ($end_char === NULL) ? '…' : $end_char;
+
+		$limit = (int) $limit;
+
+		if (trim($str) === '' OR mb_strlen($str) <= $limit)
+			return $str;
+
+		if ($limit <= 0)
+			return $end_char;
+
+		if ($preserve_words == FALSE)
+		{
+			return rtrim(mb_substr($str, 0, $limit)).$end_char;
+		}
+
+		preg_match('/^.{'.($limit - 1).'}\S*/us', $str, $matches);
+
+		return rtrim($matches[0]).(strlen($matches[0]) == strlen($str) ? '' : $end_char);
+	}
+
+	/**
+	 * Alternates between two or more strings.
+	 *
+	 * @param   string  strings to alternate between
+	 * @return  string
+	 */
+	public static function alternate()
+	{
+		static $i;
+
+		if (func_num_args() === 0)
+		{
+			$i = 0;
+			return '';
+		}
+
+		$args = func_get_args();
+		return $args[($i++ % count($args))];
+	}
+
+	/**
+	 * Generates a random string of a given type and length.
+	 *
+	 * @param   string   a type of pool, or a string of characters to use as the pool
+	 * @param   integer  length of string to return
+	 * @return  string
+	 *
+	 * @tutorial  alnum     alpha-numeric characters
+	 * @tutorial  alpha     alphabetical characters
+	 * @tutorial  hexdec    hexadecimal characters, 0-9 plus a-f
+	 * @tutorial  numeric   digit characters, 0-9
+	 * @tutorial  nozero    digit characters, 1-9
+	 * @tutorial  distinct  clearly distinct alpha-numeric characters
+	 */
+	public static function random($type = 'alnum', $length = 8)
+	{
+		$utf8 = FALSE;
+
+		switch ($type)
+		{
+			case 'alnum':
+				$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+			break;
+			case 'alpha':
+				$pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+			break;
+			case 'hexdec':
+				$pool = '0123456789abcdef';
+			break;
+			case 'numeric':
+				$pool = '0123456789';
+			break;
+			case 'nozero':
+				$pool = '123456789';
+			break;
+			case 'distinct':
+				$pool = '2345679ACDEFHJKLMNPRSTUVWXYZ';
+			break;
+			default:
+				$pool = (string) $type;
+				$utf8 = ! text::is_ascii($pool);
+			break;
+		}
+
+		// Split the pool into an array of characters
+		$pool = ($utf8 === TRUE) ? utf8::str_split($pool, 1) : str_split($pool, 1);
+
+		// Largest pool key
+		$max = count($pool) - 1;
+
+		$str = '';
+		for ($i = 0; $i < $length; $i++)
+		{
+			// Select a random character from the pool and add it to the string
+			$str .= $pool[mt_rand(0, $max)];
+		}
+
+		// Make sure alnum strings contain at least one letter and one digit
+		if ($type === 'alnum' AND $length > 1)
+		{
+			if (ctype_alpha($str))
+			{
+				// Add a random digit
+				$str[mt_rand(0, $length - 1)] = chr(mt_rand(48, 57));
+			}
+			elseif (ctype_digit($str))
+			{
+				// Add a random letter
+				$str[mt_rand(0, $length - 1)] = chr(mt_rand(65, 90));
+			}
+		}
+
+		return $str;
+	}
+
+	/**
+	 * Reduces multiple slashes in a string to single slashes.
+	 *
+	 * @param   string  string to reduce slashes of
+	 * @return  string
+	 */
+	public static function reduce_slashes($str)
+	{
+		return preg_replace('#(?<!:)//+#', '/', $str);
+	}
+
+	/**
+	 * Replaces the given words with a string.
+	 *
+	 * @param   string   phrase to replace words in
+	 * @param   array    words to replace
+	 * @param   string   replacement string
+	 * @param   boolean  replace words across word boundries (space, period, etc)
+	 * @return  string
+	 */
+	public static function censor($str, $badwords, $replacement = '#', $replace_partial_words = TRUE)
+	{
+		foreach ((array) $badwords as $key => $badword)
+		{
+			$badwords[$key] = str_replace('\*', '\S*?', preg_quote((string) $badword));
+		}
+
+		$regex = '('.implode('|', $badwords).')';
+
+		if ($replace_partial_words === FALSE)
+		{
+			// Just using \b isn't sufficient when we need to replace a badword that already contains word boundaries itself
+			$regex = '(?<=\b|\s|^)'.$regex.'(?=\b|\s|$)';
+		}
+
+		$regex = '!'.$regex.'!ui';
+
+		if (mb_strlen($replacement) == 1)
+		{
+			$regex .= 'e';
+			return preg_replace($regex, 'str_repeat($replacement, mb_strlen(\'$1\'))', $str);
+		}
+
+		return preg_replace($regex, $replacement, $str);
+	}
+
+	/**
+	 * Finds the text that is similar between a set of words.
+	 *
+	 * @param   array   words to find similar text of
+	 * @return  string
+	 */
+	public static function similar(array $words)
+	{
+		// First word is the word to match against
+		$word = current($words);
+
+		for ($i = 0, $max = strlen($word); $i < $max; ++$i)
+		{
+			foreach ($words as $w)
+			{
+				// Once a difference is found, break out of the loops
+				if ( ! isset($w[$i]) OR $w[$i] !== $word[$i])
+					break 2;
+			}
+		}
+
+		// Return the similar text
+		return substr($word, 0, $i);
+	}
+
+	/**
+	 * An alternative to the php levenshtein() function that work out the
+	 * distance between 2 words using the Damerau–Levenshtein algorithm.
+	 * Credit: http://forums.devnetwork.net/viewtopic.php?f=50&t=89094
+	 *
+	 * @see http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance
+	 * @param     string    first word
+	 * @param     string    second word
+	 * @return    int       distance between words
+	 */
+	public static function distance($string1, $string2)
+	{
+		$string1_length = strlen($string1);
+		$string2_length = strlen($string2);
+
+		// Here we start building the table of values
+		$matrix = array();
+
+		// String1 length + 1 = rows.
+		for ($i = 0; $i <= $string1_length; ++$i)
+		{
+			$matrix[$i][0] = $i;
+		}
+
+		// String2 length + 1 columns.
+		for ($j = 0; $j <= $string2_length; ++$j)
+		{
+			$matrix[0][$j] = $j;
+		}
+
+		for ($i = 1; $i <= $string1_length; ++$i)
+		{
+			for ($j = 1; $j <= $string2_length; ++$j)
+			{
+				$cost = substr($string1, $i - 1, 1) == substr($string2, $j - 1, 1) ? 0 : 1;
+
+				$matrix[$i][$j] = min(
+					$matrix[$i - 1][$j] + 1,		// deletion
+					$matrix[$i][$j - 1] + 1,		// insertion
+					$matrix[$i - 1][$j - 1] + $cost	// substitution
+				);
+
+				if ($i > 1 && $j > 1 &&	(substr($string1, $i - 1, 1) == substr($string2, $j - 2, 1))
+					&& (substr($string1, $i - 2, 1) == substr($string2, $j - 1, 1)))
+				{
+					$matrix[$i][$j] = min(
+						$matrix[$i][$j],
+						$matrix[$i - 2][$j - 2] + $cost	// transposition
+					);
+				}
+			}
+		}
+
+		return $matrix[$string1_length][$string2_length];
+	}
+
+	/**
+	 * Converts text anchors into links.
+	 *
+	 * @param   string   text to auto link
+	 * @return  string
+	 */
+	public static function auto_link_urls($text)
+	{
+
+		$regex = '~\\b'
+				.'((?:ht|f)tps?://)?' // protocol
+				.'(?:[-a-zA-Z0-9]{1,63}\.)+' // host name
+				.'(?:[0-9]{1,3}|aero|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)' // tlds
+				.'(?:/[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]*?)?' // path
+				.'(?:\?[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+?)?' // query
+				.'(?:#[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+?)?' // fragment
+				.'(?=[?.!,;:"]?(?:\s|$))~'; // punctuation and url end
+
+		$result = "";
+		$position = 0;
+
+		while (preg_match($regex, $text, $match, PREG_OFFSET_CAPTURE, $position))
+		{
+			list($url, $url_pos) = $match[0];
+
+			// Add the text before the url
+			$result  .= substr($text, $position, $url_pos - $position);
+
+			// Default to http://
+			$full_url = empty($match[1][0]) ? 'http://'.$url : $url;
+
+			// Add the hyperlink.
+			$result .= html::anchor($full_url, $url);
+
+			// New position to start parsing
+			$position = $url_pos + strlen($url);
+		}
+
+		return $result.substr($text, $position);
+	}
+
+	/**
+	 * Converts text email addresses into links.
+	 *
+	 * @param   string   text to auto link
+	 * @return  string
+	 */
+	public static function auto_link_emails($text)
+	{
+		// Finds all email addresses that are not part of an existing html mailto anchor
+		// Note: The "58;" negative lookbehind prevents matching of existing encoded html mailto anchors
+		//       The html entity for a colon (:) is &#58; or &#058; or &#0058; etc.
+		if (preg_match_all('~\b(?<!href="mailto:|">|58;)(?!\.)[-+_a-z0-9.]++(?<!\.)@(?![-.])[-a-z0-9.]+(?<!\.)\.[a-z]{2,6}\b~i', $text, $matches))
+		{
+			foreach ($matches[0] as $match)
+			{
+				// Replace each email with an encoded mailto
+				$text = str_replace($match, html::mailto($match), $text);
+			}
+		}
+
+		return $text;
+	}
+
+	/**
+	 * Automatically applies <p> and <br /> markup to text. Basically nl2br() on steroids.
+	 *
+	 * @param   string   subject
+	 * @param   boolean  convert single linebreaks to <br />
+	 * @return  string
+	 */
+	public static function auto_p($str, $br = TRUE)
+	{
+		// Trim whitespace
+		if (($str = trim($str)) === '')
+			return '';
+
+		// Standardize newlines
+		$str = str_replace(array("\r\n", "\r"), "\n", $str);
+
+		// Trim whitespace on each line
+		$str = preg_replace('~^[ \t]+~m', '', $str);
+		$str = preg_replace('~[ \t]+$~m', '', $str);
+
+		// The following regexes only need to be executed if the string contains html
+		if ($html_found = (strpos($str, '<') !== FALSE))
+		{
+			// Elements that should not be surrounded by p tags
+			$no_p = '(?:p|div|h[1-6r]|ul|ol|li|blockquote|d[dlt]|pre|t[dhr]|t(?:able|body|foot|head)|c(?:aption|olgroup)|form|s(?:elect|tyle)|a(?:ddress|rea)|ma(?:p|th))';
+
+			// Put at least two linebreaks before and after $no_p elements
+			$str = preg_replace('~^<'.$no_p.'[^>]*+>~im', "\n$0", $str);
+			$str = preg_replace('~</'.$no_p.'\s*+>$~im', "$0\n", $str);
+		}
+
+		// Do the <p> magic!
+		$str = '<p>'.trim($str).'</p>';
+		$str = preg_replace('~\n{2,}~', "</p>\n\n<p>", $str);
+
+		// The following regexes only need to be executed if the string contains html
+		if ($html_found !== FALSE)
+		{
+			// Remove p tags around $no_p elements
+			$str = preg_replace('~<p>(?=</?'.$no_p.'[^>]*+>)~i', '', $str);
+			$str = preg_replace('~(</?'.$no_p.'[^>]*+>)</p>~i', '$1', $str);
+		}
+
+		// Convert single linebreaks to <br />
+		if ($br === TRUE)
+		{
+			$str = preg_replace('~(?<!\n)\n(?!\n)~', "<br />\n", $str);
+		}
+
+		return $str;
+	}
+
+	/**
+	 * Returns human readable sizes.
+	 * @see  Based on original functions written by:
+	 * @see  Aidan Lister: http://aidanlister.com/repos/v/function.size_readable.php
+	 * @see  Quentin Zervaas: http://www.phpriot.com/d/code/strings/filesize-format/
+	 *
+	 * @param   integer  size in bytes
+	 * @param   string   a definitive unit
+	 * @param   string   the return string format
+	 * @param   boolean  whether to use SI prefixes or IEC
+	 * @return  string
+	 */
+	public static function bytes($bytes, $force_unit = NULL, $format = NULL, $si = TRUE)
+	{
+		// Format string
+		$format = ($format === NULL) ? '%01.2f %s' : (string) $format;
+
+		// IEC prefixes (binary)
+		if ($si == FALSE OR strpos($force_unit, 'i') !== FALSE)
+		{
+			$units = array(__('B'), __('KiB'), __('MiB'), __('GiB'), __('TiB'), __('PiB'));
+			$mod   = 1024;
+		}
+		// SI prefixes (decimal)
+		else
+		{
+			$units = array(__('B'), __('kB'), __('MB'), __('GB'), __('TB'), __('PB'));
+			$mod   = 1000;
+		}
+
+		// Determine unit to use
+		if (($power = array_search((string) $force_unit, $units)) === FALSE)
+		{
+			$power = ($bytes > 0) ? floor(log($bytes, $mod)) : 0;
+		}
+
+		return sprintf($format, $bytes / pow($mod, $power), $units[$power]);
+	}
+
+	/**
+	 * Prevents widow words by inserting a non-breaking space between the last two words.
+	 * @see  http://www.shauninman.com/archive/2006/08/22/widont_wordpress_plugin
+	 *
+	 * @param   string  string to remove widows from
+	 * @return  string
+	 */
+	public static function widont($str)
+	{
+		$str = rtrim($str);
+		$space = strrpos($str, ' ');
+
+		if ($space !== FALSE)
+		{
+			$str = substr($str, 0, $space).'&nbsp;'.substr($str, $space + 1);
+		}
+
+		return $str;
+	}
+
+	/**
+	 * Tests whether a string contains only 7bit ASCII bytes. This is used to
+	 * determine when to use native functions or UTF-8 functions.
+	 *
+	 * @see http://sourceforge.net/projects/phputf8/
+	 * @copyright  (c) 2007-2009 Kohana Team
+	 * @copyright  (c) 2005 Harry Fuecks
+	 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
+	 *
+	 * @param   string  string to check
+	 * @return  bool
+	 */
+	public static function is_ascii($str)
+	{
+		return is_string($str) AND ! preg_match('/[^\x00-\x7F]/S', $str);
+	}
+
+	/**
+	 * Strips out device control codes in the ASCII range.
+	 *
+	 * @see http://sourceforge.net/projects/phputf8/
+	 * @copyright  (c) 2007-2009 Kohana Team
+	 * @copyright  (c) 2005 Harry Fuecks
+	 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
+	 *
+	 * @param   string  string to clean
+	 * @return  string
+	 */
+	public static function strip_ascii_ctrl($str)
+	{
+		return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $str);
+	}
+
+	/**
+	 * Strips out all non-7bit ASCII bytes.
+	 *
+	 * @see http://sourceforge.net/projects/phputf8/
+	 * @copyright  (c) 2007-2009 Kohana Team
+	 * @copyright  (c) 2005 Harry Fuecks
+	 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
+	 *
+	 * @param   string  string to clean
+	 * @return  string
+	 */
+	public static function strip_non_ascii($str)
+	{
+		return preg_replace('/[^\x00-\x7F]+/S', '', $str);
+	}
+
+	/**
+	 * Replaces special/accented UTF-8 characters by ASCII-7 'equivalents'.
+	 *
+	 * @author  Andreas Gohr <andi@splitbrain.org>
+	 * @see http://sourceforge.net/projects/phputf8/
+	 * @copyright  (c) 2007-2009 Kohana Team
+	 * @copyright  (c) 2005 Harry Fuecks
+	 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
+	 *
+	 * @param   string   string to transliterate
+	 * @param   integer  -1 lowercase only, +1 uppercase only, 0 both cases
+	 * @return  string
+	 */
+	public static function transliterate_to_ascii($str, $case = 0)
+	{
+		static $UTF8_LOWER_ACCENTS = NULL;
+		static $UTF8_UPPER_ACCENTS = NULL;
+
+		if ($case <= 0)
+		{
+			if ($UTF8_LOWER_ACCENTS === NULL)
+			{
+				$UTF8_LOWER_ACCENTS = array(
+					'à' => 'a',  'ô' => 'o',  'ď' => 'd',  'ḟ' => 'f',  'ë' => 'e',  'š' => 's',  'ơ' => 'o',
+					'ß' => 'ss', 'ă' => 'a',  'ř' => 'r',  'ț' => 't',  'ň' => 'n',  'ā' => 'a',  'ķ' => 'k',
+					'ŝ' => 's',  'ỳ' => 'y',  'ņ' => 'n',  'ĺ' => 'l',  'ħ' => 'h',  'ṗ' => 'p',  'ó' => 'o',
+					'ú' => 'u',  'ě' => 'e',  'é' => 'e',  'ç' => 'c',  'ẁ' => 'w',  'ċ' => 'c',  'õ' => 'o',
+					'ṡ' => 's',  'ø' => 'o',  'ģ' => 'g',  'ŧ' => 't',  'ș' => 's',  'ė' => 'e',  'ĉ' => 'c',
+					'ś' => 's',  'î' => 'i',  'ű' => 'u',  'ć' => 'c',  'ę' => 'e',  'ŵ' => 'w',  'ṫ' => 't',
+					'ū' => 'u',  'č' => 'c',  'ö' => 'o',  'è' => 'e',  'ŷ' => 'y',  'ą' => 'a',  'ł' => 'l',
+					'ų' => 'u',  'ů' => 'u',  'ş' => 's',  'ğ' => 'g',  'ļ' => 'l',  'ƒ' => 'f',  'ž' => 'z',
+					'ẃ' => 'w',  'ḃ' => 'b',  'å' => 'a',  'ì' => 'i',  'ï' => 'i',  'ḋ' => 'd',  'ť' => 't',
+					'ŗ' => 'r',  'ä' => 'a',  'í' => 'i',  'ŕ' => 'r',  'ê' => 'e',  'ü' => 'u',  'ò' => 'o',
+					'ē' => 'e',  'ñ' => 'n',  'ń' => 'n',  'ĥ' => 'h',  'ĝ' => 'g',  'đ' => 'd',  'ĵ' => 'j',
+					'ÿ' => 'y',  'ũ' => 'u',  'ŭ' => 'u',  'ư' => 'u',  'ţ' => 't',  'ý' => 'y',  'ő' => 'o',
+					'â' => 'a',  'ľ' => 'l',  'ẅ' => 'w',  'ż' => 'z',  'ī' => 'i',  'ã' => 'a',  'ġ' => 'g',
+					'ṁ' => 'm',  'ō' => 'o',  'ĩ' => 'i',  'ù' => 'u',  'į' => 'i',  'ź' => 'z',  'á' => 'a',
+					'û' => 'u',  'þ' => 'th', 'ð' => 'dh', 'æ' => 'ae', 'µ' => 'u',  'ĕ' => 'e',  'ı' => 'i',
+				);
+			}
+
+			$str = str_replace(
+				array_keys($UTF8_LOWER_ACCENTS),
+				array_values($UTF8_LOWER_ACCENTS),
+				$str
+			);
+		}
+
+		if ($case >= 0)
+		{
+			if ($UTF8_UPPER_ACCENTS === NULL)
+			{
+				$UTF8_UPPER_ACCENTS = array(
+					'À' => 'A',  'Ô' => 'O',  'Ď' => 'D',  'Ḟ' => 'F',  'Ë' => 'E',  'Š' => 'S',  'Ơ' => 'O',
+					'Ă' => 'A',  'Ř' => 'R',  'Ț' => 'T',  'Ň' => 'N',  'Ā' => 'A',  'Ķ' => 'K',  'Ĕ' => 'E',
+					'Ŝ' => 'S',  'Ỳ' => 'Y',  'Ņ' => 'N',  'Ĺ' => 'L',  'Ħ' => 'H',  'Ṗ' => 'P',  'Ó' => 'O',
+					'Ú' => 'U',  'Ě' => 'E',  'É' => 'E',  'Ç' => 'C',  'Ẁ' => 'W',  'Ċ' => 'C',  'Õ' => 'O',
+					'Ṡ' => 'S',  'Ø' => 'O',  'Ģ' => 'G',  'Ŧ' => 'T',  'Ș' => 'S',  'Ė' => 'E',  'Ĉ' => 'C',
+					'Ś' => 'S',  'Î' => 'I',  'Ű' => 'U',  'Ć' => 'C',  'Ę' => 'E',  'Ŵ' => 'W',  'Ṫ' => 'T',
+					'Ū' => 'U',  'Č' => 'C',  'Ö' => 'O',  'È' => 'E',  'Ŷ' => 'Y',  'Ą' => 'A',  'Ł' => 'L',
+					'Ų' => 'U',  'Ů' => 'U',  'Ş' => 'S',  'Ğ' => 'G',  'Ļ' => 'L',  'Ƒ' => 'F',  'Ž' => 'Z',
+					'Ẃ' => 'W',  'Ḃ' => 'B',  'Å' => 'A',  'Ì' => 'I',  'Ï' => 'I',  'Ḋ' => 'D',  'Ť' => 'T',
+					'Ŗ' => 'R',  'Ä' => 'A',  'Í' => 'I',  'Ŕ' => 'R',  'Ê' => 'E',  'Ü' => 'U',  'Ò' => 'O',
+					'Ē' => 'E',  'Ñ' => 'N',  'Ń' => 'N',  'Ĥ' => 'H',  'Ĝ' => 'G',  'Đ' => 'D',  'Ĵ' => 'J',
+					'Ÿ' => 'Y',  'Ũ' => 'U',  'Ŭ' => 'U',  'Ư' => 'U',  'Ţ' => 'T',  'Ý' => 'Y',  'Ő' => 'O',
+					'Â' => 'A',  'Ľ' => 'L',  'Ẅ' => 'W',  'Ż' => 'Z',  'Ī' => 'I',  'Ã' => 'A',  'Ġ' => 'G',
+					'Ṁ' => 'M',  'Ō' => 'O',  'Ĩ' => 'I',  'Ù' => 'U',  'Į' => 'I',  'Ź' => 'Z',  'Á' => 'A',
+					'Û' => 'U',  'Þ' => 'Th', 'Ð' => 'Dh', 'Æ' => 'Ae', 'İ' => 'I',
+				);
+			}
+
+			$str = str_replace(
+				array_keys($UTF8_UPPER_ACCENTS),
+				array_values($UTF8_UPPER_ACCENTS),
+				$str
+			);
+		}
+
+		return $str;
+	}
+
+} // End text
\ No newline at end of file
diff --git a/system/helpers/upload.php b/system/helpers/upload.php
new file mode 100644
index 0000000..62de674
--- /dev/null
+++ b/system/helpers/upload.php
@@ -0,0 +1,157 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Upload helper class for working with the global $_FILES
+ * array and Validation library.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class upload_Core {
+
+	/**
+	 * Save an uploaded file to a new location.
+	 *
+	 * @param   mixed    name of $_FILE input or array of upload data
+	 * @param   string   new filename
+	 * @param   string   new directory
+	 * @param   integer  chmod mask
+	 * @return  string   full path to new file
+	 */
+	public static function save($file, $filename = NULL, $directory = NULL, $chmod = 0644)
+	{
+		// Load file data from FILES if not passed as array
+		$file = is_array($file) ? $file : $_FILES[$file];
+
+		if ($filename === NULL)
+		{
+			// Use the default filename, with a timestamp pre-pended
+			$filename = time().$file['name'];
+		}
+
+		if (Kohana::config('upload.remove_spaces') === TRUE)
+		{
+			// Remove spaces from the filename
+			$filename = preg_replace('/\s+/', '_', $filename);
+		}
+
+		if ($directory === NULL)
+		{
+			// Use the pre-configured upload directory
+			$directory = Kohana::config('upload.directory', TRUE);
+		}
+
+		// Make sure the directory ends with a slash
+		$directory = rtrim($directory, '/').'/';
+
+		if ( ! is_dir($directory) AND Kohana::config('upload.create_directories') === TRUE)
+		{
+			// Create the upload directory
+			mkdir($directory, 0777, TRUE);
+		}
+
+		if ( ! is_writable($directory))
+			throw new Kohana_Exception('The upload destination folder, :dir:, does not appear to be writable.', array(':dir:' => $directory));
+
+		if (is_uploaded_file($file['tmp_name']) AND move_uploaded_file($file['tmp_name'], $filename = $directory.$filename))
+		{
+			if ($chmod !== FALSE)
+			{
+				// Set permissions on filename
+				chmod($filename, $chmod);
+			}
+
+			// Return new file path
+			return $filename;
+		}
+
+		return FALSE;
+	}
+
+	/* Validation Rules */
+
+	/**
+	 * Tests if input data is valid file type, even if no upload is present.
+	 *
+	 * @param   array  $_FILES item
+	 * @return  bool
+	 */
+	public static function valid($file)
+	{
+		return (is_array($file)
+			AND isset($file['error'])
+			AND isset($file['name'])
+			AND isset($file['type'])
+			AND isset($file['tmp_name'])
+			AND isset($file['size']));
+	}
+
+	/**
+	 * Tests if input data has valid upload data.
+	 *
+	 * @param   array    $_FILES item
+	 * @return  bool
+	 */
+	public static function required(array $file)
+	{
+		return (isset($file['tmp_name'])
+			AND isset($file['error'])
+			AND is_uploaded_file($file['tmp_name'])
+			AND (int) $file['error'] === UPLOAD_ERR_OK);
+	}
+
+	/**
+	 * Validation rule to test if an uploaded file is allowed by extension.
+	 *
+	 * @param   array    $_FILES item
+	 * @param   array    allowed file extensions
+	 * @return  bool
+	 */
+	public static function type(array $file, array $allowed_types)
+	{
+		if ((int) $file['error'] !== UPLOAD_ERR_OK)
+			return TRUE;
+
+		// Get the default extension of the file
+		$extension = strtolower(substr(strrchr($file['name'], '.'), 1));
+
+		// Make sure there is an extension and that the extension is allowed
+		return ( ! empty($extension) AND in_array($extension, $allowed_types));
+	}
+
+	/**
+	 * Validation rule to test if an uploaded file is allowed by file size.
+	 * File sizes are defined as: SB, where S is the size (1, 15, 300, etc) and
+	 * B is the byte modifier: (B)ytes, (K)ilobytes, (M)egabytes, (G)igabytes.
+	 * Eg: to limit the size to 1MB or less, you would use "1M".
+	 *
+	 * @param   array    $_FILES item
+	 * @param   array    maximum file size
+	 * @return  bool
+	 */
+	public static function size(array $file, array $size)
+	{
+		if ((int) $file['error'] !== UPLOAD_ERR_OK)
+			return TRUE;
+
+		// Only one size is allowed
+		$size = strtoupper($size[0]);
+
+		if ( ! preg_match('/[0-9]++[BKMG]/', $size))
+			return FALSE;
+
+		// Make the size into a power of 1024
+		switch (substr($size, -1))
+		{
+			case 'G': $size = intval($size) * pow(1024, 3); break;
+			case 'M': $size = intval($size) * pow(1024, 2); break;
+			case 'K': $size = intval($size) * pow(1024, 1); break;
+			default:  $size = intval($size);                break;
+		}
+
+		// Test that the file is under or equal to the max size
+		return ($file['size'] <= $size);
+	}
+
+} // End upload
\ No newline at end of file
diff --git a/system/helpers/url.php b/system/helpers/url.php
new file mode 100644
index 0000000..02956fc
--- /dev/null
+++ b/system/helpers/url.php
@@ -0,0 +1,264 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * URL helper class.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class url_Core {
+
+	/**
+	 * Fetches the current URI.
+	 *
+	 * @param   boolean  include the query string
+	 * @param   boolean  include the suffix
+	 * @return  string
+	 */
+	public static function current($qs = FALSE, $suffix = FALSE)
+	{
+		$uri = ($qs === TRUE) ? Router::$complete_uri : Router::$current_uri;
+
+		return ($suffix === TRUE) ? $uri.Kohana::config('core.url_suffix') : $uri;
+	}
+
+	/**
+	 * Base URL, with or without the index page.
+	 *
+	 * If protocol (and core.site_protocol) and core.site_domain are both empty,
+	 * then
+	 *
+	 * @param   boolean  include the index page
+	 * @param   boolean  non-default protocol
+	 * @return  string
+	 */
+	public static function base($index = FALSE, $protocol = FALSE)
+	{
+		if ($protocol == FALSE)
+		{
+			// Use the default configured protocol
+			$protocol = Kohana::config('core.site_protocol');
+		}
+
+		// Load the site domain
+		$site_domain = (string) Kohana::config('core.site_domain', TRUE);
+
+		if ($protocol == FALSE)
+		{
+			if ($site_domain === '' OR $site_domain[0] === '/')
+			{
+				// Use the configured site domain
+				$base_url = $site_domain;
+			}
+			else
+			{
+				// Guess the protocol to provide full http://domain/path URL
+				$base_url = ((empty($_SERVER['HTTPS']) OR $_SERVER['HTTPS'] === 'off') ? 'http' : 'https').'://'.$site_domain;
+			}
+		}
+		else
+		{
+			if ($site_domain === '' OR $site_domain[0] === '/')
+			{
+				// Guess the server name if the domain starts with slash
+				$port = $_SERVER['SERVER_PORT'];
+				$port = ((($port == 80) && ($protocol == 'http')) || (($port == 443) && ($protocol == 'https')) || !$port) ? '' : ":$port";
+				$base_url = $protocol.'://'.($_SERVER['SERVER_NAME']?($_SERVER['SERVER_NAME'].$port):$_SERVER['HTTP_HOST']).$site_domain;
+			}
+			else
+			{
+				// Use the configured site domain
+				$base_url = $protocol.'://'.$site_domain;
+			}
+		}
+
+		if ($index === TRUE AND $index = Kohana::config('core.index_page'))
+		{
+			// Append the index page
+			$base_url = $base_url.$index;
+		}
+
+		// Force a slash on the end of the URL
+		return rtrim($base_url, '/').'/';
+	}
+
+	/**
+	 * Fetches an absolute site URL based on a URI segment.
+	 *
+	 * @param   string  site URI to convert
+	 * @param   string  non-default protocol
+	 * @return  string
+	 */
+	public static function site($uri = '', $protocol = FALSE)
+	{
+		if ($path = trim(parse_url($uri, PHP_URL_PATH), '/'))
+		{
+			// Add path suffix
+			$path .= Kohana::config('core.url_suffix');
+		}
+
+		if ($query = parse_url($uri, PHP_URL_QUERY))
+		{
+			// ?query=string
+			$query = '?'.$query;
+		}
+
+		if ($fragment = parse_url($uri, PHP_URL_FRAGMENT))
+		{
+			// #fragment
+			$fragment =  '#'.$fragment;
+		}
+
+		// Concat the URL
+		return url::base(TRUE, $protocol).$path.$query.$fragment;
+	}
+
+	/**
+	 * Return the URL to a file. Absolute filenames and relative filenames
+	 * are allowed.
+	 *
+	 * @param   string   filename
+	 * @param   boolean  include the index page
+	 * @return  string
+	 */
+	public static function file($file, $index = FALSE)
+	{
+		if (strpos($file, '://') === FALSE)
+		{
+			// Add the base URL to the filename
+			$file = url::base($index).$file;
+		}
+
+		return $file;
+	}
+
+	/**
+	 * Merges an array of arguments with the current URI and query string to
+	 * overload, instead of replace, the current query string.
+	 *
+	 * @param   array   associative array of arguments
+	 * @return  string
+	 */
+	public static function merge(array $arguments)
+	{
+		if ($_GET === $arguments)
+		{
+			$query = Router::$query_string;
+		}
+		elseif ($query = http_build_query(array_merge($_GET, $arguments)))
+		{
+			$query = '?'.$query;
+		}
+
+		// Return the current URI with the arguments merged into the query string
+		return Router::$current_uri.$query;
+	}
+
+	/**
+	 * Convert a phrase to a URL-safe title.
+	 *
+	 * @param   string  phrase to convert
+	 * @param   string  word separator (- or _)
+	 * @param   boolean  transliterate to ASCII
+	 * @return  string
+	 */
+	public static function title($title, $separator = '-', $ascii_only = FALSE)
+	{
+		$separator = ($separator === '-') ? '-' : '_';
+
+		if ($ascii_only === TRUE)
+		{
+			// Replace accented characters by their unaccented equivalents
+			$title = text::transliterate_to_ascii($title);
+
+			// Remove all characters that are not the separator, a-z, 0-9, or whitespace
+			$title = preg_replace('/[^'.$separator.'a-z0-9\s]+/', '', strtolower($title));
+		}
+		else
+		{
+			// Remove all characters that are not the separator, letters, numbers, or whitespace
+			$title = preg_replace('/[^'.$separator.'\pL\pN\s]+/u', '', mb_strtolower($title));
+		}
+
+		// Replace all separator characters and whitespace by a single separator
+		$title = preg_replace('/['.$separator.'\s]+/', $separator, $title);
+
+		// Trim separators from the beginning and end
+		return trim($title, $separator);
+	}
+
+	/**
+	 * Sends a page redirect header and runs the system.redirect Event.
+	 *
+	 * @param  mixed   string site URI or URL to redirect to, or array of strings if method is 300
+	 * @param  string  HTTP method of redirect
+	 * @return void
+	 */
+	public static function redirect($uri = '', $method = '302')
+	{
+		if (Event::has_run('system.send_headers'))
+		{
+			return FALSE;
+		}
+
+		$codes = array
+		(
+			'refresh' => 'Refresh',
+			'300' => 'Multiple Choices',
+			'301' => 'Moved Permanently',
+			'302' => 'Found',
+			'303' => 'See Other',
+			'304' => 'Not Modified',
+			'305' => 'Use Proxy',
+			'307' => 'Temporary Redirect'
+		);
+
+		// Validate the method and default to 302
+		$method = isset($codes[$method]) ? (string) $method : '302';
+
+		if ($method === '300')
+		{
+			$uri = (array) $uri;
+
+			$output = '<ul>';
+			foreach ($uri as $link)
+			{
+				$output .= '<li>'.html::anchor($link).'</li>';
+			}
+			$output .= '</ul>';
+
+			// The first URI will be used for the Location header
+			$uri = $uri[0];
+		}
+		else
+		{
+			$output = '<p>'.html::anchor($uri).'</p>';
+		}
+
+		// Run the redirect event
+		Event::run('system.redirect', $uri);
+
+		if (strpos($uri, '://') === FALSE)
+		{
+			// HTTP headers expect absolute URLs
+			$uri = url::site($uri, request::protocol());
+		}
+
+		if ($method === 'refresh')
+		{
+			header('Refresh: 0; url='.$uri);
+		}
+		else
+		{
+			header('HTTP/1.1 '.$method.' '.$codes[$method]);
+			header('Location: '.$uri);
+		}
+
+		// We are about to exit, so run the send_headers event
+		Event::run('system.send_headers');
+
+		exit('<h1>'.$method.' - '.$codes[$method].'</h1>'.$output);
+	}
+
+} // End url
\ No newline at end of file
diff --git a/system/helpers/utf8.php b/system/helpers/utf8.php
new file mode 100644
index 0000000..0123cfb
--- /dev/null
+++ b/system/helpers/utf8.php
@@ -0,0 +1,744 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * A port of phputf8 to a unified file/class.
+ *
+ * This file is licensed differently from the rest of Kohana. As a port of
+ * phputf8, which is LGPL software, this file is released under the LGPL.
+ *
+ * PCRE needs to be compiled with UTF-8 support (--enable-utf8).
+ * Support for Unicode properties is highly recommended (--enable-unicode-properties).
+ * @see http://php.net/manual/reference.pcre.pattern.modifiers.php
+ *
+ * string functions.
+ * @see http://php.net/mbstring
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @copyright  (c) 2005 Harry Fuecks
+ * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
+ */
+
+class utf8_Core {
+
+	/**
+	 * Replaces text within a portion of a UTF-8 string.
+	 * @see http://php.net/substr_replace
+	 *
+	 * @author  Harry Fuecks <hfuecks@gmail.com>
+	 *
+	 * @param   string   input string
+	 * @param   string   replacement string
+	 * @param   integer  offset
+	 * @return  string
+	 */
+	public static function substr_replace($str, $replacement, $offset, $length = NULL)
+	{
+		if (text::is_ascii($str))
+			return ($length === NULL) ? substr_replace($str, $replacement, $offset) : substr_replace($str, $replacement, $offset, $length);
+
+		$length = ($length === NULL) ? mb_strlen($str) : (int) $length;
+		preg_match_all('/./us', $str, $str_array);
+		preg_match_all('/./us', $replacement, $replacement_array);
+
+		array_splice($str_array[0], $offset, $length, $replacement_array[0]);
+		return implode('', $str_array[0]);
+	}
+
+	/**
+	 * Makes a UTF-8 string's first character uppercase.
+	 * @see http://php.net/ucfirst
+	 *
+	 * @author  Harry Fuecks <hfuecks@gmail.com>
+	 *
+	 * @param   string   mixed case string
+	 * @return  string
+	 */
+	public static function ucfirst($str)
+	{
+		if (text::is_ascii($str))
+			return ucfirst($str);
+
+		preg_match('/^(.?)(.*)$/us', $str, $matches);
+		return mb_strtoupper($matches[1]).$matches[2];
+	}
+
+	/**
+	 * Case-insensitive UTF-8 string comparison.
+	 * @see http://php.net/strcasecmp
+	 *
+	 * @author  Harry Fuecks <hfuecks@gmail.com>
+	 *
+	 * @param   string   string to compare
+	 * @param   string   string to compare
+	 * @return  integer  less than 0 if str1 is less than str2
+	 * @return  integer  greater than 0 if str1 is greater than str2
+	 * @return  integer  0 if they are equal
+	 */
+	public static function strcasecmp($str1, $str2)
+	{
+		if (text::is_ascii($str1) AND text::is_ascii($str2))
+			return strcasecmp($str1, $str2);
+
+		$str1 = mb_strtolower($str1);
+		$str2 = mb_strtolower($str2);
+		return strcmp($str1, $str2);
+	}
+
+	/**
+	 * Returns a string or an array with all occurrences of search in subject (ignoring case).
+	 * replaced with the given replace value.
+	 * @see     http://php.net/str_ireplace
+	 *
+	 * @note    It's not fast and gets slower if $search and/or $replace are arrays.
+	 * @author  Harry Fuecks <hfuecks@gmail.com
+	 *
+	 * @param   string|array  text to replace
+	 * @param   string|array  replacement text
+	 * @param   string|array  subject text
+	 * @param   integer       number of matched and replaced needles will be returned via this parameter which is passed by reference
+	 * @return  string        if the input was a string
+	 * @return  array         if the input was an array
+	 */
+	public static function str_ireplace($search, $replace, $str, & $count = NULL)
+	{
+		if (text::is_ascii($search) AND text::is_ascii($replace) AND text::is_ascii($str))
+			return str_ireplace($search, $replace, $str, $count);
+
+		if (is_array($str))
+		{
+			foreach ($str as $key => $val)
+			{
+				$str[$key] = utf8::str_ireplace($search, $replace, $val, $count);
+			}
+			return $str;
+		}
+
+		if (is_array($search))
+		{
+			$keys = array_keys($search);
+
+			foreach ($keys as $k)
+			{
+				if (is_array($replace))
+				{
+					if (array_key_exists($k, $replace))
+					{
+						$str = utf8::str_ireplace($search[$k], $replace[$k], $str, $count);
+					}
+					else
+					{
+						$str = utf8::str_ireplace($search[$k], '', $str, $count);
+					}
+				}
+				else
+				{
+					$str = utf8::str_ireplace($search[$k], $replace, $str, $count);
+				}
+			}
+			return $str;
+		}
+
+		$search = mb_strtolower($search);
+		$str_lower = mb_strtolower($str);
+
+		$total_matched_strlen = 0;
+		$i = 0;
+
+		while (preg_match('/(.*?)'.preg_quote($search, '/').'/s', $str_lower, $matches))
+		{
+			$matched_strlen = strlen($matches[0]);
+			$str_lower = substr($str_lower, $matched_strlen);
+
+			$offset = $total_matched_strlen + strlen($matches[1]) + ($i * (strlen($replace) - 1));
+			$str = substr_replace($str, $replace, $offset, strlen($search));
+
+			$total_matched_strlen += $matched_strlen;
+			$i++;
+		}
+
+		$count += $i;
+		return $str;
+	}
+
+	/**
+	 * Case-insenstive UTF-8 version of strstr. Returns all of input string
+	 * from the first occurrence of needle to the end.
+	 * @see http://php.net/stristr
+	 *
+	 * @author Harry Fuecks <hfuecks@gmail.com>
+	 *
+	 * @param   string   input string
+	 * @param   string   needle
+	 * @return  string   matched substring if found
+	 * @return  boolean  FALSE if the substring was not found
+	 */
+	public static function stristr($str, $search)
+	{
+		if (text::is_ascii($str) AND text::is_ascii($search))
+			return stristr($str, $search);
+
+		if ($search == '')
+			return $str;
+
+		$str_lower = mb_strtolower($str);
+		$search_lower = mb_strtolower($search);
+
+		preg_match('/^(.*?)'.preg_quote($search, '/').'/s', $str_lower, $matches);
+
+		if (isset($matches[1]))
+			return substr($str, strlen($matches[1]));
+
+		return FALSE;
+	}
+
+	/**
+	 * Finds the length of the initial segment matching mask.
+	 * @see http://php.net/strspn
+	 *
+	 * @author Harry Fuecks <hfuecks@gmail.com>
+	 *
+	 * @param   string   input string
+	 * @param   string   mask for search
+	 * @param   integer  start position of the string to examine
+	 * @param   integer  length of the string to examine
+	 * @return  integer  length of the initial segment that contains characters in the mask
+	 */
+	public static function strspn($str, $mask, $offset = NULL, $length = NULL)
+	{
+		if ($str == '' OR $mask == '')
+			return 0;
+
+		if (text::is_ascii($str) AND text::is_ascii($mask))
+			return ($offset === NULL) ? strspn($str, $mask) : (($length === NULL) ? strspn($str, $mask, $offset) : strspn($str, $mask, $offset, $length));
+
+		if ($offset !== NULL OR $length !== NULL)
+		{
+			$str = mb_substr($str, $offset, $length);
+		}
+
+		// Escape these characters:  - [ ] . : \ ^ /
+		// The . and : are escaped to prevent possible warnings about POSIX regex elements
+		$mask = preg_replace('#[-[\].:\\\\^/]#', '\\\\$0', $mask);
+		preg_match('/^[^'.$mask.']+/u', $str, $matches);
+
+		return isset($matches[0]) ? mb_strlen($matches[0]) : 0;
+	}
+
+	/**
+	 * Finds the length of the initial segment not matching mask.
+	 * @see http://php.net/strcspn
+	 *
+	 * @author  Harry Fuecks <hfuecks@gmail.com>
+	 *
+	 * @param   string   input string
+	 * @param   string   mask for search
+	 * @param   integer  start position of the string to examine
+	 * @param   integer  length of the string to examine
+	 * @return  integer  length of the initial segment that contains characters not in the mask
+	 */
+	public static function strcspn($str, $mask, $offset = NULL, $length = NULL)
+	{
+		if ($str == '' OR $mask == '')
+			return 0;
+
+		if (text::is_ascii($str) AND text::is_ascii($mask))
+			return ($offset === NULL) ? strcspn($str, $mask) : (($length === NULL) ? strcspn($str, $mask, $offset) : strcspn($str, $mask, $offset, $length));
+
+		if ($str !== NULL OR $length !== NULL)
+		{
+			$str = mb_substr($str, $offset, $length);
+		}
+
+		// Escape these characters:  - [ ] . : \ ^ /
+		// The . and : are escaped to prevent possible warnings about POSIX regex elements
+		$mask = preg_replace('#[-[\].:\\\\^/]#', '\\\\$0', $mask);
+		preg_match('/^[^'.$mask.']+/u', $str, $matches);
+
+		return isset($matches[0]) ? mb_strlen($matches[0]) : 0;
+	}
+
+	/**
+	 * Pads a UTF-8 string to a certain length with another string.
+	 * @see http://php.net/str_pad
+	 *
+	 * @author  Harry Fuecks <hfuecks@gmail.com>
+	 *
+	 * @param   string   input string
+	 * @param   integer  desired string length after padding
+	 * @param   string   string to use as padding
+	 * @param   string   padding type: STR_PAD_RIGHT, STR_PAD_LEFT, or STR_PAD_BOTH
+	 * @return  string
+	 */
+	public static function str_pad($str, $final_str_length, $pad_str = ' ', $pad_type = STR_PAD_RIGHT)
+	{
+		if (text::is_ascii($str) AND text::is_ascii($pad_str))
+		{
+			return str_pad($str, $final_str_length, $pad_str, $pad_type);
+		}
+
+		$str_length = mb_strlen($str);
+
+		if ($final_str_length <= 0 OR $final_str_length <= $str_length)
+		{
+			return $str;
+		}
+
+		$pad_str_length = mb_strlen($pad_str);
+		$pad_length = $final_str_length - $str_length;
+
+		if ($pad_type == STR_PAD_RIGHT)
+		{
+			$repeat = ceil($pad_length / $pad_str_length);
+			return mb_substr($str.str_repeat($pad_str, $repeat), 0, $final_str_length);
+		}
+
+		if ($pad_type == STR_PAD_LEFT)
+		{
+			$repeat = ceil($pad_length / $pad_str_length);
+			return mb_substr(str_repeat($pad_str, $repeat), 0, floor($pad_length)).$str;
+		}
+
+		if ($pad_type == STR_PAD_BOTH)
+		{
+			$pad_length /= 2;
+			$pad_length_left = floor($pad_length);
+			$pad_length_right = ceil($pad_length);
+			$repeat_left = ceil($pad_length_left / $pad_str_length);
+			$repeat_right = ceil($pad_length_right / $pad_str_length);
+
+			$pad_left = mb_substr(str_repeat($pad_str, $repeat_left), 0, $pad_length_left);
+			$pad_right = mb_substr(str_repeat($pad_str, $repeat_right), 0, $pad_length_left);
+			return $pad_left.$str.$pad_right;
+		}
+
+		trigger_error('utf8::str_pad: Unknown padding type (' . $pad_type . ')', E_USER_ERROR);
+	}
+
+	/**
+	 * Converts a UTF-8 string to an array.
+	 * @see http://php.net/str_split
+	 *
+	 * @author  Harry Fuecks <hfuecks@gmail.com>
+	 *
+	 * @param   string   input string
+	 * @param   integer  maximum length of each chunk
+	 * @return  array
+	 */
+	public static function str_split($str, $split_length = 1)
+	{
+		$split_length = (int) $split_length;
+
+		if (text::is_ascii($str))
+		{
+			return str_split($str, $split_length);
+		}
+
+		if ($split_length < 1)
+		{
+			return FALSE;
+		}
+
+		if (mb_strlen($str) <= $split_length)
+		{
+			return array($str);
+		}
+
+		preg_match_all('/.{'.$split_length.'}|[^\x00]{1,'.$split_length.'}$/us', $str, $matches);
+
+		return $matches[0];
+	}
+
+	/**
+	 * Reverses a UTF-8 string.
+	 * @see http://php.net/strrev
+	 *
+	 * @author  Harry Fuecks <hfuecks@gmail.com>
+	 *
+	 * @param   string   string to be reversed
+	 * @return  string
+	 */
+	public static function strrev($str)
+	{
+		if (text::is_ascii($str))
+			return strrev($str);
+
+		preg_match_all('/./us', $str, $matches);
+		return implode('', array_reverse($matches[0]));
+	}
+
+	/**
+	 * Strips whitespace (or other UTF-8 characters) from the beginning and
+	 * end of a string.
+	 * @see http://php.net/trim
+	 *
+	 * @author  Andreas Gohr <andi@splitbrain.org>
+	 *
+	 * @param   string   input string
+	 * @param   string   string of characters to remove
+	 * @return  string
+	 */
+	public static function trim($str, $charlist = NULL)
+	{
+		if ($charlist === NULL)
+			return trim($str);
+
+		return utf8::ltrim(utf8::rtrim($str, $charlist), $charlist);
+	}
+
+	/**
+	 * Strips whitespace (or other UTF-8 characters) from the beginning of a string.
+	 * @see http://php.net/ltrim
+	 *
+	 * @author  Andreas Gohr <andi@splitbrain.org>
+	 *
+	 * @param   string   input string
+	 * @param   string   string of characters to remove
+	 * @return  string
+	 */
+	public static function ltrim($str, $charlist = NULL)
+	{
+		if ($charlist === NULL)
+			return ltrim($str);
+
+		if (text::is_ascii($charlist))
+			return ltrim($str, $charlist);
+
+		$charlist = preg_replace('#[-\[\]:\\\\^/]#', '\\\\$0', $charlist);
+
+		return preg_replace('/^['.$charlist.']+/u', '', $str);
+	}
+
+	/**
+	 * Strips whitespace (or other UTF-8 characters) from the end of a string.
+	 * @see http://php.net/rtrim
+	 *
+	 * @author  Andreas Gohr <andi@splitbrain.org>
+	 *
+	 * @param   string   input string
+	 * @param   string   string of characters to remove
+	 * @return  string
+	 */
+	public static function rtrim($str, $charlist = NULL)
+	{
+		if ($charlist === NULL)
+			return rtrim($str);
+
+		if (text::is_ascii($charlist))
+			return rtrim($str, $charlist);
+
+		$charlist = preg_replace('#[-\[\]:\\\\^/]#', '\\\\$0', $charlist);
+
+		return preg_replace('/['.$charlist.']++$/uD', '', $str);
+	}
+
+	/**
+	 * Returns the unicode ordinal for a character.
+	 * @see http://php.net/ord
+	 *
+	 * @author Harry Fuecks <hfuecks@gmail.com>
+	 *
+	 * @param   string   UTF-8 encoded character
+	 * @return  integer
+	 */
+	public static function ord($chr)
+	{
+		$ord0 = ord($chr);
+
+		if ($ord0 >= 0 AND $ord0 <= 127)
+		{
+			return $ord0;
+		}
+
+		if ( ! isset($chr[1]))
+		{
+			trigger_error('Short sequence - at least 2 bytes expected, only 1 seen', E_USER_WARNING);
+			return FALSE;
+		}
+
+		$ord1 = ord($chr[1]);
+
+		if ($ord0 >= 192 AND $ord0 <= 223)
+		{
+			return ($ord0 - 192) * 64 + ($ord1 - 128);
+		}
+
+		if ( ! isset($chr[2]))
+		{
+			trigger_error('Short sequence - at least 3 bytes expected, only 2 seen', E_USER_WARNING);
+			return FALSE;
+		}
+
+		$ord2 = ord($chr[2]);
+
+		if ($ord0 >= 224 AND $ord0 <= 239)
+		{
+			return ($ord0 - 224) * 4096 + ($ord1 - 128) * 64 + ($ord2 - 128);
+		}
+
+		if ( ! isset($chr[3]))
+		{
+			trigger_error('Short sequence - at least 4 bytes expected, only 3 seen', E_USER_WARNING);
+			return FALSE;
+		}
+
+		$ord3 = ord($chr[3]);
+
+		if ($ord0 >= 240 AND $ord0 <= 247)
+		{
+			return ($ord0 - 240) * 262144 + ($ord1 - 128) * 4096 + ($ord2-128) * 64 + ($ord3 - 128);
+		}
+
+		if ( ! isset($chr[4]))
+		{
+			trigger_error('Short sequence - at least 5 bytes expected, only 4 seen', E_USER_WARNING);
+			return FALSE;
+		}
+
+		$ord4 = ord($chr[4]);
+
+		if ($ord0 >= 248 AND $ord0 <= 251)
+		{
+			return ($ord0 - 248) * 16777216 + ($ord1-128) * 262144 + ($ord2 - 128) * 4096 + ($ord3 - 128) * 64 + ($ord4 - 128);
+		}
+
+		if ( ! isset($chr[5]))
+		{
+			trigger_error('Short sequence - at least 6 bytes expected, only 5 seen', E_USER_WARNING);
+			return FALSE;
+		}
+
+		if ($ord0 >= 252 AND $ord0 <= 253)
+		{
+			return ($ord0 - 252) * 1073741824 + ($ord1 - 128) * 16777216 + ($ord2 - 128) * 262144 + ($ord3 - 128) * 4096 + ($ord4 - 128) * 64 + (ord($chr[5]) - 128);
+		}
+
+		if ($ord0 >= 254 AND $ord0 <= 255)
+		{
+			trigger_error('Invalid UTF-8 with surrogate ordinal '.$ord0, E_USER_WARNING);
+			return FALSE;
+		}
+	}
+
+	/**
+	 * Takes an UTF-8 string and returns an array of ints representing the Unicode characters.
+	 * Astral planes are supported i.e. the ints in the output can be > 0xFFFF.
+	 * Occurrances of the BOM are ignored. Surrogates are not allowed.
+	 *
+	 * The Original Code is Mozilla Communicator client code.
+	 * The Initial Developer of the Original Code is Netscape Communications Corporation.
+	 * Portions created by the Initial Developer are Copyright (C) 1998 the Initial Developer.
+	 * Ported to PHP by Henri Sivonen <hsivonen@iki.fi>, see http://hsivonen.iki.fi/php-utf8/.
+	 * Slight modifications to fit with phputf8 library by Harry Fuecks <hfuecks@gmail.com>.
+	 *
+	 * @param   string   UTF-8 encoded string
+	 * @return  array    unicode code points
+	 * @return  boolean  FALSE if the string is invalid
+	 */
+	public static function to_unicode($str)
+	{
+		$mState = 0; // cached expected number of octets after the current octet until the beginning of the next UTF8 character sequence
+		$mUcs4  = 0; // cached Unicode character
+		$mBytes = 1; // cached expected number of octets in the current sequence
+
+		$out = array();
+
+		$len = strlen($str);
+
+		for ($i = 0; $i < $len; $i++)
+		{
+			$in = ord($str[$i]);
+
+			if ($mState == 0)
+			{
+				// When mState is zero we expect either a US-ASCII character or a
+				// multi-octet sequence.
+				if (0 == (0x80 & $in))
+				{
+					// US-ASCII, pass straight through.
+					$out[] = $in;
+					$mBytes = 1;
+				}
+				elseif (0xC0 == (0xE0 & $in))
+				{
+					// First octet of 2 octet sequence
+					$mUcs4 = $in;
+					$mUcs4 = ($mUcs4 & 0x1F) << 6;
+					$mState = 1;
+					$mBytes = 2;
+				}
+				elseif (0xE0 == (0xF0 & $in))
+				{
+					// First octet of 3 octet sequence
+					$mUcs4 = $in;
+					$mUcs4 = ($mUcs4 & 0x0F) << 12;
+					$mState = 2;
+					$mBytes = 3;
+				}
+				elseif (0xF0 == (0xF8 & $in))
+				{
+					// First octet of 4 octet sequence
+					$mUcs4 = $in;
+					$mUcs4 = ($mUcs4 & 0x07) << 18;
+					$mState = 3;
+					$mBytes = 4;
+				}
+				elseif (0xF8 == (0xFC & $in))
+				{
+					// First octet of 5 octet sequence.
+					//
+					// This is illegal because the encoded codepoint must be either
+					// (a) not the shortest form or
+					// (b) outside the Unicode range of 0-0x10FFFF.
+					// Rather than trying to resynchronize, we will carry on until the end
+					// of the sequence and let the later error handling code catch it.
+					$mUcs4 = $in;
+					$mUcs4 = ($mUcs4 & 0x03) << 24;
+					$mState = 4;
+					$mBytes = 5;
+				}
+				elseif (0xFC == (0xFE & $in))
+				{
+					// First octet of 6 octet sequence, see comments for 5 octet sequence.
+					$mUcs4 = $in;
+					$mUcs4 = ($mUcs4 & 1) << 30;
+					$mState = 5;
+					$mBytes = 6;
+				}
+				else
+				{
+					// Current octet is neither in the US-ASCII range nor a legal first octet of a multi-octet sequence.
+					trigger_error('utf8::to_unicode: Illegal sequence identifier in UTF-8 at byte '.$i, E_USER_WARNING);
+					return FALSE;
+				}
+			}
+			else
+			{
+				// When mState is non-zero, we expect a continuation of the multi-octet sequence
+				if (0x80 == (0xC0 & $in))
+				{
+					// Legal continuation
+					$shift = ($mState - 1) * 6;
+					$tmp = $in;
+					$tmp = ($tmp & 0x0000003F) << $shift;
+					$mUcs4 |= $tmp;
+
+					// End of the multi-octet sequence. mUcs4 now contains the final Unicode codepoint to be output
+					if (0 == --$mState)
+					{
+						// Check for illegal sequences and codepoints
+
+						// From Unicode 3.1, non-shortest form is illegal
+						if (((2 == $mBytes) AND ($mUcs4 < 0x0080)) OR
+							((3 == $mBytes) AND ($mUcs4 < 0x0800)) OR
+							((4 == $mBytes) AND ($mUcs4 < 0x10000)) OR
+							(4 < $mBytes) OR
+							// From Unicode 3.2, surrogate characters are illegal
+							(($mUcs4 & 0xFFFFF800) == 0xD800) OR
+							// Codepoints outside the Unicode range are illegal
+							($mUcs4 > 0x10FFFF))
+						{
+							trigger_error('utf8::to_unicode: Illegal sequence or codepoint in UTF-8 at byte '.$i, E_USER_WARNING);
+							return FALSE;
+						}
+
+						if (0xFEFF != $mUcs4)
+						{
+							// BOM is legal but we don't want to output it
+							$out[] = $mUcs4;
+						}
+
+						// Initialize UTF-8 cache
+						$mState = 0;
+						$mUcs4  = 0;
+						$mBytes = 1;
+					}
+				}
+				else
+				{
+					// ((0xC0 & (*in) != 0x80) AND (mState != 0))
+					// Incomplete multi-octet sequence
+					trigger_error('utf8::to_unicode: Incomplete multi-octet sequence in UTF-8 at byte '.$i, E_USER_WARNING);
+					return FALSE;
+				}
+			}
+		}
+
+		return $out;
+	}
+
+	/**
+	 * Takes an array of ints representing the Unicode characters and returns a UTF-8 string.
+	 * Astral planes are supported i.e. the ints in the input can be > 0xFFFF.
+	 * Occurrances of the BOM are ignored. Surrogates are not allowed.
+	 *
+	 * The Original Code is Mozilla Communicator client code.
+	 * The Initial Developer of the Original Code is Netscape Communications Corporation.
+	 * Portions created by the Initial Developer are Copyright (C) 1998 the Initial Developer.
+	 * Ported to PHP by Henri Sivonen <hsivonen@iki.fi>, see http://hsivonen.iki.fi/php-utf8/.
+	 * Slight modifications to fit with phputf8 library by Harry Fuecks <hfuecks@gmail.com>.
+	 *
+	 * @param   array    unicode code points representing a string
+	 * @return  string   utf8 string of characters
+	 * @return  boolean  FALSE if a code point cannot be found
+	 */
+	public static function from_unicode($arr)
+	{
+		ob_start();
+
+		$keys = array_keys($arr);
+
+		foreach ($keys as $k)
+		{
+			// ASCII range (including control chars)
+			if (($arr[$k] >= 0) AND ($arr[$k] <= 0x007f))
+			{
+				echo chr($arr[$k]);
+			}
+			// 2 byte sequence
+			elseif ($arr[$k] <= 0x07ff)
+			{
+				echo chr(0xc0 | ($arr[$k] >> 6));
+				echo chr(0x80 | ($arr[$k] & 0x003f));
+			}
+			// Byte order mark (skip)
+			elseif ($arr[$k] == 0xFEFF)
+			{
+				// nop -- zap the BOM
+			}
+			// Test for illegal surrogates
+			elseif ($arr[$k] >= 0xD800 AND $arr[$k] <= 0xDFFF)
+			{
+				// Found a surrogate
+				trigger_error('utf8::from_unicode: Illegal surrogate at index: '.$k.', value: '.$arr[$k], E_USER_WARNING);
+				return FALSE;
+			}
+			// 3 byte sequence
+			elseif ($arr[$k] <= 0xffff)
+			{
+				echo chr(0xe0 | ($arr[$k] >> 12));
+				echo chr(0x80 | (($arr[$k] >> 6) & 0x003f));
+				echo chr(0x80 | ($arr[$k] & 0x003f));
+			}
+			// 4 byte sequence
+			elseif ($arr[$k] <= 0x10ffff)
+			{
+				echo chr(0xf0 | ($arr[$k] >> 18));
+				echo chr(0x80 | (($arr[$k] >> 12) & 0x3f));
+				echo chr(0x80 | (($arr[$k] >> 6) & 0x3f));
+				echo chr(0x80 | ($arr[$k] & 0x3f));
+			}
+			// Out of range
+			else
+			{
+				trigger_error('utf8::from_unicode: Codepoint out of Unicode range at index: '.$k.', value: '.$arr[$k], E_USER_WARNING);
+				return FALSE;
+			}
+		}
+
+		$result = ob_get_contents();
+		ob_end_clean();
+		return $result;
+	}
+
+} // End utf8
\ No newline at end of file
diff --git a/system/helpers/valid.php b/system/helpers/valid.php
new file mode 100644
index 0000000..1f7be22
--- /dev/null
+++ b/system/helpers/valid.php
@@ -0,0 +1,453 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * The Valid Helper provides functions to help validate data. They can be used as standalone static functions or
+ * as rules for the Validation Library.
+ *
+ * ###### Validation Library Example:
+ *     $data = new Validation($_POST);
+ *     $data->add_rules('phone', 'required', 'valid::phone[7, 10, 11, 14]')
+ *
+ *     if ($data->validate())
+ *     {
+ *         echo 'The phone number is valid';
+ *     }
+ *     else
+ *     {
+ *         echo Kohana::debug($data->errors());
+ *     }
+ *
+ * [!!] The *valid::* part of the rule is optional, but is recommended to avoid conflicts with php functions.
+ *
+ * For more informaiton see the [Validation] Library.
+ *
+ * ###### Standalone Example:
+ *     if (valid::phone($_POST['phone'], array(7, 10, 11, 14))
+ *     {
+ *         echo 'The phone number is valid';
+ *     }
+ *     else
+ *     {
+ *         echo 'Not valid';
+ *     }
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class valid_Core {
+
+	/**
+	 * Validate an email address. This method is more strict than valid::email_rfc();
+	 *
+	 * ###### Example:
+	 *     $email = 'bill@gates.com';
+	 *     if (valid::email($email))
+	 *     {
+	 *         echo "Valid email";
+	 *     }
+	 *     else
+	 *     {
+	 *         echo "Invalid email";
+	 *     }
+	 *
+	 * @param   string   A email address
+	 * @return  boolean
+	 */
+	public static function email($email)
+	{
+		return (bool) preg_match('/^[-_a-z0-9\'+*$^&%=~!?{}]++(?:\.[-_a-z0-9\'+*$^&%=~!?{}]+)*+@(?:(?![-.])[-a-z0-9.]+(?<![-.])\.[a-z]{2,6}|\d{1,3}(?:\.\d{1,3}){3})(?::\d++)?$/iD', (string) $email);
+	}
+
+	/**
+	 * Validate the domain of an email address by checking if the domain has a
+	 * valid MX record.
+	 *
+	 * [!!] This function will always return `TRUE` if the checkdnsrr() function isn't avaliable (All Windows platforms before php 5.3)
+	 *
+	 * @param   string   email address
+	 * @return  boolean
+	 */
+	public static function email_domain($email)
+	{
+		// If we can't prove the domain is invalid, consider it valid
+		// Note: checkdnsrr() is not implemented on Windows platforms
+		if ( ! function_exists('checkdnsrr'))
+			return TRUE;
+
+		// Check if the email domain has a valid MX record
+		return (bool) checkdnsrr(preg_replace('/^[^@]+@/', '', $email), 'MX');
+	}
+
+	/**
+	 * RFC compliant email validation. This function is __LESS__ strict than [valid::email]. Choose carefully.
+	 *
+	 * @see  Originally by Cal Henderson, modified to fit Kohana syntax standards:
+	 * @see  http://www.iamcal.com/publish/articles/php/parsing_email/
+	 * @see  http://www.w3.org/Protocols/rfc822/
+	 *
+	 * @param   string   email address
+	 * @return  boolean
+	 */
+	public static function email_rfc($email)
+	{
+		$qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
+		$dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
+		$atom  = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
+		$pair  = '\\x5c[\\x00-\\x7f]';
+
+		$domain_literal = "\\x5b($dtext|$pair)*\\x5d";
+		$quoted_string  = "\\x22($qtext|$pair)*\\x22";
+		$sub_domain     = "($atom|$domain_literal)";
+		$word           = "($atom|$quoted_string)";
+		$domain         = "$sub_domain(\\x2e$sub_domain)*";
+		$local_part     = "$word(\\x2e$word)*";
+		$addr_spec      = "$local_part\\x40$domain";
+
+		return (bool) preg_match('/^'.$addr_spec.'$/D', (string) $email);
+	}
+
+	/**
+	 * Basic URL validation.
+	 *
+	 * ###### Example:
+	 *     $url = 'http://www.kohanaphp.com';
+	 *     if (valid::url($url))
+	 *     {
+	 *         echo "Valid url";
+	 *     }
+	 *     else
+	 *     {
+	 *         echo "Invalid url";
+	 *     }
+	 *
+	 * @param   string   URL
+	 * @return  boolean
+	 */
+	public static function url($url)
+	{
+		return (bool) filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED);
+	}
+
+	/**
+	 * Validates an IP Address. This only tests to see if the ip address is valid,
+	 * it doesn't check to see if the ip address is actually in use. Has optional support for
+	 * IPv6, and private ip address ranges.
+	 *
+	 * @param   string   IP address
+	 * @param   boolean  allow IPv6 addresses
+	 * @param   boolean  allow private IP networks
+	 * @return  boolean
+	 */
+	public static function ip($ip, $ipv6 = FALSE, $allow_private = TRUE)
+	{
+		// By default do not allow private and reserved range IPs
+		$flags = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
+		if ($allow_private === TRUE)
+			$flags =  FILTER_FLAG_NO_RES_RANGE;
+
+		if ($ipv6 === TRUE)
+			return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flags);
+
+		return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flags | FILTER_FLAG_IPV4);
+	}
+
+	/**
+	 * Validates a credit card number using the [Luhn (mod10)](http://en.wikipedia.org/wiki/Luhn_algorithm)
+	 * formula.
+	 *
+	 * ###### Example:
+	 *     $cc_number = '4111111111111111';
+	 *     if (valid::credit_card($cc_number, array('visa', 'mastercard')))
+	 *     {
+	 *         echo "Valid number";
+	 *     }
+	 *     else
+	 *     {
+	 *         echo "Invalid number";
+	 *     }
+	 *
+	 * @param   integer       credit card number
+	 * @param   string|array  card type, or an array of card types
+	 * @return  boolean
+	 */
+	public static function credit_card($number, $type = NULL)
+	{
+		// Remove all non-digit characters from the number
+		if (($number = preg_replace('/\D+/', '', $number)) === '')
+			return FALSE;
+
+		if ($type == NULL)
+		{
+			// Use the default type
+			$type = 'default';
+		}
+		elseif (is_array($type))
+		{
+			foreach ($type as $t)
+			{
+				// Test each type for validity
+				if (valid::credit_card($number, $t))
+					return TRUE;
+			}
+
+			return FALSE;
+		}
+
+		$cards = Kohana::config('credit_cards');
+
+		// Check card type
+		$type = strtolower($type);
+
+		if ( ! isset($cards[$type]))
+			return FALSE;
+
+		// Check card number length
+		$length = strlen($number);
+
+		// Validate the card length by the card type
+		if ( ! in_array($length, preg_split('/\D+/', $cards[$type]['length'])))
+			return FALSE;
+
+		// Check card number prefix
+		if ( ! preg_match('/^'.$cards[$type]['prefix'].'/', $number))
+			return FALSE;
+
+		// No Luhn check required
+		if ($cards[$type]['luhn'] == FALSE)
+			return TRUE;
+
+		// Checksum of the card number
+		$checksum = 0;
+
+		for ($i = $length - 1; $i >= 0; $i -= 2)
+		{
+			// Add up every 2nd digit, starting from the right
+			$checksum += substr($number, $i, 1);
+		}
+
+		for ($i = $length - 2; $i >= 0; $i -= 2)
+		{
+			// Add up every 2nd digit doubled, starting from the right
+			$double = substr($number, $i, 1) * 2;
+
+			// Subtract 9 from the double where value is greater than 10
+			$checksum += ($double >= 10) ? $double - 9 : $double;
+		}
+
+		// If the checksum is a multiple of 10, the number is valid
+		return ($checksum % 10 === 0);
+	}
+
+	/**
+	 * Checks if a phone number is valid. This function will strip all non-digit
+	 * characters from the phone number for testing.
+	 *
+	 * ###### Example:
+	 *     $phone_number = '(201) 664-0274';
+	 *     if (valid::phone($phone_number))
+	 *     {
+	 *         echo "Valid phone number";
+	 *     }
+	 *     else
+	 *     {
+	 *         echo "Invalid phone number";
+	 *     }
+	 *
+	 * @param   string   phone number to check
+	 * @return  boolean
+	 */
+	public static function phone($number, $lengths = NULL)
+	{
+		if ( ! is_array($lengths))
+		{
+			$lengths = array(7,10,11);
+		}
+
+		// Remove all non-digit characters from the number
+		$number = preg_replace('/\D+/', '', $number);
+
+		// Check if the number is within range
+		return in_array(strlen($number), $lengths);
+	}
+
+	/**
+	 * Tests if a string is a valid date using the php
+	 * [strtotime()](http://php.net/strtotime) function
+	 *
+	 * @param   string   date to check
+	 * @return  boolean
+	 */
+	public static function date($str)
+	{
+		return (strtotime($str) !== FALSE);
+	}
+
+	/**
+	 * Checks whether a string consists of alphabetical characters only.
+	 *
+	 * @param   string   input string
+	 * @param   boolean  trigger UTF-8 compatibility
+	 * @return  boolean
+	 */
+	public static function alpha($str, $utf8 = FALSE)
+	{
+		return ($utf8 === TRUE)
+			? (bool) preg_match('/^\pL++$/uD', (string) $str)
+			: ctype_alpha((string) $str);
+	}
+
+	/**
+	 * Checks whether a string consists of alphabetical characters and numbers only.
+	 *
+	 * @param   string   input string
+	 * @param   boolean  trigger UTF-8 compatibility
+	 * @return  boolean
+	 */
+	public static function alpha_numeric($str, $utf8 = FALSE)
+	{
+		return ($utf8 === TRUE)
+			? (bool) preg_match('/^[\pL\pN]++$/uD', (string) $str)
+			: ctype_alnum((string) $str);
+	}
+
+	/**
+	 * Checks whether a string consists of alphabetical characters, numbers, underscores and dashes only.
+	 *
+	 * @param   string   input string
+	 * @param   boolean  trigger UTF-8 compatibility
+	 * @return  boolean
+	 */
+	public static function alpha_dash($str, $utf8 = FALSE)
+	{
+		return ($utf8 === TRUE)
+			? (bool) preg_match('/^[-\pL\pN_]++$/uD', (string) $str)
+			: (bool) preg_match('/^[-a-z0-9_]++$/iD', (string) $str);
+	}
+
+	/**
+	 * Checks whether a string consists of digits only (no dots or dashes).
+	 *
+	 * @param   string   input string
+	 * @param   boolean  trigger UTF-8 compatibility
+	 * @return  boolean
+	 */
+	public static function digit($str, $utf8 = FALSE)
+	{
+		return ($utf8 === TRUE)
+			? (bool) preg_match('/^\pN++$/uD', (string) $str)
+			: ctype_digit((string) $str);
+	}
+
+	/**
+	 * Checks whether a string is a valid number (negative and decimal numbers allowed).
+	 * This function uses [localeconv()](http://www.php.net/manual/en/function.localeconv.php)
+	 * to support international number formats.
+	 *
+	 * @param   string   input string
+	 * @return  boolean
+	 */
+	public static function numeric($str)
+	{
+		// Use localeconv to set the decimal_point value: Usually a comma or period.
+		$locale = localeconv();
+		return (bool) preg_match('/^-?[0-9'.$locale['decimal_point'].']++$/D', (string) $str);
+	}
+
+	/**
+	 * Tests if an integer is within a range.
+	 *
+	 * @param   integer  number to check
+	 * @param   array    valid range of input
+	 * @return  boolean
+	 */
+	public static function range($number, array $range)
+	{
+		// Invalid by default
+		$status = FALSE;
+
+		if (is_int($number) OR ctype_digit($number))
+		{
+			if (count($range) > 1)
+			{
+				if ($number >= $range[0] AND $number <= $range[1])
+				{
+					// Number is within the required range
+					$status = TRUE;
+				}
+			}
+			elseif ($number >= $range[0])
+			{
+				// Number is greater than the minimum
+				$status = TRUE;
+			}
+		}
+
+		return $status;
+	}
+
+	/**
+	 * Checks if a string is a proper decimal format. The format array can be
+	 * used to specify a decimal length, or a number and decimal length, eg:
+	 * array(2) would force the number to have 2 decimal places, array(4,2)
+	 * would force the number to have 4 digits and 2 decimal places.
+	 *
+	 * ###### Example:
+	 *     $decimal = '4.5';
+	 *     if (valid::decimal($decimal, array(2,1)))
+	 *     {
+	 *         echo "Valid decimal";
+	 *     }
+	 *     else
+	 *     {
+	 *         echo "Invalid decimal";
+	 *     }
+	 *     
+	 *     Output: Invalid decimal
+	 *
+	 * @param   string   input string
+	 * @param   array    decimal format: y or x,y
+	 * @return  boolean
+	 */
+	public static function decimal($str, $format = NULL)
+	{
+		// Create the pattern
+		$pattern = '/^[0-9]%s\.[0-9]%s$/';
+
+		if ( ! empty($format))
+		{
+			if (count($format) > 1)
+			{
+				// Use the format for number and decimal length
+				$pattern = sprintf($pattern, '{'.$format[0].'}', '{'.$format[1].'}');
+			}
+			elseif (count($format) > 0)
+			{
+				// Use the format as decimal length
+				$pattern = sprintf($pattern, '+', '{'.$format[0].'}');
+			}
+		}
+		else
+		{
+			// No format
+			$pattern = sprintf($pattern, '+', '+');
+		}
+
+		return (bool) preg_match($pattern, (string) $str);
+	}
+
+	/**
+	 * Checks if a string is a proper hexadecimal HTML color value. The validation
+	 * is quite flexible as it does not require an initial "#" and also allows for
+	 * the short notation using only three instead of six hexadecimal characters.
+	 * You may want to normalize these values with format::color().
+	 *
+	 * @param   string   input string
+	 * @return  boolean
+	 */
+	public static function color($str)
+	{
+		return (bool) preg_match('/^#?+[0-9a-f]{3}(?:[0-9a-f]{3})?$/iD', $str);
+	}
+
+} // End valid
\ No newline at end of file
diff --git a/system/libraries/Cache.php b/system/libraries/Cache.php
new file mode 100644
index 0000000..c7954d3
--- /dev/null
+++ b/system/libraries/Cache.php
@@ -0,0 +1,248 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Provides a driver-based interface for finding, creating, and deleting cached
+ * resources. Caches are identified by a unique string. Tagging of caches is
+ * also supported, and caches can be found and deleted by id or tag.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Cache_Core {
+
+	protected static $instances = array();
+
+	// Configuration
+	protected $config;
+
+	// Driver object
+	protected $driver;
+
+	/**
+	 * Returns a singleton instance of Cache.
+	 *
+	 * @param   string  configuration
+	 * @return  Cache_Core
+	 */
+	public static function & instance($config = FALSE)
+	{
+		if ( ! isset(Cache::$instances[$config]))
+		{
+			// Create a new instance
+			Cache::$instances[$config] = new Cache($config);
+		}
+
+		return Cache::$instances[$config];
+	}
+
+	/**
+	 * Loads the configured driver and validates it.
+	 *
+	 * @param   array|string  custom configuration or config group name
+	 * @return  void
+	 */
+	public function __construct($config = FALSE)
+	{
+		if (is_string($config))
+		{
+			$name = $config;
+
+			// Test the config group name
+			if (($config = Kohana::config('cache.'.$config)) === NULL)
+				throw new Cache_Exception('The :group: group is not defined in your configuration.', array(':group:' => $name));
+		}
+
+		if (is_array($config))
+		{
+			// Append the default configuration options
+			$config += Kohana::config('cache.default');
+		}
+		else
+		{
+			// Load the default group
+			$config = Kohana::config('cache.default');
+		}
+
+		// Cache the config in the object
+		$this->config = $config;
+
+		// Set driver name
+		$driver = 'Cache_'.ucfirst($this->config['driver']).'_Driver';
+
+		// Load the driver
+		if ( ! Kohana::auto_load($driver))
+			throw new Cache_Exception('The :driver: driver for the :class: library could not be found',
+									   array(':driver:' => $this->config['driver'], ':class:' => get_class($this)));
+
+		// Initialize the driver
+		$this->driver = new $driver($this->config['params']);
+
+		// Validate the driver
+		if ( ! ($this->driver instanceof Cache_Driver))
+			throw new Cache_Exception('The :driver: driver for the :library: library must implement the :interface: interface',
+									   array(':driver:' => $this->config['driver'], ':library:' => get_class($this), ':interface:' => 'Cache_Driver'));
+
+		Kohana_Log::add('debug', 'Cache Library initialized');
+	}
+
+	/**
+	 * Set cache items
+	 */
+	public function set($key, $value = NULL, $tags = NULL, $lifetime = NULL)
+	{
+		if ($lifetime === NULL)
+		{
+			$lifetime = $this->config['lifetime'];
+		}
+
+		if ( ! is_array($key))
+		{
+			$key = array($key => $value);
+		}
+
+		if ($this->config['prefix'] !== NULL)
+		{
+			$key = $this->add_prefix($key);
+
+			if ($tags !== NULL)
+			{
+				$tags = $this->add_prefix($tags, FALSE);
+			}
+		}
+
+		return $this->driver->set($key, $tags, $lifetime);
+	}
+
+	/**
+	 * Get a cache items by key
+	 */
+	public function get($keys)
+	{
+		$single = FALSE;
+
+		if ( ! is_array($keys))
+		{
+			$keys = array($keys);
+			$single = TRUE;
+		}
+
+		if ($this->config['prefix'] !== NULL)
+		{
+			$keys = $this->add_prefix($keys, FALSE);
+
+			if ( ! $single)
+			{
+			    return $this->strip_prefix($this->driver->get($keys, $single));
+			}
+
+		}
+
+		return $this->driver->get($keys, $single);
+	}
+
+	/**
+	 * Get cache items by tags
+	 */
+	public function get_tag($tags)
+	{
+		if ( ! is_array($tags))
+		{
+			$tags = array($tags);
+		}
+
+		if ($this->config['prefix'] !== NULL)
+		{
+		    $tags = $this->add_prefix($tags, FALSE);
+		    return $this->strip_prefix($this->driver->get_tag($tags));
+		}
+		else
+		{
+		    return $this->driver->get_tag($tags);
+		}
+	}
+
+	/**
+	 * Delete cache item by key
+	 */
+	public function delete($keys)
+	{
+		if ( ! is_array($keys))
+		{
+			$keys = array($keys);
+		}
+
+		if ($this->config['prefix'] !== NULL)
+		{
+			$keys = $this->add_prefix($keys, FALSE);
+		}
+
+		return $this->driver->delete($keys);
+	}
+
+	/**
+	 * Delete cache items by tag
+	 */
+	public function delete_tag($tags)
+	{
+		if ( ! is_array($tags))
+		{
+			$tags = array($tags);
+		}
+
+		if ($this->config['prefix'] !== NULL)
+		{
+			$tags = $this->add_prefix($tags, FALSE);
+		}
+
+		return $this->driver->delete_tag($tags);
+	}
+
+	/**
+	 * Empty the cache
+	 */
+	public function delete_all()
+	{
+		return $this->driver->delete_all();
+	}
+
+	/**
+	 * Add a prefix to keys or tags
+	 */
+	protected function add_prefix($array, $to_key = TRUE)
+	{
+		$out = array();
+
+		foreach($array as $key => $value)
+		{
+			if ($to_key)
+			{
+				$out[$this->config['prefix'].$key] = $value;
+			}
+			else
+			{
+				$out[$key] = $this->config['prefix'].$value;
+			}
+		}
+
+		return $out;
+	}
+
+	/**
+	 * Strip a prefix to keys or tags
+	 */
+	protected function strip_prefix($array)
+	{
+		$out = array();
+
+		$start = strlen($this->config['prefix']);
+
+		foreach($array as $key => $value)
+		{
+			$out[substr($key, $start)] = $value;
+		}
+
+		return $out;
+	}
+
+} // End Cache Library
\ No newline at end of file
diff --git a/system/libraries/Cache_Exception.php b/system/libraries/Cache_Exception.php
new file mode 100644
index 0000000..706dc09
--- /dev/null
+++ b/system/libraries/Cache_Exception.php
@@ -0,0 +1,11 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+class Cache_Exception_Core extends Kohana_Exception {}
+// End Kohana User Exception
diff --git a/system/libraries/Controller.php b/system/libraries/Controller.php
new file mode 100644
index 0000000..a1139f6
--- /dev/null
+++ b/system/libraries/Controller.php
@@ -0,0 +1,44 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Kohana Controller class. The controller class must be extended to work
+ * properly, so this class is defined as abstract.
+ *
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+abstract class Controller_Core {
+
+	// Allow all controllers to run in production by default
+	const ALLOW_PRODUCTION = TRUE;
+
+	/**
+	 * Loads URI, and Input into this controller.
+	 *
+	 * @return  void
+	 */
+	public function __construct()
+	{
+		if (Kohana::$instance == NULL)
+		{
+			// Set the instance to the first controller loaded
+			Kohana::$instance = $this;
+		}
+	}
+
+	/**
+	 * Handles methods that do not exist.
+	 *
+	 * @param   string  method name
+	 * @param   array   arguments
+	 * @return  void
+	 */
+	public function __call($method, $args)
+	{
+		// Default to showing a 404 page
+		Event::run('system.404');
+	}
+
+} // End Controller Class
\ No newline at end of file
diff --git a/system/libraries/Database.php b/system/libraries/Database.php
new file mode 100644
index 0000000..253bb15
--- /dev/null
+++ b/system/libraries/Database.php
@@ -0,0 +1,648 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Database wrapper.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+abstract class Database_Core {
+
+	const SELECT          =  1;
+	const INSERT          =  2;
+	const UPDATE          =  3;
+	const DELETE          =  4;
+	const CROSS_REQUEST   =  5;
+	const PER_REQUEST     =  6;
+
+	protected static $instances = array();
+
+	// Global benchmarks
+	public static $benchmarks = array();
+
+	// Last execute query
+	protected $last_query;
+
+	// Configuration array
+	protected $config;
+
+	// Required configuration keys
+	protected $config_required = array();
+
+	// Raw server connection
+	protected $connection;
+
+	// Cache (Cache object for cross-request, array for per-request)
+	protected $cache;
+
+	// Quote character to use for identifiers (tables/columns/aliases)
+	protected $quote = '"';
+
+	/**
+	 * Returns a singleton instance of Database.
+	 *
+	 * @param   string  Database name
+	 * @return  Database_Core
+	 */
+	public static function instance($name = 'default')
+	{
+		if ( ! isset(Database::$instances[$name]))
+		{
+			// Load the configuration for this database group
+			$config = Kohana::config('database.'.$name);
+
+			if (is_string($config['connection']))
+			{
+				// Parse the DSN into connection array
+				$config['connection'] = Database::parse_dsn($config['connection']);
+			}
+
+			// Set the driver class name
+			$driver = 'Database_'.ucfirst($config['connection']['type']);
+
+			// Create the database connection instance
+			Database::$instances[$name] = new $driver($config);
+		}
+
+		return Database::$instances[$name];
+	}
+
+	/**
+	 * Constructs a new Database object
+	 *
+	 * @param   array  Database config array
+	 * @return  Database_Core
+	 */
+	protected function __construct(array $config)
+	{
+		// Store the config locally
+		$this->config = $config;
+
+		if ($this->config['cache'] !== FALSE)
+		{
+			if (is_string($this->config['cache']))
+			{
+				// Use Cache library
+				$this->cache = new Cache($this->config['cache']);
+			}
+			elseif ($this->config['cache'] === TRUE)
+			{
+				// Use array
+				$this->cache = array();
+			}
+		}
+	}
+
+	public function __destruct()
+	{
+		$this->disconnect();
+	}
+
+	/**
+	 * Connects to the database
+	 *
+	 * @return void
+	 */
+	abstract public function connect();
+
+	/**
+	 * Disconnects from the database
+	 *
+	 * @return void
+	 */
+	abstract public function disconnect();
+
+	/**
+	 * Sets the character set
+	 *
+	 * @return void
+	 */
+	abstract public function set_charset($charset);
+
+	/**
+	 * Executes the query
+	 *
+	 * @param  string  SQL
+	 * @return Database_Result
+	 */
+	abstract public function query_execute($sql);
+
+	/**
+	 * Escapes the given value
+	 *
+	 * @param  mixed  Value
+	 * @return mixed  Escaped value
+	 */
+	abstract public function escape($value);
+
+	/**
+	 * List constraints for the given table
+	 *
+	 * @param  string  Table name
+	 * @return array
+	 */
+	abstract public function list_constraints($table);
+
+	/**
+	 * List fields for the given table
+	 *
+	 * @param  string  Table name
+	 * @return array
+	 */
+	abstract public function list_fields($table);
+
+	/**
+	 * List tables for the given connection (checks for prefix)
+	 *
+	 * @return array
+	 */
+	abstract public function list_tables();
+
+	/**
+	 * Converts the given DSN string to an array of database connection components
+	 *
+	 * @param  string  DSN string
+	 * @return array
+	 */
+	public static function parse_dsn($dsn)
+	{
+		$db = array
+		(
+			'type'     => FALSE,
+			'user'     => FALSE,
+			'pass'     => FALSE,
+			'host'     => FALSE,
+			'port'     => FALSE,
+			'socket'   => FALSE,
+			'database' => FALSE
+		);
+
+		// Get the protocol and arguments
+		list ($db['type'], $connection) = explode('://', $dsn, 2);
+
+		if ($connection[0] === '/')
+		{
+			// Strip leading slash
+			$db['database'] = substr($connection, 1);
+		}
+		else
+		{
+			$connection = parse_url('http://'.$connection);
+
+			if (isset($connection['user']))
+			{
+				$db['user'] = $connection['user'];
+			}
+
+			if (isset($connection['pass']))
+			{
+				$db['pass'] = $connection['pass'];
+			}
+
+			if (isset($connection['port']))
+			{
+				$db['port'] = $connection['port'];
+			}
+
+			if (isset($connection['host']))
+			{
+				if ($connection['host'] === 'unix(')
+				{
+					list($db['socket'], $connection['path']) = explode(')', $connection['path'], 2);
+				}
+				else
+				{
+					$db['host'] = $connection['host'];
+				}
+			}
+
+			if (isset($connection['path']) AND $connection['path'])
+			{
+				// Strip leading slash
+				$db['database'] = substr($connection['path'], 1);
+			}
+		}
+
+		return $db;
+	}
+
+	/**
+	 * Returns the last executed query for this database
+	 *
+	 * @return string
+	 */
+	public function last_query()
+	{
+		return $this->last_query;
+	}
+
+	/**
+	 * Executes the given query, returning the cached version if enabled
+	 *
+	 * @param  string  SQL query
+	 * @return Database_Result
+	 */
+	public function query($sql)
+	{
+		// Start the benchmark
+		$start = microtime(TRUE);
+
+		if (is_array($this->cache))
+		{
+			$hash = $this->query_hash($sql);
+
+			if (isset($this->cache[$hash]))
+			{
+				// Use cached result
+				$result = $this->cache[$hash];
+
+				// It's from cache
+				$sql .= ' [CACHE]';
+			}
+			else
+			{
+				// No cache, execute query and store in cache
+				$result = $this->cache[$hash] = $this->query_execute($sql);
+			}
+		}
+		else
+		{
+			// Execute the query, cache is off
+			$result = $this->query_execute($sql);
+		}
+
+		// Stop the benchmark
+		$stop = microtime(TRUE);
+
+		if ($this->config['benchmark'] === TRUE)
+		{
+			// Benchmark the query
+			Database::$benchmarks[] = array('query' => $sql, 'time' => $stop - $start, 'rows' => count($result));
+		}
+
+		return $result;
+	}
+
+	/**
+	 * Performs the query on the cache (and caches it if it's not found)
+	 *
+	 * @param   string  query
+	 * @param   int     time-to-live (NULL for Cache default)
+	 * @return  Database_Cache_Result
+	 */
+	public function query_cache($sql, $ttl)
+	{
+		if ( ! $this->cache instanceof Cache)
+		{
+			throw new Database_Exception('Database :name has not been configured to use the Cache library.');
+		}
+
+		// Start the benchmark
+		$start = microtime(TRUE);
+
+		$hash = $this->query_hash($sql);
+
+		if (($data = $this->cache->get($hash)) !== NULL)
+		{
+			// Found in cache, create result
+			$result = new Database_Cache_Result($data, $sql, $this->config['object']);
+
+			// It's from the cache
+			$sql .= ' [CACHE]';
+		}
+		else
+		{
+			// Run the query and return the full array of rows
+			$data = $this->query_execute($sql)->as_array(TRUE);
+
+			// Set the Cache
+			$this->cache->set($hash, $data, NULL, $ttl);
+
+			// Create result
+			$result = new Database_Cache_Result($data, $sql, $this->config['object']);
+		}
+
+		// Stop the benchmark
+		$stop = microtime(TRUE);
+
+		if ($this->config['benchmark'] === TRUE)
+		{
+			// Benchmark the query
+			Database::$benchmarks[] = array('query' => $sql, 'time' => $stop - $start, 'rows' => count($result));
+		}
+
+		return $result;
+	}
+
+	/**
+	 * Generates a hash for the given query
+	 *
+	 * @param   string  SQL query string
+	 * @return  string
+	 */
+	protected function query_hash($sql)
+	{
+		return sha1(str_replace("\n", ' ', trim($sql)));
+	}
+
+	/**
+	 * Clears the internal query cache.
+	 *
+	 * @param   mixed  clear cache by SQL statement, NULL for all, or TRUE for last query
+	 * @param   integer  Type of cache to clear, Database::CROSS_REQUEST or Database::PER_REQUEST
+	 * @return  Database
+	 */
+	public function clear_cache($sql = NULL, $type = NULL)
+	{
+		if ($this->cache instanceof Cache AND ($type == NULL OR $type == Database::CROSS_REQUEST))
+		{
+			// Using cross-request Cache library
+			if ($sql === TRUE)
+			{
+				$this->cache->delete($this->query_hash($this->last_query));
+			}
+			elseif (is_string($sql))
+			{
+				$this->cache->delete($this->query_hash($sql));
+			}
+			else
+			{
+				$this->cache->delete_all();
+			}
+		}
+		elseif (is_array($this->cache) AND ($type == NULL OR $type == Database::PER_REQUEST))
+		{
+			// Using per-request memory cache
+			if ($sql === TRUE)
+			{
+				unset($this->cache[$this->query_hash($this->last_query)]);
+			}
+			elseif (is_string($sql))
+			{
+				unset($this->cache[$this->query_hash($sql)]);
+			}
+			else
+			{
+				$this->cache = array();
+			}
+		}
+	}
+
+	/**
+	 * Quotes the given value
+	 *
+	 * @param   mixed  value
+	 * @return  mixed
+	 */
+	public function quote($value)
+	{
+		if ( ! $this->config['escape'])
+			return $value;
+
+		if ($value === NULL)
+		{
+			return 'NULL';
+		}
+		elseif ($value === TRUE)
+		{
+			return 'TRUE';
+		}
+		elseif ($value === FALSE)
+		{
+			return 'FALSE';
+		}
+		elseif (is_int($value))
+		{
+			return (int) $value;
+		}
+		elseif ($value instanceof Database_Expression)
+		{
+			return (string) $value;
+		}
+		elseif (is_float($value))
+		{
+			// Convert to non-locale aware float to prevent possible commas
+			return sprintf('%F', $value);
+		}
+
+		return '\''.$this->escape($value).'\'';
+	}
+
+	/**
+	 * Quotes a table, adding the table prefix
+	 * Reserved characters not allowed in table names for the builder are [ .*] (space, dot, asterisk)
+	 *
+	 * @param   string|array    table name or array - 'users u' or array('u' => 'users') both valid
+	 * @param   string          table alias
+	 * @return  string
+	 */
+	public function quote_table($table, $alias = NULL)
+	{
+		if (is_array($table))
+		{
+			// Using array('u' => 'user')
+			list($alias, $table) = each($table);
+		}
+		elseif (strpos(' ', $table) !== FALSE)
+		{
+			// Using format 'user u'
+			list($table, $alias) = explode(' ', $table);
+		}
+
+		if ($table instanceof Database_Expression)
+		{
+			if ($alias)
+			{
+				if ($this->config['escape'])
+				{
+					$alias = $this->quote.$alias.$this->quote;
+				}
+
+				return $table.' AS '.$alias;
+			}
+
+			return (string) $table;
+		}
+
+		if ($this->config['table_prefix'])
+		{
+			$table = $this->config['table_prefix'].$table;
+		}
+
+		if ($alias)
+		{
+			if ($this->config['escape'])
+			{
+				$table = $this->quote.$table.$this->quote;
+				$alias = $this->quote.$alias.$this->quote;
+			}
+
+			return $table.' AS '.$alias;
+		}
+
+		if ($this->config['escape'])
+		{
+			$table = $this->quote.$table.$this->quote;
+		}
+
+		return $table;
+	}
+
+	/**
+	 * Quotes column or table.column, adding the table prefix if necessary
+	 * Reserved characters not allowed in table names for the builder are [ .*] (space, dot, asterisk)
+	 * Complex column names must have table/columns in double quotes, e.g. array('mycount' => 'COUNT("users.id")')
+	 *
+	 * @param   string|array    column name or array('u' => 'COUNT("*")')
+	 * @param   string          column alias
+	 * @return  string
+	 */
+	public function quote_column($column, $alias = NULL)
+	{
+		if ($column === '*')
+			return $column;
+
+		if (is_array($column))
+		{
+			list($alias, $column) = each($column);
+		}
+
+		if ($column instanceof Database_Expression)
+		{
+			if ($alias)
+			{
+				if ($this->config['escape'])
+				{
+					$alias = $this->quote.$alias.$this->quote;
+				}
+
+				return $column.' AS '.$alias;
+			}
+
+			return (string) $column;
+		}
+
+		if ($this->config['table_prefix'] AND strpos($column, '.') !== FALSE)
+		{
+			if (strpos($column, '"') !== FALSE)
+			{
+				// Find "table.column" and replace them with "[prefix]table.column"
+				$column = preg_replace('/"([^.]++)\.([^"]++)"/', '"'.$this->config['table_prefix'].'$1.$2"', $column);
+			}
+			else
+			{
+				// Attach table prefix if table.column format
+				$column = $this->config['table_prefix'].$column;
+			}
+		}
+
+		if ($this->config['escape'])
+		{
+			if (strpos($column, '"') === FALSE)
+			{
+				// Quote the column
+				$column = $this->quote.$column.$this->quote;
+			}
+			elseif ($this->quote !== '"')
+			{
+				// Replace double quotes
+				$column = str_replace('"', $this->quote, $column);
+			}
+
+			// Replace . with "."
+			$column = str_replace('.', $this->quote.'.'.$this->quote, $column);
+
+			// Unescape any asterisks
+			$column = str_replace($this->quote.'*'.$this->quote, '*', $column);
+
+			if ($alias)
+			{
+				// Quote the alias
+				return $column.' AS '.$this->quote.$alias.$this->quote;
+			}
+
+			return $column;
+		}
+
+		// Strip double quotes
+		$column = str_replace('"', '', $column);
+
+		if ($alias)
+			return $column.' AS '.$alias;
+
+		return $column;
+	}
+
+	/**
+	 * Get the table prefix
+	 *
+	 * @param  string  Optional new table prefix to set
+	 * @return string
+	 */
+	public function table_prefix($new_prefix = NULL)
+	{
+		$prefix = $this->config['table_prefix'];
+
+		if ($new_prefix !== NULL)
+		{
+			// Set a new prefix
+			$this->config['table_prefix'] = $new_prefix;
+		}
+
+		return $prefix;
+	}
+
+	/**
+	 * Fetches SQL type information about a field, in a generic format.
+	 *
+	 * @param   string  field datatype
+	 * @return  array
+	 */
+	protected function sql_type($str)
+	{
+		static $sql_types;
+
+		if ($sql_types === NULL)
+		{
+			// Load SQL data types
+			$sql_types = Kohana::config('sql_types');
+		}
+
+		$str = trim($str);
+
+		if (($open = strpos($str, '(')) !== FALSE)
+		{
+			// Closing bracket
+			$close = strpos($str, ')', $open);
+
+			// Length without brackets
+			$length = substr($str, $open + 1, $close - 1 - $open);
+
+			// Type without the length
+			$type = substr($str, 0, $open).substr($str, $close + 1);
+		}
+		else
+		{
+			// No length
+			$type = $str;
+		}
+
+		if (empty($sql_types[$type]))
+			throw new Database_Exception('Undefined field type :type', array(':type' => $str));
+
+		// Fetch the field definition
+		$field = $sql_types[$type];
+
+		$field['sql_type'] = $type;
+
+		if (isset($length))
+		{
+			// Add the length to the field info
+			$field['length'] = $length;
+		}
+
+		return $field;
+	}
+
+} // End Database
diff --git a/system/libraries/Database_Builder.php b/system/libraries/Database_Builder.php
new file mode 100644
index 0000000..e86ce37
--- /dev/null
+++ b/system/libraries/Database_Builder.php
@@ -0,0 +1,1241 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * The Database Query Builder provides methods for creating database agnostic queries and
+ * data manipulation.
+ *
+ * ##### A basic select query
+ *
+ *     $builder = new Database_Builder;
+ *     $kohana = $builder
+ *                 ->select()
+ *                 ->where('name', '=', 'Kohana')
+ *                 ->from('frameworks')
+ *                 ->execute();
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Database_Builder_Core {
+
+	// Valid ORDER BY directions
+	protected $order_directions = array('ASC', 'DESC', 'RAND()');
+
+	// Database object
+	protected $db;
+
+	// Builder members
+	protected $select   = array();
+	protected $from     = array();
+	protected $join     = array();
+	protected $where    = array();
+	protected $group_by = array();
+	protected $having   = array();
+	protected $order_by = array();
+	protected $limit    = NULL;
+	protected $offset   = NULL;
+	protected $set      = array();
+	protected $columns  = array();
+	protected $values   = array();
+	protected $type;
+	protected $distinct = FALSE;
+	protected $reset    = TRUE;
+
+	// TTL for caching (using Cache library)
+	protected $ttl      = FALSE;
+
+	public function __construct($db = 'default')
+	{
+		$this->db = $db;
+	}
+
+	/**
+	 * Compiles the builder object into a SQL query. Useful for debugging
+	 *
+	 * ##### Example
+	 *
+	 *     echo $builder->select()->from('products');
+	 *     // Output: SELECT * FROM `products`
+	 *
+	 * @return  string Compiled query
+	 */
+	public function __toString()
+	{
+		return $this->compile();
+	}
+
+	/**
+	 * Creates a `SELECT` query with support for column aliases, database functions,
+	 * subqueries or a [Database_Expression]
+	 *
+	 * ##### Examples
+	 *
+	 *     // Simple select
+	 *     echo $builder->select()->from('products');
+	 *
+	 *     // Select with database function
+	 *     echo $builder->select(array('records_found' => 'COUNT("*")'))->from('products');
+	 *
+	 *     // Select with sub query
+	 *     echo $builder->select(array('field', 'test' => db::select('test')->from('table')))->from('products');
+	 *
+	 * @chainable
+	 * @param   string|array    column name or array(alias => column)
+	 * @return  Database_Builder
+	 */
+	public function select($columns = NULL)
+	{
+		$this->type = Database::SELECT;
+
+		if ($columns === NULL)
+		{
+			$columns = array('*');
+		}
+		elseif ( ! is_array($columns))
+		{
+			$columns = func_get_args();
+		}
+
+		$this->select = array_merge($this->select, $columns);
+
+		return $this;
+	}
+
+	/**
+	 * Creates a `DISTINCT SELECT` query. For more information see see [Database_Builder::select].
+	 *
+	 * @chainable
+	 * @param   string|array    column name or array(alias => column)
+	 * @return  Database_Builder
+	 */
+	public function select_distinct($columns = NULL)
+	{
+		$this->select($columns);
+		$this->distinct = TRUE;
+		return $this;
+	}
+
+	/**
+	 * Add tables to the FROM portion of the builder
+	 *
+	 * ##### Example
+	 *
+	 *     $builder->select()->from('products')
+	 *             ->from(array('other' => 'other_table'));
+	 *     // Output: SELECT * FROM `products`, `other_table` AS `other`
+	 *
+	 * @chainable
+	 * @param   string|array    table name or array(alias => table)
+	 * @return  Database_Builder
+	 */
+	public function from($tables)
+	{
+		if ( ! is_array($tables))
+		{
+			$tables = func_get_args();
+		}
+
+		$this->from = array_merge($this->from, $tables);
+
+		return $this;
+	}
+
+	/**
+	 * Add conditions to the `WHERE` clause. Alias for [Database_Builder::and_where].
+	 *
+	 * @chainable
+	 * @param  mixed   Column name or array of columns => vals
+	 * @param  string  Operation to perform
+	 * @param  mixed   Value
+	 * @return Database_Builder
+	 */
+	public function where($columns, $op = '=', $value = NULL)
+	{
+		return $this->and_where($columns, $op, $value);
+	}
+
+	/**
+	 * Add conditions to the `WHERE` clause separating multiple conditions with `AND`.
+	 * This function supports all `WHERE` operators including `LIKE` and `IN`. It can
+	 * also be used with a [Database_Expression] or subquery.
+	 *
+	 * ##### Examples
+	 *
+	 *     // Basic where condition
+	 *     $builder->where('field', '=', 'value');
+	 *
+	 *     // Multiple conditions with an array (you can also chain where() function calls)
+	 *     $builder->where(array(array('field', '=', 'value'), array(...)));
+	 *
+	 *     // With a database expression
+	 *     $builder->where('field', '=', db::expr('field + 1'));
+	 *     // or a function
+	 *     $builder->where('field', '=', db::expr('UNIX_TIMESTAMP()'));
+	 *
+	 *     // With a subquery
+	 *     $builder->where('field', 'IN', db::select('id')->from('table'));
+	 *
+	 * [!!] You must manually escape all data you pass into a database expression!
+	 *
+	 * @chainable
+	 * @param  mixed   Column name or array of triplets
+	 * @param  string  Operation to perform
+	 * @param  mixed   Value
+	 * @return Database_Builder
+	 */
+	public function and_where($columns, $op = '=', $value = NULL)
+	{
+		if (is_array($columns))
+		{
+			foreach ($columns as $column)
+			{
+				$this->where[] = array('AND' => $column);
+			}
+		}
+		else
+		{
+			$this->where[] = array('AND' => array($columns, $op, $value));
+		}
+		return $this;
+	}
+
+	/**
+	 * Add conditions to the `WHERE` clause separating multiple conditions with `OR`.
+	 * For more information about building a `WHERE` clause see [Database_Builder::and_where]
+	 *
+	 * @chainable
+	 * @param  mixed   Column name or array of triplets
+	 * @param  string  Operation to perform
+	 * @param  mixed   Value
+	 * @return Database_Builder
+	 */
+	public function or_where($columns, $op = '=', $value = NULL)
+	{
+		if (is_array($columns))
+		{
+			foreach ($columns as $column)
+			{
+				$this->where[] = array('OR' => $column);
+			}
+		}
+		else
+		{
+			$this->where[] = array('OR' => array($columns, $op, $value));
+		}
+		return $this;
+	}
+
+	/**
+	 * Join tables to the builder
+	 *
+	 * ##### Example
+	 *
+	 *     // Basic join
+	 *     db::select()->from('products')
+	 *                 ->join('reviews', 'reviews.product_id', 'products.id');
+	 *
+	 *     // Advanced joins
+	 *     echo db::select()->from('products')
+	 *                      ->join('reviews', 'field', db::expr('advanced condition here'), 'RIGHT');
+	 *
+	 * @chainable
+	 * @param  mixed   Table name
+	 * @param  mixed   Key, or an array of key => value pair, for join condition (can be a Database_Expression)
+	 * @param  mixed   Value if $keys is not an array or Database_Expression
+	 * @param  string  Join type (LEFT, RIGHT, INNER, etc.)
+	 * @return Database_Builder
+	 */
+	public function join($table, $keys, $value = NULL, $type = NULL)
+	{
+		if (is_string($keys))
+		{
+			$keys = array($keys => $value);
+		}
+
+		if ($type !== NULL)
+		{
+			$type = strtoupper($type);
+		}
+
+		$this->join[] = array($table, $keys, $type);
+
+		return $this;
+	}
+
+	/**
+	 * This function is an alias for [Database_Builder::join]
+	 * with the join type set to `LEFT`.
+	 *
+	 * @chainable
+	 * @param  mixed   Table name
+	 * @param  mixed   Key, or an array of key => value pair, for join condition (can be a Database_Expression)
+	 * @param  mixed   Value if $keys is not an array or Database_Expression
+	 * @return Database_Builder
+	 */
+	public function left_join($table, $keys, $value = NULL)
+	{
+		return $this->join($table, $keys, $value, 'LEFT');
+	}
+
+	/**
+	 * This function is an alias for [Database_Builder::join]
+	 * with the join type set to `RIGHT`.
+	 *
+	 * @chainable
+	 * @param  mixed   Table name
+	 * @param  mixed   Key, or an array of key => value pair, for join condition (can be a Database_Expression)
+	 * @param  mixed   Value if $keys is not an array or Database_Expression
+	 * @return Database_Builder
+	 */
+	public function right_join($table, $keys, $value = NULL)
+	{
+		return $this->join($table, $keys, $value, 'RIGHT');
+	}
+
+	/**
+	 * This function is an alias for [Database_Builder::join]
+	 * with the join type set to `INNER`.
+	 *
+	 * @chainable
+	 * @param  mixed   Table name
+	 * @param  mixed   Key, or an array of key => value pair, for join condition (can be a Database_Expression)
+	 * @param  mixed   Value if $keys is not an array or Database_Expression
+	 * @return Database_Builder
+	 */
+	public function inner_join($table, $keys, $value = NULL)
+	{
+		return $this->join($table, $keys, $value, 'INNER');
+	}
+
+	/**
+	 * This function is an alias for [Database_Builder::join]
+	 * with the join type set to `OUTER`.
+	 *
+	 * @chainable
+	 * @param  mixed   Table name
+	 * @param  mixed   Key, or an array of key => value pair, for join condition (can be a Database_Expression)
+	 * @param  mixed   Value if $keys is not an array or Database_Expression
+	 * @return Database_Builder
+	 */
+	public function outer_join($table, $keys, $value = NULL)
+	{
+		return $this->join($table, $keys, $value, 'OUTER');
+	}
+
+	/**
+	 * This function is an alias for [Database_Builder::join]
+	 * with the join type set to `FULL`.
+	 *
+	 * @chainable
+	 * @param  mixed   Table name
+	 * @param  mixed   Key, or an array of key => value pair, for join condition (can be a Database_Expression)
+	 * @param  mixed   Value if $keys is not an array or Database_Expression
+	 * @return Database_Builder
+	 */
+	public function full_join($table, $keys, $value = NULL)
+	{
+		return $this->join($table, $keys, $value, 'FULL');
+	}
+
+	/**
+	 * This function is an alias for [Database_Builder::join]
+	 * with the join type set to `LEFT INNER`.
+	 *
+	 * @chainable
+	 * @param  mixed   Table name
+	 * @param  mixed   Key, or an array of key => value pair, for join condition (can be a Database_Expression)
+	 * @param  mixed   Value if $keys is not an array or Database_Expression
+	 * @return Database_Builder
+	 */
+	public function left_inner_join($table, $keys, $value = NULL)
+	{
+		return $this->join($table, $keys, $value, 'LEFT INNER');
+	}
+
+	/**
+	 * This function is an alias for [Database_Builder::join]
+	 * with the join type set to `RIGHT INNER`.
+	 *
+	 * @chainable
+	 * @param  mixed   Table name
+	 * @param  mixed   Key, or an array of key => value pair, for join condition (can be a Database_Expression)
+	 * @param  mixed   Value if $keys is not an array or Database_Expression
+	 * @return Database_Builder
+	 */
+	public function right_inner_join($table, $keys, $value = NULL)
+	{
+		return $this->join($table, $keys, $value, 'RIGHT INNER');
+	}
+
+	/**
+	 * Add fields to the GROUP BY portion
+	 *
+	 * ##### Example
+	 *
+	 *     db::select()->from('products')
+	 *                 ->group_by(array('name', 'cat_id'));
+	 *     // Output: SELECT * FROM `products` GROUP BY `name`, `cat_id`
+	 *
+	 * @chainable
+	 * @param  mixed  Field names or an array of fields
+	 * @return Database_Builder
+	 */
+	public function group_by($columns)
+	{
+		if ( ! is_array($columns))
+		{
+			$columns = func_get_args();
+		}
+
+		$this->group_by = array_merge($this->group_by, $columns);
+
+		return $this;
+	}
+
+	/**
+	 * Add conditions to the HAVING clause (AND)
+	 *
+	 * @chainable
+	 * @param  mixed   Column name or array of columns => vals
+	 * @param  string  Operation to perform
+	 * @param  mixed   Value
+	 * @return Database_Builder
+	 */
+	public function having($columns, $op = '=', $value = NULL)
+	{
+		return $this->and_having($columns, $op, $value);
+	}
+
+	/**
+	 * Add conditions to the HAVING clause (AND)
+	 *
+	 * @chainable
+	 * @param  mixed   Column name or array of triplets
+	 * @param  string  Operation to perform
+	 * @param  mixed   Value
+	 * @return Database_Builder
+	 */
+	public function and_having($columns, $op = '=', $value = NULL)
+	{
+		if (is_array($columns))
+		{
+			foreach ($columns as $column)
+			{
+				$this->having[] = array('AND' => $column);
+			}
+		}
+		else
+		{
+			$this->having[] = array('AND' => array($columns, $op, $value));
+		}
+		return $this;
+	}
+
+	/**
+	 * Add conditions to the HAVING clause (OR)
+	 *
+	 * @chainable
+	 * @param  mixed   Column name or array of triplets
+	 * @param  string  Operation to perform
+	 * @param  mixed   Value
+	 * @return Database_Builder
+	 */
+	public function or_having($columns, $op = '=', $value = NULL)
+	{
+		if (is_array($columns))
+		{
+			foreach ($columns as $column)
+			{
+				$this->having[] = array('OR' => $column);
+			}
+		}
+		else
+		{
+			$this->having[] = array('OR' => array($columns, $op, $value));
+		}
+		return $this;
+	}
+
+	/**
+	 * Add fields to the ORDER BY portion
+	 *
+	 * @chainable
+	 * @param  mixed   Field names or an array of fields (field => direction)
+	 * @param  string  Direction or NULL for ascending
+	 * @return Database_Builder
+	 */
+	public function order_by($columns, $direction = NULL)
+	{
+		if (is_array($columns))
+		{
+			foreach ($columns as $column => $direction)
+			{
+				if (is_string($column))
+				{
+					$this->order_by[] = array($column => $direction);
+				}
+				else
+				{
+					// $direction is the column name when the array key is numeric
+					$this->order_by[] = array($direction => NULL);
+				}
+			}
+		}
+		else
+		{
+			$this->order_by[] = array($columns => $direction);
+		}
+		return $this;
+	}
+
+	/**
+	 * Limit rows returned
+	 *
+	 * @chainable
+	 * @param  int  Number of rows
+	 * @return Database_Builder
+	 */
+	public function limit($number)
+	{
+		$this->limit = (int) $number;
+
+		return $this;
+	}
+
+	/**
+	 * Offset into result set
+	 *
+	 * @chainable
+	 * @param  int  Offset
+	 * @return Database_Builder
+	 */
+	public function offset($number)
+	{
+		$this->offset = (int) $number;
+
+		return $this;
+	}
+
+	/**
+	 * Alias for [Database_Builder::and_open]
+	 *
+	 * @chainable
+	 * @param  string  Clause (WHERE OR HAVING)
+	 * @return Database_Builder
+	 */
+	public function open($clause = 'WHERE')
+	{
+		return $this->and_open($clause);
+	}
+
+	/**
+	 * Open new **ANDs** parenthesis set
+	 *
+	 * @chainable
+	 * @param  string  Clause (WHERE OR HAVING)
+	 * @return Database_Builder
+	 */
+	public function and_open($clause = 'WHERE')
+	{
+		if ($clause === 'WHERE')
+		{
+			$this->where[] = array('AND' => '(');
+		}
+		else
+		{
+			$this->having[] = array('AND' => '(');
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Open new **OR** parenthesis set
+	 *
+	 * @chainable
+	 * @param  string  Clause (WHERE OR HAVING)
+	 * @return Database_Builder
+	 */
+	public function or_open($clause = 'WHERE')
+	{
+		if ($clause === 'WHERE')
+		{
+			$this->where[] = array('OR' => '(');
+		}
+		else
+		{
+			$this->having[] = array('OR' => '(');
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Close close parenthesis set
+	 *
+	 * @chainable
+	 * @param  string  Clause (WHERE OR HAVING)
+	 * @return Database_Builder
+	 */
+	public function close($clause = 'WHERE')
+	{
+		if ($clause === 'WHERE')
+		{
+			$this->where[] = array(')');
+		}
+		else
+		{
+			$this->having[] = array(')');
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Set values for UPDATE
+	 *
+	 * @chainable
+	 * @param  mixed   Column name or array of columns => vals
+	 * @param  mixed   Value (can be a Database_Expression)
+	 * @return Database_Builder
+	 */
+	public function set($keys, $value = NULL)
+	{
+		if (is_string($keys))
+		{
+			$keys = array($keys => $value);
+		}
+
+		$this->set = array_merge($keys, $this->set);
+
+		return $this;
+	}
+
+	/**
+	 * Columns used for INSERT queries
+	 *
+	 * @chainable
+	 * @param  array  Columns
+	 * @return Database_Builder
+	 */
+	public function columns($columns)
+	{
+		if ( ! is_array($columns))
+		{
+			$columns = func_get_args();
+		}
+
+		$this->columns = $columns;
+
+		return $this;
+	}
+
+	/**
+	 * Values used for INSERT queries
+	 *
+	 * @chainable
+	 * @param  array  Values
+	 * @return Database_Builder
+	 */
+	public function values($values)
+	{
+		if ( ! is_array($values))
+		{
+			$values = func_get_args();
+		}
+
+		$this->values[] = $values;
+
+		return $this;
+	}
+
+	/**
+	 * Set caching for the query
+	 *
+	 * @chainable
+	 * @param  mixed  Time-to-live (FALSE to disable, NULL for Cache default, seconds otherwise)
+	 * @return Database_Builder
+	 */
+	public function cache($ttl = NULL)
+	{
+		$this->ttl = $ttl;
+
+		return $this;
+	}
+
+	/**
+	 * Resets the database builder after execution. By default after you `execute()` a query
+	 * the database builder will reset to its default state. You can use `reset(FALSE)`
+	 * to stop this from happening. This is useful for pagination when you might want to
+	 * apply a limit to the previous query.
+	 *
+	 * ##### Example
+	 *
+	 *     $db = new Database_Builder;
+	 *     $all_results = $db->select()
+	 *                        ->where('id', '=', 3)
+	 *                        ->from('products')
+	 *                        ->reset(FALSE)
+	 *                        ->execute();
+	 *
+	 *     // Run the query again with a limit of 10
+	 *     $ten_results = $db->limit(10)
+	 *                       ->execute();
+	 * @chainable
+	 * @param   bool reset builder
+	 * @return  Database_Builder
+	 */
+	public function reset($reset = TRUE)
+	{
+		$this->reset = (bool) $reset;
+		return $this;
+	}
+
+	/**
+	 * Compiles the given clause's conditions
+	 *
+	 * @param  array  Clause conditions
+	 * @return string
+	 */
+	protected function compile_conditions($groups)
+	{
+		$last_condition = NULL;
+
+		$sql = '';
+		foreach ($groups as $group)
+		{
+			// Process groups of conditions
+			foreach ($group as $logic => $condition)
+			{
+				if ($condition === '(')
+				{
+					if ( ! empty($sql) AND $last_condition !== '(')
+					{
+						// Include logic operator
+						$sql .= ' '.$logic.' ';
+					}
+
+					$sql .= '(';
+				}
+				elseif ($condition === ')')
+				{
+					$sql .= ')';
+				}
+				else
+				{
+					list($columns, $op, $value) = $condition;
+
+					// Stores each individual condition
+					$vals = array();
+
+					if ($columns instanceof Database_Expression)
+					{
+						// Add directly to condition list
+						$vals[] = (string) $columns;
+					}
+					else
+					{
+						$op = strtoupper($op);
+
+						if ( ! is_array($columns))
+						{
+							$columns = array($columns => $value);
+						}
+
+						foreach ($columns as $column => $value)
+						{
+							if ($value instanceof Database_Builder)
+							{
+								// Using a subquery
+								$value->db = $this->db;
+								$value = '('.(string) $value.')';
+							}
+							elseif (is_array($value))
+							{
+								if ($op === 'BETWEEN' OR $op === 'NOT BETWEEN')
+								{
+									// Falls between two values
+									$value = $this->db->quote($value[0]).' AND '.$this->db->quote($value[1]);
+								}
+								else
+								{
+									// Return as list
+									$value = array_map(array($this->db, 'quote'), $value);
+									$value = '('.implode(', ', $value).')';
+								}
+							}
+							else
+							{
+								$value = $this->db->quote($value);
+							}
+
+							if ( ! empty($column))
+							{
+								// Ignore blank columns
+								$column = $this->db->quote_column($column);
+							}
+
+							// Add to condition list
+							$vals[] = $column.' '.$op.' '.$value;
+						}
+					}
+
+					if ( ! empty($sql) AND $last_condition !== '(')
+					{
+						// Add the logic operator
+						$sql .= ' '.$logic.' ';
+					}
+
+					// Join the condition list items together by the given logic operator
+					$sql .= implode(' '.$logic.' ', $vals);
+				}
+
+				$last_condition = $condition;
+			}
+		}
+
+		return $sql;
+	}
+
+	/**
+	 * Compiles the columns portion of the query for INSERT
+	 *
+	 * @return string
+	 */
+	protected function compile_columns()
+	{
+		return '('.implode(', ', array_map(array($this->db, 'quote_column'), $this->columns)).')';
+	}
+
+	/**
+	 * Compiles the VALUES portion of the query for INSERT
+	 *
+	 * @return string
+	 */
+	protected function compile_values()
+	{
+		$values = array();
+		foreach ($this->values as $group)
+		{
+			// Each set of values to be inserted
+			$values[] = '('.implode(', ', array_map(array($this->db, 'quote'), $group)).')';
+		}
+
+		return implode(', ', $values);
+	}
+
+	/**
+	 * Create an UPDATE query
+	 *
+	 * @chainable
+	 * @param  string  Table name
+	 * @param  array   Array of Keys => Values
+	 * @param  array   WHERE conditions
+	 * @return Database_Builder
+	 */
+	public function update($table = NULL, $set = NULL, $where = NULL)
+	{
+		$this->type = Database::UPDATE;
+
+		if (is_array($set))
+		{
+			$this->set($set);
+		}
+
+		if ($where !== NULL)
+		{
+			$this->where($where);
+		}
+
+		if ($table !== NULL)
+		{
+			$this->from($table);
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Create an INSERT query.  Use 'columns' and 'values' methods for multi-row inserts
+	 *
+	 * @chainable
+	 * @param  string  Table name
+	 * @param  array   Array of Keys => Values
+	 * @return Database_Builder
+	 */
+	public function insert($table = NULL, $set = NULL)
+	{
+		$this->type = Database::INSERT;
+
+		if (is_array($set))
+		{
+			$this->columns(array_keys($set));
+			$this->values(array_values($set));
+		}
+
+		if ($table !== NULL)
+		{
+			$this->from($table);
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Create a DELETE query
+	 *
+	 * @chainable
+	 * @param  string  Table name
+	 * @param  array   WHERE conditions
+	 * @return Database_Builder
+	 */
+	public function delete($table, $where = NULL)
+	{
+		$this->type = Database::DELETE;
+
+		if ($where !== NULL)
+		{
+			$this->where($where);
+		}
+
+		if ($table !== NULL)
+		{
+			$this->from($table);
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Count records for a given table
+	 *
+	 * @param  string  Table name
+	 * @param  array   WHERE conditions
+	 * @return int
+	 */
+	public function count_records($table = FALSE, $where = NULL)
+	{
+		if (count($this->from) < 1)
+		{
+			if ($table === FALSE)
+				throw new Database_Exception('Database count_records requires a table');
+
+			$this->from($table);
+		}
+
+		if ($where !== NULL)
+		{
+			$this->where($where);
+		}
+
+		// Grab the count AS records_found
+		$result = $this->select(array('records_found' => 'COUNT("*")'))->execute();
+
+		return $result->get('records_found');
+	}
+
+	/**
+	 * Executes the built query
+	 *
+	 * @param  mixed  Database name or object
+	 * @return Database_Result
+	 */
+	public function execute($db = NULL)
+	{
+		if ($db !== NULL)
+		{
+			$this->db = $db;
+		}
+
+		if ( ! is_object($this->db))
+		{
+			// Get the database instance
+			$this->db = Database::instance($this->db);
+		}
+
+		$query = $this->compile();
+
+		if ($this->reset)
+		{
+			// Reset the query after executing
+			$this->_reset();
+		}
+
+		if ($this->ttl !== FALSE AND $this->type === Database::SELECT)
+		{
+			// Return result from cache (only allowed with SELECT)
+			return $this->db->query_cache($query, $this->ttl);
+		}
+		else
+		{
+			// Load the result (no caching)
+			return $this->db->query($query);
+		}
+	}
+
+	/**
+	 * Compiles the builder object into a SQL query
+	 *
+	 * @return  string Compiled query
+	 */
+	protected function compile()
+	{
+		if ( ! is_object($this->db))
+		{
+			// Use default database for compiling to string if none is given
+			$this->db = Database::instance($this->db);
+		}
+
+		if ($this->type === Database::SELECT)
+		{
+			// SELECT columns FROM table
+			$sql = $this->distinct ? 'SELECT DISTINCT ' : 'SELECT ';
+			$sql .= $this->compile_select();
+
+			if ( ! empty($this->from))
+			{
+				$sql .= "\nFROM ".$this->compile_from();
+			}
+		}
+		elseif ($this->type === Database::UPDATE)
+		{
+			$sql = 'UPDATE '.$this->compile_from()."\n".'SET '.$this->compile_set();
+		}
+		elseif ($this->type === Database::INSERT)
+		{
+			$sql = 'INSERT INTO '.$this->compile_from()."\n".$this->compile_columns()."\nVALUES ".$this->compile_values();
+		}
+		elseif ($this->type === Database::DELETE)
+		{
+			$sql = 'DELETE FROM '.$this->compile_from();
+		}
+
+		if ( ! empty($this->join))
+		{
+			$sql .= $this->compile_join();
+		}
+
+		if ( ! empty($this->where))
+		{
+			$sql .= "\n".'WHERE '.$this->compile_conditions($this->where);
+		}
+
+		if ( ! empty($this->group_by))
+		{
+			$sql .= "\n".'GROUP BY '.$this->compile_group_by();
+		}
+
+		if ( ! empty($this->having))
+		{
+			$sql .= "\n".'HAVING '.$this->compile_conditions($this->having);
+		}
+
+		if ( ! empty($this->order_by))
+		{
+			$sql .= "\nORDER BY ".$this->compile_order_by();
+		}
+
+		if (is_int($this->limit))
+		{
+			$sql .= "\nLIMIT ".$this->limit;
+		}
+
+		if (is_int($this->offset))
+		{
+			$sql .= "\nOFFSET ".$this->offset;
+		}
+
+		return $sql;
+	}
+
+	/**
+	 * Compiles the SELECT portion of the query
+	 *
+	 * @return string
+	 */
+	protected function compile_select()
+	{
+		$vals = array();
+
+		foreach ($this->select as $alias => $name)
+		{
+			if ($name instanceof Database_Builder)
+			{
+				// Using a subquery
+				$name->db = $this->db;
+				$vals[] = '('.(string) $name.') AS '.$this->db->quote_column($alias);
+			}
+			elseif (is_string($alias))
+			{
+				$vals[] = $this->db->quote_column($name, $alias);
+			}
+			else
+			{
+				$vals[] = $this->db->quote_column($name);
+			}
+		}
+
+		return implode(', ', $vals);
+	}
+
+	/**
+	 * Compiles the FROM portion of the query
+	 *
+	 * @return string
+	 */
+	protected function compile_from()
+	{
+		$vals = array();
+
+		foreach ($this->from as $alias => $name)
+		{
+			if (is_string($alias))
+			{
+				// Using AS format so escape both
+				$vals[] = $this->db->quote_table($name, $alias);
+			}
+			else
+			{
+				// Just using the table name itself
+				$vals[] = $this->db->quote_table($name);
+			}
+		}
+
+		return implode(', ', $vals);
+	}
+
+	/**
+	 * Compiles the JOIN portion of the query
+	 *
+	 * @return string
+	 */
+	protected function compile_join()
+	{
+		$sql = '';
+		foreach ($this->join as $join)
+		{
+			list($table, $keys, $type) = $join;
+
+			if ($type !== NULL)
+			{
+				// Join type
+				$sql .= ' '.$type;
+			}
+
+			$sql .= ' JOIN '.$this->db->quote_table($table);
+
+			$condition = '';
+			if ($keys instanceof Database_Expression)
+			{
+				$condition = (string) $keys;
+			}
+			elseif (is_array($keys))
+			{
+				// ON condition is an array of matches
+				foreach ($keys as $key => $value)
+				{
+					if ( ! empty($condition))
+					{
+						$condition .= ' AND ';
+					}
+
+					$condition .= $this->db->quote_column($key).' = '.$this->db->quote_column($value);
+				}
+			}
+
+			if ( ! empty($condition))
+			{
+				// Add ON condition
+				$sql .= ' ON ('.$condition.')';
+			}
+		}
+
+		return $sql;
+	}
+
+	/**
+	 * Compiles the GROUP BY portion of the query
+	 *
+	 * @return string
+	 */
+	protected function compile_group_by()
+	{
+		$vals = array();
+
+		foreach ($this->group_by as $column)
+		{
+			// Escape the column
+			$vals[] = $this->db->quote_column($column);
+		}
+
+		return implode(', ', $vals);
+	}
+
+	/**
+	 * Compiles the ORDER BY portion of the query
+	 *
+	 * @return string
+	 */
+	protected function compile_order_by()
+	{
+		$ordering = array();
+
+		foreach ($this->order_by as $column => $order_by)
+		{
+			list($column, $direction) = each($order_by);
+
+			$column = $this->db->quote_column($column);
+
+			if ($direction !== NULL)
+			{
+				$direction = ' '.$direction;
+			}
+
+			$ordering[] = $column.$direction;
+		}
+
+		return implode(', ', $ordering);
+	}
+
+	/**
+	 * Compiles the SET portion of the query for UPDATE
+	 *
+	 * @return string
+	 */
+	protected function compile_set()
+	{
+		$vals = array();
+
+		foreach ($this->set as $key => $value)
+		{
+			// Using an UPDATE so Key = Val
+			$vals[] = $this->db->quote_column($key).' = '.$this->db->quote($value);
+		}
+
+		return implode(', ', $vals);
+	}
+
+	/**
+	 * Resets all query components
+	 */
+	protected function _reset()
+	{
+		$this->select   = array();
+		$this->from     = array();
+		$this->join     = array();
+		$this->where    = array();
+		$this->group_by = array();
+		$this->having   = array();
+		$this->order_by = array();
+		$this->limit    = NULL;
+		$this->offset   = NULL;
+		$this->set      = array();
+		$this->values   = array();
+		$this->type     = NULL;
+		$this->distinct = FALSE;
+		$this->reset    = TRUE;
+		$this->ttl      = FALSE;
+	}
+
+} // End Database_Builder
diff --git a/system/libraries/Database_Cache_Result.php b/system/libraries/Database_Cache_Result.php
new file mode 100644
index 0000000..3945c42
--- /dev/null
+++ b/system/libraries/Database_Cache_Result.php
@@ -0,0 +1,81 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Cached database result.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Database_Cache_Result_Core extends Database_Result {
+
+	/**
+	 * Result data (array of rows)
+	 * @var array
+	 */
+	protected $data;
+
+	public function __construct($data, $sql, $return_objects)
+	{
+		$this->data           = $data;
+		$this->sql            = $sql;
+		$this->total_rows     = count($data);
+		$this->return_objects = $return_objects;
+	}
+
+	public function __destruct()
+	{
+		// Not used
+	}
+
+	public function as_array($return = FALSE)
+	{
+		// Return arrays rather than objects
+		$this->return_objects = FALSE;
+
+		if ( ! $return )
+		{
+			// Return this result object
+			return $this;
+		}
+
+		// Return the entire array of rows
+		return $this->data;
+	}
+
+	public function as_object($class = NULL, $return = FALSE)
+	{
+		if ($class !== NULL)
+			throw new Database_Exception('Database cache results do not support object casting');
+
+		// Return objects of type $class (or stdClass if none given)
+		$this->return_objects = TRUE;
+
+		return $this;
+	}
+
+	public function seek($offset)
+	{
+		if ( ! $this->offsetExists($offset))
+			return FALSE;
+
+		$this->current_row = $offset;
+
+		return TRUE;
+	}
+
+	public function current()
+	{
+		if ($this->return_objects)
+		{
+			// Return a new object with the current row of data
+			return (object) $this->data[$this->current_row];
+		}
+		else
+		{
+			// Return an array of the row
+			return $this->data[$this->current_row];
+		}
+	}
+
+} // End Database_Cache_Result
\ No newline at end of file
diff --git a/system/libraries/Database_Exception.php b/system/libraries/Database_Exception.php
new file mode 100644
index 0000000..0f6bb75
--- /dev/null
+++ b/system/libraries/Database_Exception.php
@@ -0,0 +1,15 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Database exceptions.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Database_Exception_Core extends Kohana_Exception {
+
+	// Database error code
+	protected $code = E_DATABASE_ERROR;
+
+} // End Database_Exception
\ No newline at end of file
diff --git a/system/libraries/Database_Expression.php b/system/libraries/Database_Expression.php
new file mode 100644
index 0000000..007a0cb
--- /dev/null
+++ b/system/libraries/Database_Expression.php
@@ -0,0 +1,23 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Database expression.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Database_Expression_Core {
+
+	protected $expression;
+
+	public function __construct($expression)
+	{
+		$this->expression = $expression;
+	}
+
+	public function __toString()
+	{
+		return $this->expression;
+	}
+}
diff --git a/system/libraries/Database_Mysql.php b/system/libraries/Database_Mysql.php
new file mode 100644
index 0000000..a325cbc
--- /dev/null
+++ b/system/libraries/Database_Mysql.php
@@ -0,0 +1,226 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * MySQL database connection.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Database_Mysql_Core extends Database {
+
+	// Quote character to use for identifiers (tables/columns/aliases)
+	protected $quote = '`';
+
+	// Use SET NAMES to set the character set
+	protected static $set_names;
+
+	public function connect()
+	{
+		if ($this->connection)
+			return;
+
+		if (Database_Mysql::$set_names === NULL)
+		{
+			// Determine if we can use mysql_set_charset(), which is only
+			// available on PHP 5.2.3+ when compiled against MySQL 5.0+
+			Database_Mysql::$set_names = ! function_exists('mysql_set_charset');
+		}
+
+		extract($this->config['connection']);
+
+		$host = isset($host) ? $host : $socket;
+		$port = isset($port) ? ':'.$port : '';
+
+		try
+		{
+			// Connect to the database
+			$this->connection = ($this->config['persistent'] === TRUE)
+				? mysql_pconnect($host.$port, $user, $pass, $params)
+				: mysql_connect($host.$port, $user, $pass, TRUE, $params);
+		}
+		catch (Kohana_PHP_Exception $e)
+		{
+			// No connection exists
+			$this->connection = NULL;
+
+			// Unable to connect to the database
+			throw new Database_Exception('#:errno: :error',
+				array(':error' => mysql_error(),
+				':errno' => mysql_errno()));
+		}
+
+		if ( ! mysql_select_db($database, $this->connection))
+		{
+			// Unable to select database
+			throw new Database_Exception('#:errno: :error',
+				array(':error' => mysql_error($this->connection),
+				':errno' => mysql_errno($this->connection)));
+		}
+
+		if (isset($this->config['character_set']))
+		{
+			// Set the character set
+			$this->set_charset($this->config['character_set']);
+		}
+	}
+
+	public function disconnect()
+	{
+		try
+		{
+			// Database is assumed disconnected
+			$status = TRUE;
+
+			if (is_resource($this->connection))
+			{
+				$status = mysql_close($this->connection);
+			}
+		}
+		catch (Exception $e)
+		{
+			// Database is probably not disconnected
+			$status = is_resource($this->connection);
+		}
+
+		return $status;
+	}
+
+	public function set_charset($charset)
+	{
+		// Make sure the database is connected
+		$this->connection or $this->connect();
+
+		if (Database_Mysql::$set_names === TRUE)
+		{
+			// PHP is compiled against MySQL 4.x
+			$status = (bool) mysql_query('SET NAMES '.$this->quote($charset), $this->connection);
+		}
+		else
+		{
+			// PHP is compiled against MySQL 5.x
+			$status = mysql_set_charset($charset, $this->connection);
+		}
+
+		if ($status === FALSE)
+		{
+			// Unable to set charset
+			throw new Database_Exception('#:errno: :error',
+				array(':error' => mysql_error($this->connection),
+				':errno' => mysql_errno($this->connection)));
+		}
+	}
+
+	public function query_execute($sql)
+	{
+		// Make sure the database is connected
+		$this->connection or $this->connect();
+
+		$result = mysql_query($sql, $this->connection);
+
+		// Set the last query
+		$this->last_query = $sql;
+
+		return new Database_Mysql_Result($result, $sql, $this->connection, $this->config['object']);
+	}
+
+	public function escape($value)
+	{
+		// Make sure the database is connected
+		$this->connection or $this->connect();
+
+		if (($value = mysql_real_escape_string($value, $this->connection)) === FALSE)
+		{
+			throw new Database_Exception('#:errno: :error',
+				array(':error' => mysql_error($this->connection),
+				':errno' => mysql_errno($this->connection)));
+		}
+
+		return $value;
+	}
+
+	public function list_constraints($table)
+	{
+		$prefix = strlen($this->table_prefix());
+		$result = array();
+
+		$constraints = $this->query('
+			SELECT c.constraint_name, c.constraint_type, k.column_name, k.referenced_table_name, k.referenced_column_name
+			FROM information_schema.table_constraints c
+			JOIN information_schema.key_column_usage k ON (k.table_schema = c.table_schema AND k.table_name = c.table_name AND k.constraint_name = c.constraint_name)
+			WHERE c.table_schema = '.$this->quote($this->config['connection']['database']).'
+				AND c.table_name = '.$this->quote($this->table_prefix().$table).'
+				AND (k.referenced_table_schema IS NULL OR k.referenced_table_schema ='.$this->quote($this->config['connection']['database']).')
+			ORDER BY k.ordinal_position
+		');
+
+		foreach ($constraints->as_array() as $row)
+		{
+			switch ($row['constraint_type'])
+			{
+				case 'FOREIGN KEY':
+					if (isset($result[$row['constraint_name']]))
+					{
+						$result[$row['constraint_name']][1][] = $row['column_name'];
+						$result[$row['constraint_name']][3][] = $row['referenced_column_name'];
+					}
+					else
+					{
+						$result[$row['constraint_name']] = array($row['constraint_type'], array($row['column_name']), substr($row['referenced_table_name'], $prefix), array($row['referenced_column_name']));
+					}
+				break;
+				case 'PRIMARY KEY':
+				case 'UNIQUE':
+					if (isset($result[$row['constraint_name']]))
+					{
+						$result[$row['constraint_name']][1][] = $row['column_name'];
+					}
+					else
+					{
+						$result[$row['constraint_name']] = array($row['constraint_type'], array($row['column_name']));
+					}
+				break;
+			}
+		}
+
+		return $result;
+	}
+
+	public function list_fields($table)
+	{
+		$result = array();
+
+		foreach ($this->query('SHOW COLUMNS FROM '.$this->quote_table($table))->as_array() as $row)
+		{
+			$column = $this->sql_type($row['Type']);
+
+			$column['default'] = $row['Default'];
+			$column['nullable'] = $row['Null'] === 'YES';
+			$column['sequenced'] = $row['Extra'] === 'auto_increment';
+
+			if (isset($column['length']) AND $column['type'] === 'float')
+			{
+				list($column['precision'], $column['scale']) = explode(',', $column['length']);
+			}
+
+			$result[$row['Field']] = $column;
+		}
+
+		return $result;
+	}
+
+	public function list_tables()
+	{
+		$prefix = strlen($this->table_prefix());
+		$tables = array();
+
+		foreach ($this->query('SHOW TABLES LIKE '.$this->quote($this->table_prefix().'%'))->as_array() as $row)
+		{
+			// The value is the table name
+			$tables[] = substr(current($row), $prefix);
+		}
+
+		return $tables;
+	}
+
+} // End Database_MySQL
diff --git a/system/libraries/Database_Mysql_Result.php b/system/libraries/Database_Mysql_Result.php
new file mode 100644
index 0000000..0f89898
--- /dev/null
+++ b/system/libraries/Database_Mysql_Result.php
@@ -0,0 +1,174 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * MySQL database result.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Database_Mysql_Result_Core extends Database_Result {
+
+	protected $internal_row = 0;
+
+	public function __construct($result, $sql, $link, $return_objects)
+	{
+		if (is_resource($result))
+		{
+			// True to return objects, false for arrays
+			$this->return_objects = $return_objects;
+
+			$this->total_rows = mysql_num_rows($result);
+		}
+		elseif (is_bool($result))
+		{
+			if ($result == FALSE)
+			{
+				throw new Database_Exception('#:errno: :error [ :query ]',
+					array(':error' => mysql_error($link),
+					':query' => $sql,
+					':errno' => mysql_errno($link)));
+
+			}
+			else
+			{
+				// It's a DELETE, INSERT, REPLACE, or UPDATE query
+				$this->insert_id  = mysql_insert_id($link);
+				$this->total_rows = mysql_affected_rows($link);
+			}
+		}
+
+		// Store the result locally
+		$this->result = $result;
+
+		$this->sql = $sql;
+	}
+
+	public function __destruct()
+	{
+		if (is_resource($this->result))
+		{
+			mysql_free_result($this->result);
+		}
+	}
+
+	public function as_array($return = FALSE)
+	{
+		// Return arrays rather than objects
+		$this->return_objects = FALSE;
+
+		if ( ! $return )
+		{
+			// Return this result object
+			return $this;
+		}
+
+		// Return a nested array of all results
+		$array = array();
+
+		if ($this->total_rows > 0)
+		{
+			// Seek to the beginning of the result
+			mysql_data_seek($this->result, 0);
+
+			while ($row = mysql_fetch_assoc($this->result))
+			{
+				// Add each row to the array
+				$array[] = $row;
+			}
+
+			$this->internal_row = $this->total_rows;
+		}
+
+		return $array;
+	}
+
+	public function as_object($class = NULL, $return = FALSE)
+	{
+		// Return objects of type $class (or stdClass if none given)
+		$this->return_objects = ($class !== NULL) ? $class : TRUE;
+
+		if ( ! $return )
+		{
+			// Return this result object
+			return $this;
+		}
+
+		// Return a nested array of all results
+		$array = array();
+
+		if ($this->total_rows > 0)
+		{
+			// Seek to the beginning of the result
+			mysql_data_seek($this->result, 0);
+
+			if (is_string($this->return_objects))
+			{
+				while ($row = mysql_fetch_object($this->result, $this->return_objects))
+				{
+					// Add each row to the array
+					$array[] = $row;
+				}
+			}
+			else
+			{
+				while ($row = mysql_fetch_object($this->result))
+				{
+					// Add each row to the array
+					$array[] = $row;
+				}
+			}
+
+			$this->internal_row = $this->total_rows;
+		}
+
+		return $array;
+	}
+
+	/**
+	 * SeekableIterator: seek
+	 */
+	public function seek($offset)
+	{
+		if ($this->offsetExists($offset) AND mysql_data_seek($this->result, $offset))
+		{
+			// Set the current row to the offset
+			$this->current_row = $this->internal_row = $offset;
+
+			return TRUE;
+		}
+		else
+		{
+			return FALSE;
+		}
+	}
+
+	/**
+	 * Iterator: current
+	 */
+	public function current()
+	{
+		if ($this->current_row !== $this->internal_row AND ! $this->seek($this->current_row))
+			return NULL;
+
+		++$this->internal_row;
+
+		if ($this->return_objects)
+		{
+			if (is_string($this->return_objects))
+			{
+				return mysql_fetch_object($this->result, $this->return_objects);
+			}
+			else
+			{
+				return mysql_fetch_object($this->result);
+			}
+		}
+		else
+		{
+			// Return an array of the row
+			return mysql_fetch_assoc($this->result);
+		}
+	}
+
+} // End Database_MySQL_Result
\ No newline at end of file
diff --git a/system/libraries/Database_Mysqli.php b/system/libraries/Database_Mysqli.php
new file mode 100644
index 0000000..41b635d
--- /dev/null
+++ b/system/libraries/Database_Mysqli.php
@@ -0,0 +1,90 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * MySQL database connection.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+define('RUNS_MYSQLND', function_exists('mysqli_fetch_all'));
+
+class Database_Mysqli_Core extends Database_Mysql {
+
+	public function connect()
+	{
+		if (is_object($this->connection))
+			return;
+
+		extract($this->config['connection']);
+
+		// Persistent connections are supported as of PHP 5.3
+		if (RUNS_MYSQLND AND $this->config['persistent'] === TRUE)
+		{
+			$host = 'p:'.$host;
+		}
+
+		$host = isset($host) ? $host : $socket;
+
+		$mysqli = mysqli_init();
+
+		if ( ! $mysqli->real_connect($host, $user, $pass, $database, $port, $socket, $params))
+			throw new Database_Exception('#:errno: :error',
+				array(':error' => $mysqli->connect_error, ':errno' => $mysqli->connect_errno));
+
+		$this->connection = $mysqli;
+
+		if (isset($this->config['character_set']))
+		{
+			// Set the character set
+			$this->set_charset($this->config['character_set']);
+		}
+	}
+
+	public function disconnect()
+	{
+		if (is_object($this->connection))
+		{
+			$this->connection->close();
+		}
+
+		$this->connection = NULL;
+	}
+
+	public function set_charset($charset)
+	{
+		// Make sure the database is connected
+		is_object($this->connection) or $this->connect();
+
+		if ( ! $this->connection->set_charset($charset))
+		{
+			// Unable to set charset
+			throw new Database_Exception('#:errno: :error',
+				array(':error' => $this->connection->connect_error,
+				':errno' => $this->connection->connect_errno));
+		}
+	}
+
+	public function query_execute($sql)
+	{
+		// Make sure the database is connected
+		is_object($this->connection) or $this->connect();
+
+		$result = $this->connection->query($sql);
+
+		// Set the last query
+		$this->last_query = $sql;
+
+		return new Database_Mysqli_Result($result, $sql, $this->connection, $this->config['object']);
+	}
+
+	public function escape($value)
+	{
+		// Make sure the database is connected
+		is_object($this->connection) or $this->connect();
+
+		return $this->connection->real_escape_string($value);
+	}
+
+} // End Database_MySQLi
diff --git a/system/libraries/Database_Mysqli_Result.php b/system/libraries/Database_Mysqli_Result.php
new file mode 100644
index 0000000..f8b7b58
--- /dev/null
+++ b/system/libraries/Database_Mysqli_Result.php
@@ -0,0 +1,175 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * MySQL database result.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Database_Mysqli_Result_Core extends Database_Result {
+
+	protected $internal_row = 0;
+
+	public function __construct($result, $sql, $link, $return_objects)
+	{
+		if (is_object($result))
+		{
+			// True to return objects, false for arrays
+			$this->return_objects = $return_objects;
+
+			$this->total_rows = $result->num_rows;
+		}
+		elseif (is_bool($result))
+		{
+			if ($result == FALSE)
+			{
+				throw new Database_Exception('#:errno: :error [ :query ]',
+					array(':error' => $link->error,
+					':query' => $sql,
+					':errno' => $link->errno));
+			}
+			else
+			{
+				// It's a DELETE, INSERT, REPLACE, or UPDATE query
+				$this->insert_id = $link->insert_id;
+				$this->total_rows = $link->affected_rows;
+			}
+		}
+
+		// Store the result locally
+		$this->result = $result;
+
+		$this->sql = $sql;
+	}
+
+	public function __destruct()
+	{
+		if (is_object($this->result))
+		{
+			$this->result->free();
+		}
+	}
+
+	public function as_array($return = FALSE)
+	{
+		// Return arrays rather than objects
+		$this->return_objects = FALSE;
+
+		if ( ! $return )
+		{
+			// Return this result object
+			return $this;
+		}
+
+		// Return a nested array of all results
+		if (RUNS_MYSQLND)
+			return $this->result->fetch_all(MYSQLI_ASSOC);
+
+		$array = array();
+
+		if ($this->total_rows > 0)
+		{
+			// Seek to the beginning of the result
+			$this->result->data_seek(0);
+
+			while ($row = $this->result->fetch_assoc())
+			{
+				// Add each row to the array
+				$array[] = $row;
+			}
+			$this->internal_row = $this->total_rows;
+		}
+
+		return $array;
+	}
+
+	public function as_object($class = NULL, $return = FALSE)
+	{
+		// Return objects of type $class (or stdClass if none given)
+		$this->return_objects = ($class !== NULL) ? $class : TRUE;
+
+		if ( ! $return )
+		{
+			// Return this result object
+			return $this;
+		}
+
+		// Return a nested array of all results
+		$array = array();
+
+		if ($this->total_rows > 0)
+		{
+			// Seek to the beginning of the result
+			$this->result->data_seek(0);
+
+			if (is_string($this->return_objects))
+			{
+				while ($row = $this->result->fetch_object($this->return_objects))
+				{
+					// Add each row to the array
+					$array[] = $row;
+				}
+			}
+			else
+			{
+				while ($row = $this->result->fetch_object())
+				{
+					// Add each row to the array
+					$array[] = $row;
+				}
+			}
+
+			$this->internal_row = $this->total_rows;
+		}
+
+		return $array;
+	}
+
+	/**
+	 * SeekableIterator: seek
+	 */
+	public function seek($offset)
+	{
+		if ($this->offsetExists($offset) AND $this->result->data_seek($offset))
+		{
+			// Set the current row to the offset
+			$this->current_row = $offset;
+
+			return TRUE;
+		}
+		else
+		{
+			return FALSE;
+		}
+	}
+
+	/**
+	 * Iterator: current
+	 */
+	public function current()
+	{
+		if ($this->current_row !== $this->internal_row AND ! $this->seek($this->current_row))
+			return NULL;
+
+		++$this->internal_row;
+
+		if ($this->return_objects)
+		{
+			if (is_string($this->return_objects))
+			{
+				return $this->result->fetch_object($this->return_objects);
+			}
+			else
+			{
+				return $this->result->fetch_object();
+			}
+		}
+		else
+		{
+			// Return an array of the row
+			return $this->result->fetch_assoc();
+		}
+	}
+
+} // End Database_MySQLi_Result
\ No newline at end of file
diff --git a/system/libraries/Database_Query.php b/system/libraries/Database_Query.php
new file mode 100644
index 0000000..d9399d6
--- /dev/null
+++ b/system/libraries/Database_Query.php
@@ -0,0 +1,95 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Database query wrapper.
+ * 
+ * $Id: Database_Query.php 4679 2009-11-10 01:45:52Z isaiah $
+ * 
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Database_Query_Core {
+
+	protected $sql;
+	protected $params;
+	protected $ttl = FALSE;
+
+	public function __construct($sql = NULL)
+	{
+		$this->sql = $sql;
+	}
+
+	public function __toString()
+	{
+		// Return the SQL of this query
+		return $this->sql;
+	}
+
+	public function sql($sql)
+	{
+		$this->sql = $sql;
+
+		return $this;
+	}
+
+	public function value($key, $value)
+	{
+		$this->params[$key] = $value;
+
+		return $this;
+	}
+
+	public function bind($key, & $value)
+	{
+		$this->params[$key] =& $value;
+
+		return $this;
+	}
+
+	public function execute($db = 'default')
+	{
+		if ( ! is_object($db))
+		{
+			// Get the database instance
+			$db = Database::instance($db);
+		}
+
+		// Import the SQL locally
+		$sql = $this->sql;
+
+		if ( ! empty($this->params))
+		{
+			// Quote all of the values
+			$params = array_map(array($db, 'quote'), $this->params);
+
+			// Replace the values in the SQL
+			$sql = strtr($sql, $params);
+		}
+
+		if ($this->ttl !== FALSE)
+		{
+			// Load the result from the cache
+			return $db->query_cache($sql, $this->ttl);
+		}
+		else
+		{
+			// Load the result (no caching)
+			return $db->query($sql);
+		}
+	}
+
+	/**
+	 * Set caching for the query
+	 *
+	 * @param  mixed  Time-to-live (FALSE to disable, NULL for Cache default, seconds otherwise)
+	 * @return Database_Query
+	 */
+	public function cache($ttl = NULL)
+	{
+		$this->ttl = $ttl;
+
+		return $this;
+	}
+
+} // End Database_Query
\ No newline at end of file
diff --git a/system/libraries/Database_Result.php b/system/libraries/Database_Result.php
new file mode 100644
index 0000000..cf2056f
--- /dev/null
+++ b/system/libraries/Database_Result.php
@@ -0,0 +1,170 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Database result wrapper.
+ * 
+ * $Id: Database_Result.php 4679 2009-11-10 01:45:52Z isaiah $
+ * 
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+abstract class Database_Result_Core implements Countable, Iterator, SeekableIterator, ArrayAccess {
+
+	protected $result;
+
+	protected $total_rows  = 0;
+	protected $current_row = 0;
+	protected $insert_id;
+
+	// Return objects or arrays for each row
+	protected $return_objects;
+
+	/**
+	 * Sets the total number of rows and stores the result locally.
+	 *
+	 * @param   mixed   $result query result
+	 * @param   boolean $return_objects True for results as objects, false for arrays
+	 * @return  void
+	 */
+	abstract public function __construct($result, $sql, $link, $return_objects);
+
+	/**
+	 * Result destruction cleans up all open result sets.
+	 */
+	abstract public function __destruct();
+
+	/**
+	 * Return arrays for reach result, or the entire set of results
+	 *
+	 * @param  boolean $return  True to return entire result array
+	 * @return Database_Result|array
+	 */
+	abstract public function as_array($return = FALSE);
+
+	/**
+	 * Returns objects for each result
+	 *
+	 * @param  string $class  Class name to return objects as or NULL for stdClass
+	 * @return Database_Result
+	 */
+	abstract public function as_object($class = NULL, $return = FALSE);
+
+	/**
+	 * Returns the insert id
+	 *
+	 * @return int
+	 */
+	public function insert_id()
+	{
+		return $this->insert_id;
+	}
+
+	/**
+	 * Return the named column from the current row.
+	 *
+	 * @param  string  Column name
+	 * @return mixed
+	 */
+	public function get($name)
+	{
+		// Get the current row
+		$row = $this->current();
+
+		if ( ! $this->return_objects)
+			return $row[$name];
+
+		return $row->$name;
+	}
+
+	/**
+	 * Countable: count
+	 */
+	public function count()
+	{
+		return $this->total_rows;
+	}
+
+	/**
+	 * ArrayAccess: offsetExists
+	 */
+	public function offsetExists($offset)
+	{
+		return ($offset >= 0 AND $offset < $this->total_rows);
+	}
+
+	/**
+	 * ArrayAccess: offsetGet
+	 */
+	public function offsetGet($offset)
+	{
+		if ( ! $this->seek($offset))
+			return NULL;
+
+		return $this->current();
+	}
+
+	/**
+	 * ArrayAccess: offsetSet
+	 *
+	 * @throws  Kohana_Database_Exception
+	 */
+	final public function offsetSet($offset, $value)
+	{
+		throw new Kohana_Exception('Database results are read-only');
+	}
+
+	/**
+	 * ArrayAccess: offsetUnset
+	 *
+	 * @throws  Kohana_Database_Exception
+	 */
+	final public function offsetUnset($offset)
+	{
+		throw new Kohana_Exception('Database results are read-only');
+	}
+
+	/**
+	 * Iterator: key
+	 */
+	public function key()
+	{
+		return $this->current_row;
+	}
+
+	/**
+	 * Iterator: next
+	 */
+	public function next()
+	{
+		++$this->current_row;
+		return $this;
+	}
+
+	/**
+	 * Iterator: prev
+	 */
+	public function prev()
+	{
+		--$this->current_row;
+		return $this;
+	}
+
+	/**
+	 * Iterator: rewind
+	 */
+	public function rewind()
+	{
+		$this->current_row = 0;
+		return $this;
+	}
+
+	/**
+	 * Iterator: valid
+	 */
+	public function valid()
+	{
+		return $this->offsetExists($this->current_row);
+	}
+
+} // End Database_Result
\ No newline at end of file
diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php
new file mode 100644
index 0000000..15d4087
--- /dev/null
+++ b/system/libraries/Encrypt.php
@@ -0,0 +1,176 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * The Encrypt library provides two-way encryption of text and binary strings
+ * using the MCrypt extension.
+ * @see http://php.net/mcrypt
+ *
+ * $Id: Encrypt.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Encrypt_Core {
+
+	// OS-dependant RAND type to use
+	protected static $rand;
+
+	// Configuration
+	protected $config;
+
+	/**
+	 * Returns a singleton instance of Encrypt.
+	 *
+	 * @param   array  configuration options
+	 * @return  Encrypt_Core
+	 */
+	public static function instance($config = NULL)
+	{
+		static $instance;
+
+		// Create the singleton
+		empty($instance) and $instance = new Encrypt((array) $config);
+
+		return $instance;
+	}
+
+	/**
+	 * Loads encryption configuration and validates the data.
+	 *
+	 * @param   array|string      custom configuration or config group name
+	 * @throws  Kohana_Exception
+	 */
+	public function __construct($config = FALSE)
+	{
+		if ( ! defined('MCRYPT_ENCRYPT'))
+			throw new Kohana_Exception('To use the Encrypt library, mcrypt must be enabled in your PHP installation');
+
+		if (is_string($config))
+		{
+			$name = $config;
+
+			// Test the config group name
+			if (($config = Kohana::config('encryption.'.$config)) === NULL)
+				throw new Kohana_Exception('The :name: group is not defined in your configuration.', array(':name:' => $name));
+		}
+
+		if (is_array($config))
+		{
+			// Append the default configuration options
+			$config += Kohana::config('encryption.default');
+		}
+		else
+		{
+			// Load the default group
+			$config = Kohana::config('encryption.default');
+		}
+
+		if (empty($config['key']))
+			throw new Kohana_Exception('To use the Encrypt library, you must set an encryption key in your config file');
+
+		// Find the max length of the key, based on cipher and mode
+		$size = mcrypt_get_key_size($config['cipher'], $config['mode']);
+
+		if (strlen($config['key']) > $size)
+		{
+			// Shorten the key to the maximum size
+			$config['key'] = substr($config['key'], 0, $size);
+		}
+
+		// Find the initialization vector size
+		$config['iv_size'] = mcrypt_get_iv_size($config['cipher'], $config['mode']);
+
+		// Cache the config in the object
+		$this->config = $config;
+
+		Kohana_Log::add('debug', 'Encrypt Library initialized');
+	}
+
+	/**
+	 * Encrypts a string and returns an encrypted string that can be decoded.
+	 *
+	 * @param   string  data to be encrypted
+	 * @return  string  encrypted data
+	 */
+	public function encode($data)
+	{
+		// Set the rand type if it has not already been set
+		if (Encrypt::$rand === NULL)
+		{
+			if (KOHANA_IS_WIN)
+			{
+				// Windows only supports the system random number generator
+				Encrypt::$rand = MCRYPT_RAND;
+			}
+			else
+			{
+				if (defined('MCRYPT_DEV_URANDOM'))
+				{
+					// Use /dev/urandom
+					Encrypt::$rand = MCRYPT_DEV_URANDOM;
+				}
+				elseif (defined('MCRYPT_DEV_RANDOM'))
+				{
+					// Use /dev/random
+					Encrypt::$rand = MCRYPT_DEV_RANDOM;
+				}
+				else
+				{
+					// Use the system random number generator
+					Encrypt::$rand = MCRYPT_RAND;
+				}
+			}
+		}
+
+		if (Encrypt::$rand === MCRYPT_RAND)
+		{
+			// The system random number generator must always be seeded each
+			// time it is used, or it will not produce true random results
+			mt_srand();
+		}
+
+		// Create a random initialization vector of the proper size for the current cipher
+		$iv = mcrypt_create_iv($this->config['iv_size'], Encrypt::$rand);
+
+		// Encrypt the data using the configured options and generated iv
+		$data = mcrypt_encrypt($this->config['cipher'], $this->config['key'], $data, $this->config['mode'], $iv);
+
+		// Use base64 encoding to convert to a string
+		return base64_encode($iv.$data);
+	}
+
+	/**
+	 * Decrypts an encoded string back to its original value.
+	 *
+	 * @param   string  encoded string to be decrypted
+	 * @return  string  decrypted data or FALSE if decryption fails
+	 */
+	public function decode($data)
+	{
+		// Convert the data back to binary
+		$data = base64_decode($data, TRUE);
+
+		if ( ! $data)
+		{
+			// Invalid base64 data
+			return FALSE;
+		}
+
+		// Extract the initialization vector from the data
+		$iv = substr($data, 0, $this->config['iv_size']);
+
+		if ($this->config['iv_size'] !== strlen($iv))
+		{
+			// The iv is not the correct size
+			return FALSE;
+		}
+
+		// Remove the iv from the data
+		$data = substr($data, $this->config['iv_size']);
+
+		// Return the decrypted data, trimming the \0 padding bytes from the end of the data
+		return rtrim(mcrypt_decrypt($this->config['cipher'], $this->config['key'], $data, $this->config['mode'], $iv), "\0");
+	}
+
+} // End Encrypt
diff --git a/system/libraries/I18n.php b/system/libraries/I18n.php
new file mode 100644
index 0000000..9401ddc
--- /dev/null
+++ b/system/libraries/I18n.php
@@ -0,0 +1,100 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Kohana I18N System
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+class I18n_Core
+{
+	protected static $locale;
+	// All the translations will be cached in here, after the first call of get_text()
+	protected static $translations = array();
+
+	public static function set_locale($locale)
+	{
+		// Reset the translations array
+		I18n::$translations = array();
+
+		I18n::$locale = $locale;
+	}
+
+
+	/**
+	 *
+	 * Returns the locale.
+	 * If $ext is true, the UTF8 extension gets returned as well, otherwise, just the language code.
+	 * Defaults to true.
+	 *
+	 * @return 							The locale
+	 * @param boolean $ext[optional]	Get the Extension?
+	 */
+	public static function get_locale($ext = true)
+	{
+		if($ext)
+			return I18n::$locale;
+		else
+			return arr::get(explode('.', I18n::$locale), 0);
+	}
+
+
+	/**
+	 *
+	 * Translates $string into language I18n::$locale and caches all found translations on the first call
+	 *
+	 * @return                 The translated String
+	 * @param string $string   The String to translate
+	 */
+	public static function get_text($string)
+	{
+		if ( ! I18n::$translations)
+		{
+			$locale = explode('_', I18n::get_locale(FALSE));
+
+			// Get the translation files
+			$translation_files = Kohana::find_file('i18n', $locale[0]);
+
+			if($local_translation_files = Kohana::find_file('i18n', $locale[0].'/'.$locale[1]))
+				$translation_files = array_merge($translation_files, $local_translation_files);
+
+			if ($translation_files)
+			{
+				// Merge the translations
+				foreach ($translation_files as $file)
+				{
+					include $file;
+					I18n::$translations = array_merge(I18n::$translations, $translations);
+				}
+			}
+		}
+
+		if (isset(I18n::$translations[$string]))
+			return I18n::$translations[$string];
+		else
+			return $string;
+	}
+}
+
+/**
+ * Loads the configured driver and validates it.
+ *
+ * @param   string  Text to output
+ * @param   array   Key/Value pairs of arguments to replace in the string
+ * @return  string  Translated text
+ */
+function __($string, $args = NULL)
+{
+	// KOHANA_LOCALE is the default locale, in which all of Kohana's __() calls are written in
+	if (I18n::get_locale() != Kohana::LOCALE)
+	{
+		$string = I18n::get_text($string);
+	}
+
+	if ($args === NULL)
+		return $string;
+
+	return strtr($string, $args);
+}
diff --git a/system/libraries/Image.php b/system/libraries/Image.php
new file mode 100644
index 0000000..991c8d5
--- /dev/null
+++ b/system/libraries/Image.php
@@ -0,0 +1,501 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Manipulate images using standard methods such as resize, crop, rotate, etc.
+ * This class must be re-initialized for every image you wish to manipulate.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Image_Core {
+
+	// Master Dimension
+	const NONE = 1;
+	const AUTO = 2;
+	const HEIGHT = 3;
+	const WIDTH = 4;
+
+	// Flip Directions
+	const HORIZONTAL = 5;
+	const VERTICAL = 6;
+
+	// Orientations
+	const PORTRAIT = 7;
+	const LANDSCAPE = 8;
+	const SQUARE    = 9;
+
+	// Allowed image types
+	public static $allowed_types = array
+	(
+		IMAGETYPE_GIF => 'gif',
+		IMAGETYPE_JPEG => 'jpg',
+		IMAGETYPE_PNG => 'png',
+		IMAGETYPE_TIFF_II => 'tiff',
+		IMAGETYPE_TIFF_MM => 'tiff',
+	);
+
+	// Driver instance
+	protected $driver;
+
+	// Driver actions
+	protected $actions = array();
+
+	// Reference to the current image filename
+	protected $image = '';
+
+	/**
+	 * Creates a new Image instance and returns it.
+	 *
+	 * @param   string   filename of image
+	 * @param   array    non-default configurations
+	 * @return  object
+	 */
+	public static function factory($image, $config = NULL)
+	{
+		return new Image($image, $config);
+	}
+
+	/**
+	 * Creates a new image editor instance.
+	 *
+	 * @throws  Kohana_Exception
+	 * @param   string   filename of image
+	 * @param   array    non-default configurations
+	 * @return  void
+	 */
+	public function __construct($image, $config = NULL)
+	{
+		static $check;
+
+		// Make the check exactly once
+		($check === NULL) and $check = function_exists('getimagesize');
+
+		if ($check === FALSE)
+			throw new Kohana_Exception('The Image library requires the getimagesize() PHP function, which is not available in your installation.');
+
+		// Check to make sure the image exists
+		if ( ! is_file($image))
+			throw new Kohana_Exception('The specified image, :image:, was not found. Please verify that images exist by using file_exists() before manipulating them.', array(':image:' => $image));
+
+		// Disable error reporting, to prevent PHP warnings
+		$ER = error_reporting(0);
+
+		// Fetch the image size and mime type
+		$image_info = getimagesize($image);
+
+		// Turn on error reporting again
+		error_reporting($ER);
+
+		// Make sure that the image is readable and valid
+		if ( ! is_array($image_info) OR count($image_info) < 3)
+			throw new Kohana_Exception('The file specified, :file:, is not readable or is not an image', array(':file:' => $image));
+
+		// Check to make sure the image type is allowed
+		if ( ! isset(Image::$allowed_types[$image_info[2]]))
+			throw new Kohana_Exception('The specified image, :type:, is not an allowed image type.', array(':type:' => $image));
+
+		// Image has been validated, load it
+		$this->image = array
+		(
+			'file' => str_replace('\\', '/', realpath($image)),
+			'width' => $image_info[0],
+			'height' => $image_info[1],
+			'type' => $image_info[2],
+			'ext' => Image::$allowed_types[$image_info[2]],
+			'mime' => $image_info['mime']
+		);
+
+		$this->determine_orientation();
+
+		// Load configuration
+		$this->config = (array) $config + Kohana::config('image');
+
+		// Set driver class name
+		$driver = 'Image_'.ucfirst($this->config['driver']).'_Driver';
+
+		// Load the driver
+		if ( ! Kohana::auto_load($driver))
+			throw new Kohana_Exception('The :driver: driver for the :library: library could not be found',
+									   array(':driver:' => $this->config['driver'], ':library:' => get_class($this)));
+
+		// Initialize the driver
+		$this->driver = new $driver($this->config['params']);
+
+		// Validate the driver
+		if ( ! ($this->driver instanceof Image_Driver))
+			throw new Kohana_Exception('The :driver: driver for the :library: library must implement the :interface: interface',
+									   array(':driver:' => $this->config['driver'], ':library:' => get_class($this), ':interface:' => 'Image_Driver'));
+	}
+
+	/**
+	 * Works out the correct orientation for the image
+	 *
+	 * @return  void
+	 */
+	protected function determine_orientation()
+	{
+		switch (TRUE)
+		{
+			case $this->image['height'] > $this->image['width']:
+				$orientation = Image::PORTRAIT;
+			break;
+
+			case $this->image['height'] < $this->image['width']:
+				$orientation = Image::LANDSCAPE;
+			break;
+
+			default:
+				$orientation = Image::SQUARE;
+		}
+
+		$this->image['orientation'] = $orientation;
+	}
+
+	/**
+	 * Handles retrieval of pre-save image properties
+	 *
+	 * @param   string  property name
+	 * @return  mixed
+	 */
+	public function __get($property)
+	{
+		if (isset($this->image[$property]))
+		{
+			return $this->image[$property];
+		}
+		else
+		{
+			throw new Kohana_Exception('The :property: property does not exist in the :class: class.',
+									   array(':property:' => $property, ':class:' => get_class($this)));
+		}
+	}
+
+	/**
+	 * Resize an image to a specific width and height. By default, Kohana will
+	 * maintain the aspect ratio using the width as the master dimension. If you
+	 * wish to use height as master dim, set $image->master_dim = Image::HEIGHT
+	 * This method is chainable.
+	 *
+	 * @throws  Kohana_Exception
+	 * @param   integer  width
+	 * @param   integer  height
+	 * @param   integer  one of: Image::NONE, Image::AUTO, Image::WIDTH, Image::HEIGHT
+	 * @return  object
+	 */
+	public function resize($width, $height, $master = NULL)
+	{
+		if ( ! $this->valid_size('width', $width))
+			throw new Kohana_Exception('The width you specified, :width:, is not valid.', array(':width:' => $width));
+
+		if ( ! $this->valid_size('height', $height))
+			throw new Kohana_Exception('The height you specified, :height:, is not valid.', array(':height:' => $height));
+
+		if (empty($width) AND empty($height))
+			throw new Kohana_Exception('The dimensions specified for :function: are not valid.', array(':function:' => __FUNCTION__));
+
+		if ($master === NULL)
+		{
+			// Maintain the aspect ratio by default
+			$master = Image::AUTO;
+		}
+		elseif ( ! $this->valid_size('master', $master))
+			throw new Kohana_Exception('The master dimension specified is not valid.');
+
+		$this->actions['resize'] = array
+		(
+			'width'  => $width,
+			'height' => $height,
+			'master' => $master,
+		);
+
+		$this->determine_orientation();
+
+		return $this;
+	}
+
+	/**
+	 * Crop an image to a specific width and height. You may also set the top
+	 * and left offset.
+	 * This method is chainable.
+	 *
+	 * @throws  Kohana_Exception
+	 * @param   integer  width
+	 * @param   integer  height
+	 * @param   integer  top offset, pixel value or one of: top, center, bottom
+	 * @param   integer  left offset, pixel value or one of: left, center, right
+	 * @return  object
+	 */
+	public function crop($width, $height, $top = 'center', $left = 'center')
+	{
+		if ( ! $this->valid_size('width', $width))
+			throw new Kohana_Exception('The width you specified, :width:, is not valid.', array(':width:' => $width));
+
+		if ( ! $this->valid_size('height', $height))
+			throw new Kohana_Exception('The height you specified, :height:, is not valid.', array(':height:' => $height));
+
+		if ( ! $this->valid_size('top', $top))
+			throw new Kohana_Exception('The top offset you specified, :top:, is not valid.', array(':top:' => $top));
+
+		if ( ! $this->valid_size('left', $left))
+			throw new Kohana_Exception('The left offset you specified, :left:, is not valid.', array(':left:' => $left));
+
+		if (empty($width) AND empty($height))
+			throw new Kohana_Exception('The dimensions specified for :function: are not valid.', array(':function:' => __FUNCTION__));
+
+		$this->actions['crop'] = array
+		(
+			'width'  => $width,
+			'height' => $height,
+			'top'    => $top,
+			'left'   => $left,
+		);
+
+		$this->determine_orientation();
+
+		return $this;
+	}
+
+	/**
+	 * Allows rotation of an image by 180 degrees clockwise or counter clockwise.
+	 *
+	 * @param   integer  degrees
+	 * @return  object
+	 */
+	public function rotate($degrees)
+	{
+		$degrees = (int) $degrees;
+
+		if ($degrees > 180)
+		{
+			do
+			{
+				// Keep subtracting full circles until the degrees have normalized
+				$degrees -= 360;
+			}
+			while($degrees > 180);
+		}
+
+		if ($degrees < -180)
+		{
+			do
+			{
+				// Keep adding full circles until the degrees have normalized
+				$degrees += 360;
+			}
+			while($degrees < -180);
+		}
+
+		$this->actions['rotate'] = $degrees;
+
+		return $this;
+	}
+
+	/**
+         * Overlay a second image on top of this one.
+         *
+         * @throws Kohana_Exception
+         * @param  string  $overlay_file          path to an image file
+         * @param  integer $x                     x offset for the overlay
+         * @param  integer $y                     y offset for the overlay
+         * @param  integer $transparency          transparency percent
+         */
+	public function composite($overlay_file, $x, $y, $transparency)
+	{
+		$image_info = getimagesize($overlay_file);
+
+		// Check to make sure the image type is allowed
+		if ( ! isset(Image::$allowed_types[$image_info[2]]))
+			throw new Kohana_Exception('The specified image, :type:, is not an allowed image type.', array(':type:' => $overlay_file));
+
+		$this->actions['composite'] = array
+		(
+			'overlay_file'  => $overlay_file,
+			'mime'          => $image_info['mime'],
+			'x'             => $x,
+			'y'             => $y,
+			'transparency'  => $transparency
+		);
+
+		return $this;
+	}
+
+	/**
+	 * Flip an image horizontally or vertically.
+	 *
+	 * @throws  Kohana_Exception
+	 * @param   integer  direction
+	 * @return  object
+	 */
+	public function flip($direction)
+	{
+		if ($direction !== Image::HORIZONTAL AND $direction !== Image::VERTICAL)
+			throw new Kohana_Exception('The flip direction specified is not valid.');
+
+		$this->actions['flip'] = $direction;
+
+		return $this;
+	}
+
+	/**
+	 * Change the quality of an image.
+	 *
+	 * @param   integer  quality as a percentage
+	 * @return  object
+	 */
+	public function quality($amount)
+	{
+		$this->actions['quality'] = max(1, min($amount, 100));
+
+		return $this;
+	}
+
+	/**
+	 * Sharpen an image.
+	 *
+	 * @param   integer  amount to sharpen, usually ~20 is ideal
+	 * @return  object
+	 */
+	public function sharpen($amount)
+	{
+		$this->actions['sharpen'] = max(1, min($amount, 100));
+
+		return $this;
+	}
+
+	/**
+	 * Save the image to a new image or overwrite this image.
+	 *
+	 * @throws  Kohana_Exception
+	 * @param   string   new image filename
+	 * @param   integer  permissions for new image
+	 * @param   boolean  keep or discard image process actions
+	 * @return  object
+	 */
+	public function save($new_image = FALSE, $chmod = 0644, $keep_actions = FALSE, $background = NULL)
+	{
+		// If no new image is defined, use the current image
+		empty($new_image) and $new_image = $this->image['file'];
+
+		// Separate the directory and filename
+		$dir  = pathinfo($new_image, PATHINFO_DIRNAME);
+		$file = pathinfo($new_image, PATHINFO_BASENAME);
+
+		// Normalize the path
+		$dir = str_replace('\\', '/', realpath($dir)).'/';
+
+		if ( ! is_writable($dir))
+			throw new Kohana_Exception('The specified directory, :dir:, is not writable.', array(':dir:' => $dir));
+
+		if ($status = $this->driver->process($this->image, $this->actions, $dir, $file, FALSE, $background))
+		{
+			if ($chmod !== FALSE)
+			{
+				// Set permissions
+				chmod($new_image, $chmod);
+			}
+		}
+
+		if ($keep_actions !== TRUE)
+		{
+			// Reset actions. Subsequent save() or render() will not apply previous actions.
+			$this->actions = array();
+		}
+
+		return $status;
+	}
+
+	/**
+	 * Output the image to the browser.
+	 *
+	 * @param   boolean  keep or discard image process actions
+	 * @return	object
+	 */
+	public function render($keep_actions = FALSE, $background = NULL)
+	{
+		$new_image = $this->image['file'];
+
+		// Separate the directory and filename
+		$dir  = pathinfo($new_image, PATHINFO_DIRNAME);
+		$file = pathinfo($new_image, PATHINFO_BASENAME);
+
+		// Normalize the path
+		$dir = str_replace('\\', '/', realpath($dir)).'/';
+
+		// Process the image with the driver
+		$status = $this->driver->process($this->image, $this->actions, $dir, $file, TRUE, $background);
+
+		if ($keep_actions !== TRUE)
+		{
+			// Reset actions. Subsequent save() or render() will not apply previous actions.
+			$this->actions = array();
+		}
+
+		return $status;
+	}
+
+	/**
+	 * Sanitize a given value type.
+	 *
+	 * @param   string   type of property
+	 * @param   mixed    property value
+	 * @return  boolean
+	 */
+	protected function valid_size($type, & $value)
+	{
+		if (is_null($value))
+			return TRUE;
+
+		if ( ! is_scalar($value))
+			return FALSE;
+
+		switch ($type)
+		{
+			case 'width':
+			case 'height':
+				if (is_string($value) AND ! ctype_digit($value))
+				{
+					// Only numbers and percent signs
+					if ( ! preg_match('/^[0-9]++%$/D', $value))
+						return FALSE;
+				}
+				else
+				{
+					$value = (int) $value;
+				}
+			break;
+			case 'top':
+				if (is_string($value) AND ! ctype_digit($value))
+				{
+					if ( ! in_array($value, array('top', 'bottom', 'center')))
+						return FALSE;
+				}
+				else
+				{
+					$value = (int) $value;
+				}
+			break;
+			case 'left':
+				if (is_string($value) AND ! ctype_digit($value))
+				{
+					if ( ! in_array($value, array('left', 'right', 'center')))
+						return FALSE;
+				}
+				else
+				{
+					$value = (int) $value;
+				}
+			break;
+			case 'master':
+				if ($value !== Image::NONE AND
+				    $value !== Image::AUTO AND
+				    $value !== Image::WIDTH AND
+				    $value !== Image::HEIGHT)
+					return FALSE;
+			break;
+		}
+
+		return TRUE;
+	}
+
+} // End Image
\ No newline at end of file
diff --git a/system/libraries/Input.php b/system/libraries/Input.php
new file mode 100644
index 0000000..fa984a8
--- /dev/null
+++ b/system/libraries/Input.php
@@ -0,0 +1,507 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Input library.
+ *
+ * $Id: Input.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Input_Core {
+
+	// Enable or disable automatic XSS cleaning
+	protected $use_xss_clean = FALSE;
+
+	// Are magic quotes enabled?
+	protected $magic_quotes_gpc = FALSE;
+
+	// IP address of current user
+	public $ip_address;
+
+	// Input singleton
+	protected static $instance;
+
+	/**
+	 * Retrieve a singleton instance of Input. This will always be the first
+	 * created instance of this class.
+	 *
+	 * @return  object
+	 */
+	public static function instance()
+	{
+		if (Input::$instance === NULL)
+		{
+			// Create a new instance
+			return new Input;
+		}
+
+		return Input::$instance;
+	}
+
+	/**
+	 * Sanitizes global GET, POST and COOKIE data. Also takes care of
+	 * magic_quotes and register_globals, if they have been enabled.
+	 *
+	 * @return  void
+	 */
+	public function __construct()
+	{
+		// Convert all global variables to Kohana charset
+		$_GET    = Input::clean($_GET);
+		$_POST   = Input::clean($_POST);
+		$_COOKIE = Input::clean($_COOKIE);
+		$_SERVER = Input::clean($_SERVER);
+
+		if (Kohana::$server_api === 'cli')
+		{
+			// Convert command line arguments
+			$_SERVER['argv'] = Input::clean($_SERVER['argv']);
+		}
+
+		// Use XSS clean?
+		$this->use_xss_clean = (bool) Kohana::config('core.global_xss_filtering');
+
+		if (Input::$instance === NULL)
+		{
+			// magic_quotes_runtime is enabled
+			if (get_magic_quotes_runtime())
+			{
+				@set_magic_quotes_runtime(0);
+				Kohana_Log::add('debug', 'Disable magic_quotes_runtime! It is evil and deprecated: http://php.net/magic_quotes');
+			}
+
+			// magic_quotes_gpc is enabled
+			if (get_magic_quotes_gpc())
+			{
+				$this->magic_quotes_gpc = TRUE;
+				Kohana_Log::add('debug', 'Disable magic_quotes_gpc! It is evil and deprecated: http://php.net/magic_quotes');
+			}
+
+			if (is_array($_GET))
+			{
+				foreach ($_GET as $key => $val)
+				{
+					// Sanitize $_GET
+					$_GET[$this->clean_input_keys($key)] = $this->clean_input_data($val);
+				}
+			}
+			else
+			{
+				$_GET = array();
+			}
+
+			if (is_array($_POST))
+			{
+				foreach ($_POST as $key => $val)
+				{
+					// Sanitize $_POST
+					$_POST[$this->clean_input_keys($key)] = $this->clean_input_data($val);
+				}
+			}
+			else
+			{
+				$_POST = array();
+			}
+
+			if (is_array($_COOKIE))
+			{
+				foreach ($_COOKIE as $key => $val)
+				{
+					// Ignore special attributes in RFC2109 compliant cookies
+					if ($key == '$Version' OR $key == '$Path' OR $key == '$Domain')
+						continue;
+
+					// Sanitize $_COOKIE
+					$_COOKIE[$this->clean_input_keys($key)] = $this->clean_input_data($val);
+				}
+			}
+			else
+			{
+				$_COOKIE = array();
+			}
+
+			// Create a singleton
+			Input::$instance = $this;
+
+			Kohana_Log::add('debug', 'Global GET, POST and COOKIE data sanitized');
+		}
+	}
+
+	/**
+	 * Fetch an item from the $_GET array.
+	 *
+	 * @param   string   key to find
+	 * @param   mixed    default value
+	 * @param   boolean  XSS clean the value
+	 * @return  mixed
+	 */
+	public function get($key = array(), $default = NULL, $xss_clean = FALSE)
+	{
+		return $this->search_array($_GET, $key, $default, $xss_clean);
+	}
+
+	/**
+	 * Fetch an item from the $_POST array.
+	 *
+	 * @param   string   key to find
+	 * @param   mixed    default value
+	 * @param   boolean  XSS clean the value
+	 * @return  mixed
+	 */
+	public function post($key = array(), $default = NULL, $xss_clean = FALSE)
+	{
+		return $this->search_array($_POST, $key, $default, $xss_clean);
+	}
+
+	/**
+	 * Fetch an item from the cookie::get() ($_COOKIE won't work with signed
+	 * cookies.)
+	 *
+	 * @param   string   key to find
+	 * @param   mixed    default value
+	 * @param   boolean  XSS clean the value
+	 * @return  mixed
+	 */
+	public function cookie($key = array(), $default = NULL, $xss_clean = FALSE)
+	{
+		return $this->search_array(cookie::get(), $key, $default, $xss_clean);
+	}
+
+	/**
+	 * Fetch an item from the $_SERVER array.
+	 *
+	 * @param   string   key to find
+	 * @param   mixed    default value
+	 * @param   boolean  XSS clean the value
+	 * @return  mixed
+	 */
+	public function server($key = array(), $default = NULL, $xss_clean = FALSE)
+	{
+		return $this->search_array($_SERVER, $key, $default, $xss_clean);
+	}
+
+	/**
+	 * Fetch an item from a global array.
+	 *
+	 * @param   array    array to search
+	 * @param   string   key to find
+	 * @param   mixed    default value
+	 * @param   boolean  XSS clean the value
+	 * @return  mixed
+	 */
+	protected function search_array($array, $key, $default = NULL, $xss_clean = FALSE)
+	{
+		if ($key === array())
+			return $array;
+
+		if ( ! isset($array[$key]))
+			return $default;
+
+		// Get the value
+		$value = $array[$key];
+
+		if ($this->use_xss_clean === FALSE AND $xss_clean === TRUE)
+		{
+			// XSS clean the value
+			$value = $this->xss_clean($value);
+		}
+
+		return $value;
+	}
+
+	/**
+	 * Fetch the IP Address.
+	 *
+	 * @return string
+	 */
+	public function ip_address()
+	{
+		if ($this->ip_address !== NULL)
+			return $this->ip_address;
+
+		// Server keys that could contain the client IP address
+		$keys = array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR');
+
+		foreach ($keys as $key)
+		{
+			if ($ip = $this->server($key))
+			{
+				$this->ip_address = $ip;
+
+				// An IP address has been found
+				break;
+			}
+		}
+
+		if ($comma = strrpos($this->ip_address, ',') !== FALSE)
+		{
+			$this->ip_address = substr($this->ip_address, $comma + 1);
+		}
+
+		if ( ! valid::ip($this->ip_address))
+		{
+			// Use an empty IP
+			$this->ip_address = '0.0.0.0';
+		}
+
+		return $this->ip_address;
+	}
+
+	/**
+	 * Clean cross site scripting exploits from string.
+	 * HTMLPurifier may be used if installed, otherwise defaults to built in method.
+	 * Note - This function should only be used to deal with data upon submission.
+	 * It's not something that should be used for general runtime processing
+	 * since it requires a fair amount of processing overhead.
+	 *
+	 * @param   string  data to clean
+	 * @param   string  xss_clean method to use ('htmlpurifier' or defaults to built-in method)
+	 * @return  string
+	 */
+	public function xss_clean($data, $tool = NULL)
+	{
+		if ($tool === NULL)
+		{
+			// Use the default tool
+			$tool = Kohana::config('core.global_xss_filtering');
+		}
+
+		if (is_array($data))
+		{
+			foreach ($data as $key => $val)
+			{
+				$data[$key] = $this->xss_clean($val, $tool);
+			}
+
+			return $data;
+		}
+
+		// Do not clean empty strings
+		if (trim($data) === '')
+			return $data;
+
+		if (is_bool($tool))
+		{
+			$tool = 'default';
+		}
+		elseif ( ! method_exists($this, 'xss_filter_'.$tool))
+		{
+			Kohana_Log::add('error', 'Unable to use Input::xss_filter_'.$tool.'(), no such method exists');
+			$tool = 'default';
+		}
+
+		$method = 'xss_filter_'.$tool;
+
+		return $this->$method($data);
+	}
+
+	/**
+	 * Default built-in cross site scripting filter.
+	 *
+	 * @param   string  data to clean
+	 * @return  string
+	 */
+	protected function xss_filter_default($data)
+	{
+		// http://svn.bitflux.ch/repos/public/popoon/trunk/classes/externalinput.php
+		// +----------------------------------------------------------------------+
+		// | Copyright (c) 2001-2006 Bitflux GmbH                                 |
+		// +----------------------------------------------------------------------+
+		// | Licensed under the Apache License, Version 2.0 (the "License");      |
+		// | you may not use this file except in compliance with the License.     |
+		// | You may obtain a copy of the License at                              |
+		// | http://www.apache.org/licenses/LICENSE-2.0                           |
+		// | Unless required by applicable law or agreed to in writing, software  |
+		// | distributed under the License is distributed on an "AS IS" BASIS,    |
+		// | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or      |
+		// | implied. See the License for the specific language governing         |
+		// | permissions and limitations under the License.                       |
+		// +----------------------------------------------------------------------+
+		// | Author: Christian Stocker <chregu@bitflux.ch>                        |
+		// +----------------------------------------------------------------------+
+		//
+		// Kohana Modifications:
+		// * Changed double quotes to single quotes, changed indenting and spacing
+		// * Removed magic_quotes stuff
+		// * Increased regex readability:
+		//   * Used delimeters that aren't found in the pattern
+		//   * Removed all unneeded escapes
+		//   * Deleted U modifiers and swapped greediness where needed
+		// * Increased regex speed:
+		//   * Made capturing parentheses non-capturing where possible
+		//   * Removed parentheses where possible
+		//   * Split up alternation alternatives
+		//   * Made some quantifiers possessive
+		//
+		// Gallery Modifications:
+		// * Wrap the loop around all the changes to detect nested exploits
+
+		do
+		{
+			$old_data = $data;
+
+			// Fix &entity\n;
+			$data = str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data);
+			$data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
+			$data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
+			$data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
+
+			// Remove any attribute starting with "on" or xmlns
+			$data = preg_replace('#(?:on[a-z]+|xmlns)\s*=\s*[\'"\x00-\x20]?[^\'>"]*[\'"\x00-\x20]?\s?#iu', '', $data);
+
+			// Remove javascript: and vbscript: protocols
+			$data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
+			$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
+			$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
+
+                        //remove any style attributes, IE allows too much stupid things in them, eg.
+                        //<span style="width: expression(alert('Ping!'));"></span>
+                        // and in general you really don't want style declarations in your UGC
+                        $data = preg_replace('#(<[^>]+[\x00-\x20\"\'\/])style[^>]*>#iUu', "$1>", $data);
+
+			// Remove namespaced elements (we do not need them)
+			$data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
+
+			// Remove really unwanted tags
+			$data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
+		}
+		while ($old_data !== $data);
+
+		return $data;
+	}
+
+	/**
+	 * HTMLPurifier cross site scripting filter. This version assumes the
+	 * existence of the "Standalone Distribution" htmlpurifier library, and is set to not tidy
+	 * input.
+	 *
+	 * @param   string  data to clean
+	 * @return  string
+	 */
+	protected function xss_filter_htmlpurifier($data)
+	{
+		/**
+		 * @todo License should go here, http://htmlpurifier.org/
+		 */
+		if ( ! class_exists('HTMLPurifier_Config', FALSE))
+		{
+			// Load HTMLPurifier
+			require Kohana::find_file('vendor', 'htmlpurifier/HTMLPurifier.standalone', TRUE);
+		}
+
+		// Set configuration
+		$config = HTMLPurifier_Config::createDefault();
+		$config->set('HTML.TidyLevel', 'none'); // Only XSS cleaning now
+
+		$cache = Kohana::config('html_purifier.cache');
+
+		if ($cache AND is_string($cache))
+		{
+			$config->set('Cache.SerializerPath', $cache);
+		}
+
+		// Run HTMLPurifier
+		$data = HTMLPurifier::instance($config)->purify($data);
+
+		return $data;
+	}
+
+	/**
+	 * This is a helper method. It enforces W3C specifications for allowed
+	 * key name strings, to prevent malicious exploitation.
+	 *
+	 * @param   string  string to clean
+	 * @return  string
+	 */
+	public function clean_input_keys($str)
+	{
+		if ( ! preg_match('#^[\pL0-9:_.-]++$#uD', $str))
+		{
+			exit('Disallowed key characters in global data.');
+		}
+
+		return $str;
+	}
+
+	/**
+	 * This is a helper method. It escapes data and forces all newline
+	 * characters to "\n".
+	 *
+	 * @param   unknown_type  string to clean
+	 * @return  string
+	 */
+	public function clean_input_data($str)
+	{
+		if (is_array($str))
+		{
+			$new_array = array();
+			foreach ($str as $key => $val)
+			{
+				// Recursion!
+				$new_array[$this->clean_input_keys($key)] = $this->clean_input_data($val);
+			}
+			return $new_array;
+		}
+
+		if ($this->magic_quotes_gpc === TRUE)
+		{
+			// Remove annoying magic quotes
+			$str = stripslashes($str);
+		}
+
+		if ($this->use_xss_clean === TRUE)
+		{
+			$str = $this->xss_clean($str);
+		}
+
+		if (strpos($str, "\r") !== FALSE)
+		{
+			// Standardize newlines
+			$str = str_replace(array("\r\n", "\r"), "\n", $str);
+		}
+
+		return $str;
+	}
+
+	/**
+	 * Recursively cleans arrays, objects, and strings. Removes ASCII control
+	 * codes and converts to UTF-8 while silently discarding incompatible
+	 * UTF-8 characters.
+	 *
+	 * @param   string  string to clean
+	 * @return  string
+	 */
+	public static function clean($str)
+	{
+		if (is_array($str) OR is_object($str))
+		{
+			foreach ($str as $key => $val)
+			{
+				// Recursion!
+				$str[Input::clean($key)] = Input::clean($val);
+			}
+		}
+		elseif (is_string($str) AND $str !== '')
+		{
+			// Remove control characters
+			$str = text::strip_ascii_ctrl($str);
+
+			if ( ! text::is_ascii($str))
+			{
+				// Disable notices
+				$ER = error_reporting(~E_NOTICE);
+
+				// iconv is expensive, so it is only used when needed
+				$str = iconv(Kohana::CHARSET, Kohana::CHARSET.'//IGNORE', $str);
+
+				// Turn notices back on
+				error_reporting($ER);
+			}
+		}
+
+		return $str;
+	}
+
+} // End Input Class
diff --git a/system/libraries/Kohana_404_Exception.php b/system/libraries/Kohana_404_Exception.php
new file mode 100644
index 0000000..7bb7708
--- /dev/null
+++ b/system/libraries/Kohana_404_Exception.php
@@ -0,0 +1,56 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Creates a "Page Not Found" exception.
+ *
+ * $Id: Kohana_404_Exception.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+class Kohana_404_Exception_Core extends Kohana_Exception {
+
+	protected $code = E_PAGE_NOT_FOUND;
+
+	/**
+	 * Set internal properties.
+	 *
+	 * @param  string  URI of page
+	 * @param  string  custom error template
+	 */
+	public function __construct($page = NULL)
+	{
+		if ($page === NULL)
+		{
+			// Use the complete URI
+			$page = Router::$complete_uri;
+		}
+
+		parent::__construct('The page you requested, %page%, could not be found.', array('%page%' => $page));
+	}
+
+	/**
+	 * Throws a new 404 exception.
+	 *
+	 * @throws  Kohana_404_Exception
+	 * @return  void
+	 */
+	public static function trigger($page = NULL)
+	{
+		throw new Kohana_404_Exception($page);
+	}
+
+	/**
+	 * Sends 404 headers, to emulate server behavior.
+	 *
+	 * @return void
+	 */
+	public function sendHeaders()
+	{
+		// Send the 404 header
+		header('HTTP/1.1 404 File Not Found');
+	}
+
+} // End Kohana 404 Exception
\ No newline at end of file
diff --git a/system/libraries/Kohana_Log.php b/system/libraries/Kohana_Log.php
new file mode 100644
index 0000000..5126013
--- /dev/null
+++ b/system/libraries/Kohana_Log.php
@@ -0,0 +1,90 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Logging class.
+ *
+ * $Id: Kohana_Log.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Kohana_Log_Core {
+
+	// Configuration
+	protected static $config;
+
+	// Drivers
+	protected static $drivers;
+
+	// Logged messages
+	protected static $messages;
+
+	/**
+	 * Add a new message to the log.
+	 *
+	 * @param   string  type of message
+	 * @param   string  message text
+	 * @return  void
+	 */
+	public static function add($type, $message)
+	{
+		// Make sure the drivers and config are loaded
+		if ( ! is_array(Kohana_Log::$config))
+		{
+			Kohana_Log::$config = Kohana::config('log');
+		}
+
+		if ( ! is_array(Kohana_Log::$drivers))
+		{
+			foreach ( (array) Kohana::config('log.drivers') as $driver_name)
+			{
+				// Set driver name
+				$driver = 'Log_'.ucfirst($driver_name).'_Driver';
+
+				// Load the driver
+				if ( ! Kohana::auto_load($driver))
+					throw new Kohana_Exception('Log Driver Not Found: %driver%', array('%driver%' => $driver));
+
+				// Initialize the driver
+				$driver = new $driver(array_merge(Kohana::config('log'), Kohana::config('log_'.$driver_name)));
+
+				// Validate the driver
+				if ( ! ($driver instanceof Log_Driver))
+					throw new Kohana_Exception('%driver% does not implement the Log_Driver interface', array('%driver%' => $driver));
+
+				Kohana_Log::$drivers[] = $driver;
+			}
+
+			// Always save logs on shutdown
+			Event::add('system.shutdown', array('Kohana_Log', 'save'));
+		}
+
+		Kohana_Log::$messages[] = array('date' => time(), 'type' => $type, 'message' => $message);
+	}
+
+	/**
+	 * Save all currently logged messages.
+	 *
+	 * @return  void
+	 */
+	public static function save()
+	{
+		if (empty(Kohana_Log::$messages))
+			return;
+
+		foreach (Kohana_Log::$drivers as $driver)
+		{
+			// We can't throw exceptions here or else we will get a
+			// Exception thrown without a stack frame error
+			try
+			{
+				$driver->save(Kohana_Log::$messages);
+			}
+			catch(Exception $e){}
+		}
+
+		// Reset the messages
+		Kohana_Log::$messages = array();
+	}
+}
\ No newline at end of file
diff --git a/system/libraries/Kohana_PHP_Exception.php b/system/libraries/Kohana_PHP_Exception.php
new file mode 100644
index 0000000..779c229
--- /dev/null
+++ b/system/libraries/Kohana_PHP_Exception.php
@@ -0,0 +1,99 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Kohana PHP Error Exceptions
+ *
+ * $Id: Kohana_PHP_Exception.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+class Kohana_PHP_Exception_Core extends Kohana_Exception {
+
+	public static $enabled = FALSE;
+
+	/**
+	 * Enable Kohana PHP error handling.
+	 *
+	 * @return  void
+	 */
+	public static function enable()
+	{
+		if ( ! Kohana_PHP_Exception::$enabled)
+		{
+			// Handle runtime errors
+			set_error_handler(array('Kohana_PHP_Exception', 'error_handler'));
+
+			// Handle errors which halt execution
+			Event::add('system.shutdown', array('Kohana_PHP_Exception', 'shutdown_handler'));
+
+			Kohana_PHP_Exception::$enabled = TRUE;
+		}
+	}
+
+	/**
+	 * Disable Kohana PHP error handling.
+	 *
+	 * @return  void
+	 */
+	public static function disable()
+	{
+		if (Kohana_PHP_Exception::$enabled)
+		{
+			restore_error_handler();
+
+			Event::clear('system.shutdown', array('Kohana_PHP_Exception', 'shutdown_handler'));
+
+			Kohana_PHP_Exception::$enabled = FALSE;
+		}
+	}
+
+	/**
+	 * Create a new PHP error exception.
+	 *
+	 * @return  void
+	 */
+	public function __construct($code, $error, $file, $line, $context = NULL)
+	{
+		parent::__construct($error);
+
+		// Set the error code, file, line, and context manually
+		$this->code = $code;
+		$this->file = $file;
+		$this->line = $line;
+	}
+
+	/**
+	 * PHP error handler.
+	 *
+	 * @throws  Kohana_PHP_Exception
+	 * @return  void
+	 */
+	public static function error_handler($code, $error, $file, $line, $context = NULL)
+	{
+		// Respect error_reporting settings
+		if (error_reporting() & $code)
+		{
+			// Throw an exception
+			throw new Kohana_PHP_Exception($code, $error, $file, $line, $context);
+		}
+	}
+
+	/**
+	 * Catches errors that are not caught by the error handler, such as E_PARSE.
+	 *
+	 * @uses    Kohana_Exception::handle()
+	 * @return  void
+	 */
+	public static function shutdown_handler()
+	{
+		if (Kohana_PHP_Exception::$enabled AND $error = error_get_last() AND (error_reporting() & $error['type']))
+		{
+			// Fake an exception for nice debugging
+			Kohana_Exception::handle(new Kohana_PHP_Exception($error['type'], $error['message'], $error['file'], $error['line']));
+		}
+	}
+
+} // End Kohana PHP Exception
diff --git a/system/libraries/Kohana_User_Exception.php b/system/libraries/Kohana_User_Exception.php
new file mode 100644
index 0000000..a0ec3ac
--- /dev/null
+++ b/system/libraries/Kohana_User_Exception.php
@@ -0,0 +1,30 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Creates a custom exception message.
+ *
+ * $Id: Kohana_User_Exception.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+class Kohana_User_Exception_Core extends Kohana_Exception {
+
+	/**
+	 * Set exception title and message.
+	 *
+	 * @param   string  exception title string
+	 * @param   string  exception message string
+	 * @param   string  custom error template
+	 */
+	public function __construct($title, $message, array $variables = NULL)
+	{
+		parent::__construct($message, $variables);
+
+		// Code is the error title
+		$this->code = $title;
+	}
+
+} // End Kohana User Exception
diff --git a/system/libraries/Model.php b/system/libraries/Model.php
new file mode 100644
index 0000000..ee50d50
--- /dev/null
+++ b/system/libraries/Model.php
@@ -0,0 +1,62 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Model base class.
+ *
+ * $Id: Model.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Model_Core {
+
+	/**
+	 * Creates and returns a new model.
+	 *
+	 * @param   string   model name
+	 * @param   mixed    constructor arguments
+	 * @param   boolean  construct the model with multiple arguments
+	 * @return  Model
+	 */
+	public static function factory($name, $args = NULL, $multiple = FALSE)
+	{
+		// Model class name
+		$class = ucfirst($name).'_Model';
+
+		if ($args === NULL)
+		{
+			// Create a new model with no arguments
+			return new $class;
+		}
+
+		if ($multiple !== TRUE)
+		{
+			// Create a model with a single argument
+			return new $class($args);
+		}
+
+		$class = new ReflectionClass($class);
+
+		// Create a model with multiple arguments
+		return $class->newInstanceArgs($args);
+	}
+
+	// Database object
+	protected $db = 'default';
+
+	/**
+	 * Loads the database instance, if the database is not already loaded.
+	 *
+	 * @return  void
+	 */
+	public function __construct()
+	{
+		if ( ! is_object($this->db))
+		{
+			// Load the default database
+			$this->db = Database::instance($this->db);
+		}
+	}
+
+} // End Model
\ No newline at end of file
diff --git a/system/libraries/ORM.php b/system/libraries/ORM.php
new file mode 100644
index 0000000..16e047b
--- /dev/null
+++ b/system/libraries/ORM.php
@@ -0,0 +1,1528 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * [Object Relational Mapping][ref-orm] (ORM) is a method of abstracting database
+ * access to standard PHP calls. All table rows are represented as model objects,
+ * with object properties representing row data. ORM in Kohana generally follows
+ * the [Active Record][ref-act] pattern.
+ *
+ * [ref-orm]: http://wikipedia.org/wiki/Object-relational_mapping
+ * [ref-act]: http://wikipedia.org/wiki/Active_record
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class ORM_Core {
+
+	// Current relationships
+	protected $has_one                 = array();
+	protected $belongs_to              = array();
+	protected $has_many                = array();
+	protected $has_and_belongs_to_many = array();
+	protected $has_many_through        = array();
+
+	// Relationships that should always be joined
+	protected $load_with = array();
+
+	// Current object
+	protected $object  = array();
+	protected $changed = array();
+	protected $related = array();
+	protected $_valid  = FALSE;
+	protected $_loaded  = FALSE;
+	protected $_saved   = FALSE;
+	protected $sorting;
+	protected $rules = array();
+
+	// Related objects
+	protected $object_relations = array();
+	protected $changed_relations = array();
+
+	// Model table information
+	protected $object_name;
+	protected $object_plural;
+	protected $table_name;
+	protected $table_columns;
+	protected $ignored_columns;
+
+	// Auto-update columns for creation and updates
+	protected $updated_column = NULL;
+	protected $created_column = NULL;
+
+	// Table primary key and value
+	protected $primary_key = 'id';
+	protected $primary_val = 'name';
+
+	// Array of foreign key name overloads
+	protected $foreign_key = array();
+
+	// Model configuration
+	protected $table_names_plural = TRUE;
+	protected $reload_on_wakeup   = TRUE;
+
+	// Database configuration
+	protected $db = 'default';
+	protected $db_applied = array();
+	protected $db_builder;
+
+	// With calls already applied
+	protected $with_applied = array();
+
+	// Stores column information for ORM models
+	protected static $column_cache = array();
+
+	/**
+	 * Creates and returns a new model.
+	 *
+	 * @chainable
+	 * @param   string  model name
+	 * @param   mixed   parameter for find()
+	 * @return  ORM
+	 */
+	public static function factory($model, $id = NULL)
+	{
+		// Set class name
+		$model = ucfirst($model).'_Model';
+
+		return new $model($id);
+	}
+
+	/**
+	 * Prepares the model database connection and loads the object.
+	 *
+	 * @param   mixed  parameter for find or object to load
+	 * @return  void
+	 */
+	public function __construct($id = NULL)
+	{
+		// Set the object name and plural name
+		$this->object_name   = strtolower(substr(get_class($this), 0, -6));
+		$this->object_plural = inflector::plural($this->object_name);
+
+		if ( ! isset($this->sorting))
+		{
+			// Default sorting
+			$this->sorting = array($this->primary_key => 'asc');
+		}
+
+		// Initialize database
+		$this->__initialize();
+
+		// Clear the object
+		$this->clear();
+
+		if (is_object($id))
+		{
+			// Load an object
+			$this->_load_values((array) $id);
+		}
+		elseif ( ! empty($id))
+		{
+			// Set the object's primary key, but don't load it until needed
+			$this->object[$this->primary_key] = $id;
+
+			// Object is considered saved until something is set
+			$this->_saved = TRUE;
+		}
+	}
+
+	/**
+	 * Prepares the model database connection, determines the table name,
+	 * and loads column information.
+	 *
+	 * @return  void
+	 */
+	public function __initialize()
+	{
+		if ( ! is_object($this->db))
+		{
+			// Get database instance
+			$this->db = Database::instance($this->db);
+		}
+
+		if (empty($this->table_name))
+		{
+			// Table name is the same as the object name
+			$this->table_name = $this->object_name;
+
+			if ($this->table_names_plural === TRUE)
+			{
+				// Make the table name plural
+				$this->table_name = inflector::plural($this->table_name);
+			}
+		}
+
+		if (is_array($this->ignored_columns))
+		{
+			// Make the ignored columns mirrored = mirrored
+			$this->ignored_columns = array_combine($this->ignored_columns, $this->ignored_columns);
+		}
+
+		// Load column information
+		$this->reload_columns();
+
+		// Initialize the builder
+		$this->db_builder = db::build();
+	}
+
+	/**
+	 * Allows serialization of only the object data and state, to prevent
+	 * "stale" objects being unserialized, which also requires less memory.
+	 *
+	 * @return  array
+	 */
+	public function __sleep()
+	{
+		// Store only information about the object
+		return array('object_name', 'object', 'changed', '_loaded', '_saved', 'sorting');
+	}
+
+	/**
+	 * Prepares the database connection and reloads the object.
+	 *
+	 * @return  void
+	 */
+	public function __wakeup()
+	{
+		// Initialize database
+		$this->__initialize();
+
+		if ($this->reload_on_wakeup === TRUE)
+		{
+			// Reload the object
+			$this->reload();
+		}
+	}
+
+	/**
+	 * Handles pass-through to database methods. Calls to query methods
+	 * (query, get, insert, update) are not allowed. Query builder methods
+	 * are chainable.
+	 *
+	 * @param   string  method name
+	 * @param   array   method arguments
+	 * @return  mixed
+	 */
+	public function __call($method, array $args)
+	{
+		if (method_exists($this->db_builder, $method))
+		{
+			if (in_array($method, array('execute', 'insert', 'update', 'delete')))
+				throw new Kohana_Exception('Query methods cannot be used through ORM');
+
+			// Method has been applied to the database
+			$this->db_applied[$method] = $method;
+
+			// Number of arguments passed
+			$num_args = count($args);
+
+			if ($method === 'select' AND $num_args > 3)
+			{
+				// Call select() manually to avoid call_user_func_array
+				$this->db_builder->select($args);
+			}
+			else
+			{
+				// We use switch here to manually call the database methods. This is
+				// done for speed: call_user_func_array can take over 300% longer to
+				// make calls. Most database methods are 4 arguments or less, so this
+				// avoids almost any calls to call_user_func_array.
+
+				switch ($num_args)
+				{
+					case 0:
+						if (in_array($method, array('open', 'and_open', 'or_open', 'close', 'cache')))
+						{
+							// Should return ORM, not Database
+							$this->db_builder->$method();
+						}
+						else
+						{
+							// Support for things like reset_select, reset_write, list_tables
+							return $this->db_builder->$method();
+						}
+					break;
+					case 1:
+						$this->db_builder->$method($args[0]);
+					break;
+					case 2:
+						$this->db_builder->$method($args[0], $args[1]);
+					break;
+					case 3:
+						$this->db_builder->$method($args[0], $args[1], $args[2]);
+					break;
+					case 4:
+						$this->db_builder->$method($args[0], $args[1], $args[2], $args[3]);
+					break;
+					default:
+						// Here comes the snail...
+						call_user_func_array(array($this->db, $method), $args);
+					break;
+				}
+			}
+
+			return $this;
+		}
+		else
+		{
+			throw new Kohana_Exception('Invalid method :method called in :class',
+				array(':method' => $method, ':class' => get_class($this)));
+		}
+	}
+
+	/**
+	 * Handles retrieval of all model values, relationships, and metadata.
+	 *
+	 * @param   string  column name
+	 * @return  mixed
+	 */
+	public function __get($column)
+	{
+		if (array_key_exists($column, $this->object))
+		{
+			if( ! $this->loaded() AND ! $this->empty_primary_key())
+			{
+				// Column asked for but the object hasn't been loaded yet, so do it now
+				// Ignore loading of any columns that have been changed
+				$this->find($this->object[$this->primary_key], TRUE);
+			}
+
+			return $this->object[$column];
+		}
+		elseif (isset($this->related[$column]))
+		{
+			return $this->related[$column];
+		}
+		elseif ($column === 'primary_key_value')
+		{
+			if( ! $this->loaded() AND ! $this->empty_primary_key() AND $this->unique_key($this->object[$this->primary_key]) !== $this->primary_key)
+			{
+				// Load if object hasn't been loaded and the key given isn't the primary_key
+				// that we need (i.e. passing an email address to ORM::factory rather than the id)
+				$this->find($this->object[$this->primary_key], TRUE);
+			}
+
+			return $this->object[$this->primary_key];
+		}
+		elseif ($model = $this->related_object($column))
+		{
+			// This handles the has_one and belongs_to relationships
+
+			if (in_array($model->object_name, $this->belongs_to))
+			{
+				if ( ! $this->loaded() AND ! $this->empty_primary_key())
+				{
+					// Load this object first so we know what id to look for in the foreign table
+					$this->find($this->object[$this->primary_key], TRUE);
+				}
+
+				// Foreign key lies in this table (this model belongs_to target model)
+				$where = array($model->foreign_key(TRUE), '=', $this->object[$this->foreign_key($column)]);
+			}
+			else
+			{
+				// Foreign key lies in the target table (this model has_one target model)
+				$where = array($this->foreign_key($column, $model->table_name), '=', $this->primary_key_value);
+			}
+
+			// one<>alias:one relationship
+			return $this->related[$column] = $model->find($where);
+		}
+		elseif (isset($this->has_many_through[$column]))
+		{
+			// Load the "middle" model
+			$through = ORM::factory(inflector::singular($this->has_many_through[$column]));
+
+			// Load the "end" model
+			$model = ORM::factory(inflector::singular($column));
+
+			// Join ON target model's primary key set to 'through' model's foreign key
+			// User-defined foreign keys must be defined in the 'through' model
+			$join_table = $through->table_name;
+			$join_col1  = $through->foreign_key($model->object_name, $join_table);
+			$join_col2  = $model->foreign_key(TRUE);
+
+			// one<>alias:many relationship
+			return $model
+				->join($join_table, $join_col1, $join_col2)
+				->where($through->foreign_key($this->object_name, $join_table), '=', $this->primary_key_value);
+		}
+		elseif (isset($this->has_many[$column]))
+		{
+			// one<>many aliased relationship
+			$model_name = $this->has_many[$column];
+
+			$model = ORM::factory(inflector::singular($model_name));
+
+			return $model->where($this->foreign_key($column, $model->table_name), '=', $this->primary_key_value);
+		}
+		elseif (in_array($column, $this->has_many))
+		{
+			// one<>many relationship
+			$model = ORM::factory(inflector::singular($column));
+			return $model->where($this->foreign_key($column, $model->table_name), '=', $this->primary_key_value);
+		}
+		elseif (in_array($column, $this->has_and_belongs_to_many))
+		{
+			// Load the remote model, always singular
+			$model = ORM::factory(inflector::singular($column));
+
+			if ($this->has($model, TRUE))
+			{
+				// many<>many relationship
+				return $model->where($model->foreign_key(TRUE), 'IN', $this->changed_relations[$column]);
+			}
+			else
+			{
+				// empty many<>many relationship
+				return $model->where($model->foreign_key(TRUE), 'IS', NULL);
+			}
+		}
+		elseif (isset($this->ignored_columns[$column]))
+		{
+			return NULL;
+		}
+		elseif (in_array($column, array
+			(
+				'object_name', 'object_plural','_valid', // Object
+				'primary_key', 'primary_val', 'table_name', 'table_columns', // Table
+				'has_one', 'belongs_to', 'has_many', 'has_many_through', 'has_and_belongs_to_many', 'load_with' // Relationships
+			)))
+		{
+			// Model meta information
+			return $this->$column;
+		}
+		else
+		{
+			throw new Kohana_Exception('The :property property does not exist in the :class class',
+				array(':property' => $column, ':class' => get_class($this)));
+		}
+	}
+
+	/**
+	 * Tells you if the Model has been loaded or not
+	 *
+	 * @return bool
+	 */
+	public function loaded() {
+		if ( ! $this->_loaded AND ! $this->empty_primary_key())
+		{
+			// If returning the loaded member and no load has been attempted, do it now
+			$this->find($this->object[$this->primary_key], TRUE);
+		}
+		return $this->_loaded;
+	}
+
+	/**
+	 * Tells you if the model was saved successfully or not
+	 *
+	 * @return bool
+	 */
+	public function saved() {
+		return $this->_saved;
+	}
+
+	/**
+	 * Handles setting of all model values, and tracks changes between values.
+	 *
+	 * @param   string  column name
+	 * @param   mixed   column value
+	 * @return  void
+	 */
+	public function __set($column, $value)
+	{
+		if (isset($this->ignored_columns[$column]))
+		{
+			return NULL;
+		}
+		elseif (isset($this->object[$column]) OR array_key_exists($column, $this->object))
+		{
+			if (isset($this->table_columns[$column]))
+			{
+				// Data has changed
+				$this->changed[$column] = $column;
+
+				// Object is no longer saved or valid
+				$this->_saved = $this->_valid = FALSE;
+			}
+
+			$this->object[$column] = $value;
+		}
+		elseif (in_array($column, $this->has_and_belongs_to_many) AND is_array($value))
+		{
+			// Load relations
+			$model = ORM::factory(inflector::singular($column));
+
+			if ( ! isset($this->object_relations[$column]))
+			{
+				// Load relations
+				$this->has($model);
+			}
+
+			// Change the relationships
+			$this->changed_relations[$column] = $value;
+
+			if (isset($this->related[$column]))
+			{
+				// Force a reload of the relationships
+				unset($this->related[$column]);
+			}
+		}
+		else
+		{
+			throw new Kohana_Exception('The :property: property does not exist in the :class: class',
+				array(':property:' => $column, ':class:' => get_class($this)));
+		}
+	}
+
+	/**
+	 * Chainable set method
+	 *
+	 * @param   string  name of field or array of key => val
+	 * @param   mixed   value
+	 * @return  ORM
+	 */
+	public function set($name, $value = NULL)
+	{
+		if (is_array($name))
+		{
+			foreach ($name as $key => $value)
+			{
+				$this->__set($key, $value);
+			}
+		}
+		else
+		{
+			$this->__set($name, $value);
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Checks if object data is set.
+	 *
+	 * @param   string  column name
+	 * @return  boolean
+	 */
+	public function __isset($column)
+	{
+		return (isset($this->object[$column]) OR isset($this->related[$column]));
+	}
+
+	/**
+	 * Unsets object data.
+	 *
+	 * @param   string  column name
+	 * @return  void
+	 */
+	public function __unset($column)
+	{
+		unset($this->object[$column], $this->changed[$column], $this->related[$column]);
+	}
+
+	/**
+	 * Returns the values of this object as an array.
+	 *
+	 * @return  array
+	 */
+	public function as_array()
+	{
+		$object = array();
+
+		foreach ($this->object as $key => $val)
+		{
+			// Reconstruct the array (calls __get)
+			$object[$key] = $this->$key;
+		}
+
+		foreach ($this->with_applied as $model => $enabled)
+		{
+			// Generate arrays for relationships
+			if ($enabled)
+			{
+				$object[$model] = $this->$model->as_array();
+			}
+		}
+
+		return $object;
+	}
+
+	/**
+	 * Binds another one-to-one object to this model.  One-to-one objects
+	 * can be nested using 'object1:object2' syntax
+	 *
+	 * @param   string  target model to bind to
+	 * @return  void
+	 */
+	public function with($target_path)
+	{
+		if (isset($this->with_applied[$target_path]))
+		{
+			// Don't join anything already joined
+			return $this;
+		}
+
+		// Split object parts
+		$objects = explode(':', $target_path);
+		$target	 = $this;
+		foreach ($objects as $object)
+		{
+			// Go down the line of objects to find the given target
+			$parent = $target;
+			$target = $parent->related_object($object);
+
+			if ( ! $target)
+			{
+				// Can't find related object
+				return $this;
+			}
+		}
+
+		$target_name = $object;
+
+		// Pop-off top object to get the parent object (user:photo:tag becomes user:photo - the parent table prefix)
+		array_pop($objects);
+		$parent_path = implode(':', $objects);
+
+		if (empty($parent_path))
+		{
+			// Use this table name itself for the parent object
+			$parent_path = $this->table_name;
+		}
+		else
+		{
+			if( ! isset($this->with_applied[$parent_path]))
+			{
+				// If the parent object hasn't been joined yet, do it first (otherwise LEFT JOINs fail)
+				$this->with($parent_path);
+			}
+		}
+
+		// Add to with_applied to prevent duplicate joins
+		$this->with_applied[$target_path] = TRUE;
+
+		$select = array();
+
+		// Use the keys of the empty object to determine the columns
+		foreach (array_keys($target->object) as $column)
+		{
+			// Add the prefix so that load_result can determine the relationship
+			$select[$target_path.':'.$column] = $target_path.'.'.$column;
+		}
+
+		// Select all of the prefixed keys in the object
+		$this->db_builder->select($select);
+
+		if (in_array($target->object_name, $parent->belongs_to))
+		{
+			// Parent belongs_to target, use target's primary key as join column
+			$join_col1 = $target->foreign_key(TRUE, $target_path);
+			$join_col2 = $parent->foreign_key($target_name, $parent_path);
+		}
+		else
+		{
+			// Parent has_one target, use parent's primary key as join column
+			$join_col2 = $parent->foreign_key(TRUE, $parent_path);
+			$join_col1 = $parent->foreign_key($target_name, $target_path);
+		}
+
+		// This trick allows for models to use different table prefixes (sharing the same database)
+		$join_table = array($this->db->quote_table($target_path) => $target->db->quote_table($target->table_name));
+
+		// Join the related object into the result
+		// Use Database_Expression to disable prefixing
+		$this->db_builder->join(new Database_Expression($join_table), $join_col1, $join_col2, 'LEFT');
+
+		return $this;
+	}
+
+	/**
+	 * Finds and loads a single database row into the object.
+	 *
+	 * @chainable
+	 * @param   mixed  primary key or an array of clauses
+	 * @param   bool   ignore loading of columns that have been modified
+	 * @return  ORM
+	 */
+	public function find($id = NULL, $ignore_changed = FALSE)
+	{
+		if ($id !== NULL)
+		{
+			if (is_array($id))
+			{
+				// Search for all clauses
+				$this->db_builder->where(array($id));
+			}
+			else
+			{
+				// Search for a specific column
+				$this->db_builder->where($this->table_name.'.'.$this->unique_key($id), '=', $id);
+			}
+		}
+
+		return $this->load_result(FALSE, $ignore_changed);
+	}
+
+	/**
+	 * Finds multiple database rows and returns an iterator of the rows found.
+	 *
+	 * @chainable
+	 * @param   integer  SQL limit
+	 * @param   integer  SQL offset
+	 * @return  ORM_Iterator
+	 */
+	public function find_all($limit = NULL, $offset = NULL)
+	{
+		if ($limit !== NULL AND ! isset($this->db_applied['limit']))
+		{
+			// Set limit
+			$this->limit($limit);
+		}
+
+		if ($offset !== NULL AND ! isset($this->db_applied['offset']))
+		{
+			// Set offset
+			$this->offset($offset);
+		}
+
+		return $this->load_result(TRUE);
+	}
+
+	/**
+	 * Creates a key/value array from all of the objects available. Uses find_all
+	 * to find the objects.
+	 *
+	 * @param   string  key column
+	 * @param   string  value column
+	 * @return  array
+	 */
+	public function select_list($key = NULL, $val = NULL)
+	{
+		if ($key === NULL)
+		{
+			$key = $this->primary_key;
+		}
+
+		if ($val === NULL)
+		{
+			$val = $this->primary_val;
+		}
+
+		// Return a select list from the results
+		return $this->select($this->table_name.'.'.$key, $this->table_name.'.'.$val)->find_all()->select_list($key, $val);
+	}
+
+	/**
+	 * Validates the current object. This method requires that rules are set to be useful, if called with out
+	 * any rules set, or if a Validation object isn't passed, nothing happens.
+	 *
+	 * @param   object   Validation array
+	 * @param   boolean  Save on validate
+	 * @return  ORM
+	 * @chainable
+	 */
+	public function validate(Validation $array = NULL)
+	{
+		if ($array === NULL)
+			$array = new Validation($this->object);
+
+		if (count($this->rules) > 0)
+		{
+			foreach ($this->rules as $field => $parameters)
+			{
+				foreach ($parameters as $type => $value) {
+					switch ($type) {
+						case 'pre_filter':
+							$array->pre_filter($value,$field);
+							break;
+						case 'rules':
+							$rules = array_merge(array($field),$value);
+							call_user_func_array(array($array,'add_rules'), $rules);
+							break;
+						case 'callbacks':
+							$callbacks = array_merge(array($field),$value);
+							call_user_func_array(array($array,'add_callbacks'), $callbacks);
+							break;
+					}
+				}
+			}
+		}
+		// Validate the array
+		if (($this->_valid = $array->validate()) === FALSE)
+		{
+			ORM_Validation_Exception::handle_validation($this->table_name, $array);
+		}
+
+		// Fields may have been modified by filters
+		$this->object = array_merge($this->object, $array->getArrayCopy());
+
+		// Return validation status
+		return $this;
+	}
+
+	/**
+	 * Saves the current object.
+	 *
+	 * @chainable
+	 * @return  ORM
+	 */
+	public function save()
+	{
+		if ( ! empty($this->changed))
+		{
+			// Require model validation before saving
+			if ( ! $this->_valid)
+			{
+				$this->validate();
+			}
+
+			$data = array();
+			foreach ($this->changed as $column)
+			{
+				// Compile changed data
+				$data[$column] = $this->object[$column];
+			}
+
+			if ( ! $this->empty_primary_key() AND ! isset($this->changed[$this->primary_key]))
+			{
+				// Primary key isn't empty and hasn't been changed so do an update
+
+				if (is_array($this->updated_column))
+				{
+					// Fill the updated column
+					$column = $this->updated_column['column'];
+					$format = $this->updated_column['format'];
+
+					$data[$column] = $this->object[$column] = ($format === TRUE) ? time() : date($format);
+				}
+
+				$query = db::update($this->table_name)
+					->set($data)
+					->where($this->primary_key, '=', $this->primary_key_value)
+					->execute($this->db);
+
+				// Object has been saved
+				$this->_saved = TRUE;
+			}
+			else
+			{
+				if (is_array($this->created_column))
+				{
+					// Fill the created column
+					$column = $this->created_column['column'];
+					$format = $this->created_column['format'];
+
+					$data[$column] = $this->object[$column] = ($format === TRUE) ? time() : date($format);
+				}
+
+				$result = db::insert($this->table_name)
+					->columns(array_keys($data))
+					->values(array_values($data))
+					->execute($this->db);
+
+				if ($result->count() > 0)
+				{
+					if (empty($this->object[$this->primary_key]))
+					{
+						// Load the insert id as the primary key
+						$this->object[$this->primary_key] = $result->insert_id();
+					}
+
+					// Object is now loaded and saved
+					$this->_loaded = $this->_saved = TRUE;
+				}
+			}
+
+			if ($this->saved() === TRUE)
+			{
+				// All changes have been saved
+				$this->changed = array();
+			}
+		}
+
+		if ($this->saved() === TRUE AND ! empty($this->changed_relations))
+		{
+			foreach ($this->changed_relations as $column => $values)
+			{
+				// All values that were added
+				$added = array_diff($values, $this->object_relations[$column]);
+
+				// All values that were saved
+				$removed = array_diff($this->object_relations[$column], $values);
+
+				if (empty($added) AND empty($removed))
+				{
+					// No need to bother
+					continue;
+				}
+
+				// Clear related columns
+				unset($this->related[$column]);
+
+				// Load the model
+				$model = ORM::factory(inflector::singular($column));
+
+				if (($join_table = array_search($column, $this->has_and_belongs_to_many)) === FALSE)
+					continue;
+
+				if (is_int($join_table))
+				{
+					// No "through" table, load the default JOIN table
+					$join_table = $model->join_table($this->table_name);
+				}
+
+				// Foreign keys for the join table
+				$object_fk  = $this->foreign_key($join_table);
+				$related_fk = $model->foreign_key($join_table);
+
+				if ( ! empty($added))
+				{
+					foreach ($added as $id)
+					{
+						// Insert the new relationship
+						db::insert($join_table)
+							->columns($object_fk, $related_fk)
+							->values($this->primary_key_value, $id)
+							->execute($this->db);
+					}
+				}
+
+				if ( ! empty($removed))
+				{
+					db::delete($join_table)
+						->where($object_fk, '=', $this->primary_key_value)
+						->where($related_fk, 'IN', $removed)
+						->execute($this->db);
+				}
+
+				// Clear all relations for this column
+				unset($this->object_relations[$column], $this->changed_relations[$column]);
+			}
+		}
+
+		if ($this->saved() === TRUE)
+		{
+			// Always force revalidation after saving
+			$this->_valid = FALSE;
+
+			// Clear the per-request database cache
+			$this->db->clear_cache(NULL, Database::PER_REQUEST);
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Deletes the current object from the database. This does NOT destroy
+	 * relationships that have been created with other objects.
+	 *
+	 * @chainable
+	 * @param   mixed  id to delete
+	 * @return  ORM
+	 */
+	public function delete($id = NULL)
+	{
+		if ($id === NULL)
+		{
+			// Use the the primary key value
+			$id = $this->primary_key_value;
+		}
+
+		// Delete this object
+		db::delete($this->table_name)
+			->where($this->primary_key, '=', $id)
+			->execute($this->db);
+
+		// Clear the per-request database cache
+		$this->db->clear_cache(NULL, Database::PER_REQUEST);
+
+		return $this->clear();
+	}
+
+	/**
+	 * Delete all objects in the associated table. This does NOT destroy
+	 * relationships that have been created with other objects.
+	 *
+	 * @chainable
+	 * @param   array  ids to delete
+	 * @return  ORM
+	 */
+	public function delete_all($ids = NULL)
+	{
+		if (is_array($ids))
+		{
+			// Delete only given ids
+			db::delete($this->table_name)
+				->where($this->primary_key, 'IN', $ids)
+				->execute($this->db);
+		}
+		elseif ($ids === NULL)
+		{
+			// Delete all records
+			db::delete($this->table_name)
+				->execute($this->db);
+		}
+		else
+		{
+			// Do nothing - safeguard
+			return $this;
+		}
+
+		// Clear the per-request database cache
+		$this->db->clear_cache(NULL, Database::PER_REQUEST);
+
+		return $this->clear();
+	}
+
+	/**
+	 * Unloads the current object and clears the status.
+	 *
+	 * @chainable
+	 * @return  ORM
+	 */
+	public function clear()
+	{
+		// Create an array with all the columns set to NULL
+		$columns = array_keys($this->table_columns);
+		$values  = array_combine($columns, array_fill(0, count($columns), NULL));
+
+		// Replace the current object with an empty one
+		$this->_load_values($values);
+
+		return $this;
+	}
+
+	/**
+	 * Reloads the current object from the database.
+	 *
+	 * @chainable
+	 * @return  ORM
+	 */
+	public function reload()
+	{
+                if ($this->_loaded) {
+                        return $this->find($this->object[$this->primary_key]);
+                } else {
+                        return $this->clear();
+                }
+	}
+
+	/**
+	 * Reload column definitions.
+	 *
+	 * @chainable
+	 * @param   boolean  force reloading
+	 * @return  ORM
+	 */
+	public function reload_columns($force = FALSE)
+	{
+		if ($force === TRUE OR empty($this->table_columns))
+		{
+			if (isset(ORM::$column_cache[$this->object_name]))
+			{
+				// Use cached column information
+				$this->table_columns = ORM::$column_cache[$this->object_name];
+			}
+			else
+			{
+				// Load table columns
+				ORM::$column_cache[$this->object_name] = $this->table_columns = $this->list_fields();
+			}
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Tests if this object has a relationship to a different model.
+	 *
+	 * @param   object   related ORM model
+	 * @param   boolean  check for any relations to given model
+	 * @return  boolean
+	 */
+	public function has(ORM $model, $any = FALSE)
+	{
+		// Determine plural or singular relation name
+		$related = ($model->table_names_plural === TRUE) ? $model->object_plural : $model->object_name;
+
+		if (($join_table = array_search($related, $this->has_and_belongs_to_many)) === FALSE)
+			return FALSE;
+
+		if (is_int($join_table))
+		{
+			// No "through" table, load the default JOIN table
+			$join_table = $model->join_table($this->table_name);
+		}
+
+		if ( ! isset($this->object_relations[$related]))
+		{
+			// Load the object relationships
+			$this->changed_relations[$related] = $this->object_relations[$related] = $this->load_relations($join_table, $model);
+		}
+
+		if( ! $model->loaded() AND ! $model->empty_primary_key())
+		{
+			// Load the related model if it hasn't already been
+			$model->find($model->object[$model->primary_key]);
+		}
+
+		if ( ! $model->empty_primary_key())
+		{
+			// Check if a specific object exists
+			return in_array($model->primary_key_value, $this->changed_relations[$related]);
+		}
+		elseif ($any)
+		{
+			// Check if any relations to given model exist
+			return ! empty($this->changed_relations[$related]);
+		}
+		else
+		{
+			return FALSE;
+		}
+	}
+
+	/**
+	 * Adds a new relationship to between this model and another.
+	 *
+	 * @param   object   related ORM model
+	 * @return  boolean
+	 */
+	public function add(ORM $model)
+	{
+		if ($this->has($model))
+			return TRUE;
+
+		// Get the faked column name
+		$column = $model->object_plural;
+
+		// Add the new relation to the update
+		$this->changed_relations[$column][] = $model->primary_key_value;
+
+		if (isset($this->related[$column]))
+		{
+			// Force a reload of the relationships
+			unset($this->related[$column]);
+		}
+
+		return TRUE;
+	}
+
+	/**
+	 * Adds a new relationship to between this model and another.
+	 *
+	 * @param   object   related ORM model
+	 * @return  boolean
+	 */
+	public function remove(ORM $model)
+	{
+		if ( ! $this->has($model))
+			return FALSE;
+
+		// Get the faked column name
+		$column = $model->object_plural;
+
+		if (($key = array_search($model->primary_key_value, $this->changed_relations[$column])) === FALSE)
+			return FALSE;
+
+		// Remove the relationship
+		unset($this->changed_relations[$column][$key]);
+
+		if (isset($this->related[$column]))
+		{
+			// Force a reload of the relationships
+			unset($this->related[$column]);
+		}
+
+		return TRUE;
+	}
+
+	/**
+	 * Count the number of records in the table.
+	 *
+	 * @return  integer
+	 */
+	public function count_all()
+	{
+		// Return the total number of records in a table
+		return $this->db_builder->count_records($this->table_name);
+	}
+
+	/**
+	 * Proxy method to Database list_fields.
+	 *
+	 * @return  array
+	 */
+	public function list_fields()
+	{
+		// Proxy to database
+		return $this->db->list_fields($this->table_name);
+	}
+
+	/**
+	 * Proxy method to Database clear_cache.
+	 *
+	 * @chainable
+	 * @param   string  SQL query to clear
+	 * @param   integer  Type of cache to clear, Database::CROSS_REQUEST or Database::PER_REQUEST
+	 * @return  ORM
+	 */
+	public function clear_cache($sql = NULL, $type = NULL)
+	{
+		// Proxy to database
+		$this->db->clear_cache($sql, $type);
+
+		ORM::$column_cache = array();
+
+		return $this;
+	}
+
+	/**
+	 * Returns the unique key for a specific value. This method is expected
+	 * to be overloaded in models if the model has other unique columns.
+	 *
+	 * @param   mixed   unique value
+	 * @return  string
+	 */
+	public function unique_key($id)
+	{
+		return $this->primary_key;
+	}
+
+	/**
+	 * Determines the name of a foreign key for a specific table.
+	 *
+	 * @param   string  related table name
+	 * @param   string  prefix table name (used for JOINs)
+	 * @return  string
+	 */
+	public function foreign_key($table = NULL, $prefix_table = NULL)
+	{
+		if ($table === TRUE)
+		{
+			if (is_string($prefix_table))
+			{
+				// Use prefix table name and this table's PK
+				return $prefix_table.'.'.$this->primary_key;
+			}
+			else
+			{
+				// Return the name of this table's PK
+				return $this->table_name.'.'.$this->primary_key;
+			}
+		}
+
+		if (is_string($prefix_table))
+		{
+			// Add a period for prefix_table.column support
+			$prefix_table .= '.';
+		}
+
+		if (isset($this->foreign_key[$table]))
+		{
+			// Use the defined foreign key name, no magic here!
+			$foreign_key = $this->foreign_key[$table];
+		}
+		else
+		{
+			if ( ! is_string($table) OR ! array_key_exists($table.'_'.$this->primary_key, $this->object))
+			{
+				// Use this table
+				$table = $this->table_name;
+
+				if (strpos($table, '.') !== FALSE)
+				{
+					// Hack around support for PostgreSQL schemas
+					list ($schema, $table) = explode('.', $table, 2);
+				}
+
+				if ($this->table_names_plural === TRUE)
+				{
+					// Make the key name singular
+					$table = inflector::singular($table);
+				}
+			}
+
+			$foreign_key = $table.'_'.$this->primary_key;
+		}
+
+		return $prefix_table.$foreign_key;
+	}
+
+	/**
+	 * This uses alphabetical comparison to choose the name of the table.
+	 *
+	 * Example: The joining table of users and roles would be roles_users,
+	 * because "r" comes before "u". Joining products and categories would
+	 * result in categories_products, because "c" comes before "p".
+	 *
+	 * Example: zoo > zebra > robber > ocean > angel > aardvark
+	 *
+	 * @param   string  table name
+	 * @return  string
+	 */
+	public function join_table($table)
+	{
+		if ($this->table_name > $table)
+		{
+			$table = $table.'_'.$this->table_name;
+		}
+		else
+		{
+			$table = $this->table_name.'_'.$table;
+		}
+
+		return $table;
+	}
+
+	/**
+	 * Returns an ORM model for the given object name;
+	 *
+	 * @param   string  object name
+	 * @return  ORM
+	 */
+	protected function related_object($object)
+	{
+		if (isset($this->has_one[$object]))
+		{
+			$object = ORM::factory($this->has_one[$object]);
+		}
+		elseif (isset($this->belongs_to[$object]))
+		{
+			$object = ORM::factory($this->belongs_to[$object]);
+		}
+		elseif (in_array($object, $this->has_one) OR in_array($object, $this->belongs_to))
+		{
+			$object = ORM::factory($object);
+		}
+		else
+		{
+			return FALSE;
+		}
+
+		return $object;
+	}
+
+	/**
+	 * Loads an array of values into into the current object.
+	 *
+	 * @chainable
+	 * @param   array  values to load
+	 * @return  ORM
+	 */
+	public function load_values(array $values)
+	{
+		// Related objects
+		$related = array();
+
+		foreach ($values as $column => $value)
+		{
+			if (strpos($column, ':') === FALSE)
+			{
+				if ( ! isset($this->changed[$column]))
+				{
+					if (isset($this->table_columns[$column]))
+					{
+						//Update the column, respects __get()
+						$this->$column = $value;
+					}
+				}
+			}
+			else
+			{
+				list ($prefix, $column) = explode(':', $column, 2);
+
+				$related[$prefix][$column] = $value;
+			}
+		}
+
+		if ( ! empty($related))
+		{
+			foreach ($related as $object => $values)
+			{
+				// Load the related objects with the values in the result
+				$this->related[$object] = $this->related_object($object)->load_values($values);
+			}
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Loads an array of values into into the current object.  Only used internally
+	 *
+	 * @chainable
+	 * @param   array  values to load
+	 * @param   bool   ignore loading of columns that have been modified
+	 * @return  ORM
+	 */
+	public function _load_values(array $values, $ignore_changed = FALSE)
+	{
+		if (array_key_exists($this->primary_key, $values))
+		{
+			if ( ! $ignore_changed)
+			{
+				// Replace the object and reset the object status
+				$this->object = $this->changed = $this->related = array();
+			}
+
+			// Set the loaded and saved object status based on the primary key
+			$this->_loaded = $this->_saved = ($values[$this->primary_key] !== NULL);
+		}
+
+		// Related objects
+		$related = array();
+
+		foreach ($values as $column => $value)
+		{
+			if (strpos($column, ':') === FALSE)
+			{
+				if ( ! $ignore_changed OR ! isset($this->changed[$column]))
+				{
+					$this->object[$column] = $value;
+				}
+			}
+			else
+			{
+				list ($prefix, $column) = explode(':', $column, 2);
+
+				$related[$prefix][$column] = $value;
+			}
+		}
+
+		if ( ! empty($related))
+		{
+			foreach ($related as $object => $values)
+			{
+				// Load the related objects with the values in the result
+				$this->related[$object] = $this->related_object($object)->_load_values($values);
+			}
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Loads a database result, either as a new object for this model, or as
+	 * an iterator for multiple rows.
+	 *
+	 * @chainable
+	 * @param   boolean       return an iterator or load a single row
+	 * @param   boolean       ignore loading of columns that have been modified
+	 * @return  ORM           for single rows
+	 * @return  ORM_Iterator  for multiple rows
+	 */
+	protected function load_result($array = FALSE, $ignore_changed = FALSE)
+	{
+		$this->db_builder->from($this->table_name);
+
+		if ($array === FALSE)
+		{
+			// Only fetch 1 record
+			$this->db_builder->limit(1);
+		}
+
+		if ( ! isset($this->db_applied['select']))
+		{
+			// Select all columns by default
+			$this->db_builder->select($this->table_name.'.*');
+		}
+
+		if ( ! empty($this->load_with))
+		{
+			foreach ($this->load_with as $alias => $object)
+			{
+				// Join each object into the results
+				if (is_string($alias))
+				{
+					// Use alias
+					$this->with($alias);
+				}
+				else
+				{
+					// Use object
+					$this->with($object);
+				}
+			}
+		}
+
+		if ( ! isset($this->db_applied['order_by']) AND ! empty($this->sorting))
+		{
+			$sorting = array();
+			foreach ($this->sorting as $column => $direction)
+			{
+				if (strpos($column, '.') === FALSE)
+				{
+					// Keeps sorting working properly when using JOINs on
+					// tables with columns of the same name
+					$column = $this->table_name.'.'.$column;
+				}
+
+				$sorting[$column] = $direction;
+			}
+
+			// Apply the user-defined sorting
+			$this->db_builder->order_by($sorting);
+		}
+
+		// Load the result
+		$result = $this->db_builder->execute($this->db);
+                $this->db_applied = array();
+
+		if ($array === TRUE)
+		{
+			// Return an iterated result
+			return new ORM_Iterator($this, $result);
+		}
+
+		if ($result->count() === 1)
+		{
+			// Load object values
+			$this->_load_values($result->as_array()->current(), $ignore_changed);
+		}
+		else
+		{
+			// Clear the object, nothing was found
+			$this->clear();
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Return an array of all the primary keys of the related table.
+	 *
+	 * @param   string  table name
+	 * @param   object  ORM model to find relations of
+	 * @return  array
+	 */
+	protected function load_relations($table, ORM $model)
+	{
+		$result = db::select(array('id' => $model->foreign_key($table)))
+			->from($table)
+			->where($this->foreign_key($table, $table), '=', $this->primary_key_value)
+			->execute($this->db)
+			->as_object();
+
+		$relations = array();
+		foreach ($result as $row)
+		{
+			$relations[] = $row->id;
+		}
+
+		return $relations;
+	}
+
+	/**
+	 * Returns whether or not primary key is empty
+	 *
+	 * @return bool
+	 */
+	protected function empty_primary_key()
+	{
+		return (empty($this->object[$this->primary_key]) AND $this->object[$this->primary_key] !== '0');
+	}
+
+} // End ORM
diff --git a/system/libraries/ORM_Iterator.php b/system/libraries/ORM_Iterator.php
new file mode 100644
index 0000000..0bf2b47
--- /dev/null
+++ b/system/libraries/ORM_Iterator.php
@@ -0,0 +1,266 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Object Relational Mapping (ORM) result iterator.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class ORM_Iterator_Core implements Iterator, ArrayAccess, Countable {
+
+	// Class attributes
+	protected $class_name;
+	protected $primary_key;
+	protected $primary_val;
+
+	// Database result object
+	protected $result;
+
+	public function __construct(ORM $model, Database_Result $result)
+	{
+		// Class attributes
+		$this->class_name  = get_class($model);
+		$this->primary_key = $model->primary_key;
+		$this->primary_val = $model->primary_val;
+
+		// Database result (make sure rows are returned as arrays)
+		$this->result = $result;
+	}
+
+	/**
+	 * Returns an array of the results as ORM objects or a nested array
+	 *
+	 * @param   bool    TRUE to return an array of ORM objects, FALSE for an array of arrays
+	 * @param   string  key column to index on, NULL to ignore
+	 * @return  array
+	 */
+	public function as_array($objects = TRUE, $key = NULL)
+	{
+		$array = array();
+
+		// Import class name
+		$class = $this->class_name;
+
+		if ($objects)
+		{
+			// Generate an array of objects
+			foreach ($this->result as $data)
+			{
+				if ($key === NULL)
+				{
+					// No indexing
+					$array[] = new $class($data);
+				}
+				else
+				{
+					// Index on the given key
+					$array[$data->$key] = new $class($data);
+				}
+			}
+		}
+		else
+		{
+			// Generate an array of arrays (and the subarrays may be nested in the case of relationships)
+			// This could be done by creating a new ORM object and calling as_array on it, but this is much faster
+			foreach ($this->result as $data)
+			{
+				// Have to do a bit of magic here to handle any relationships and generate a nested array for them
+				$temp = array();
+
+				foreach ($data as $key => $val)
+				{
+					$ptr = & $temp;
+
+					foreach (explode(':', $key) as $subkey)
+					{
+						// Walk thru the relationships (separated in the key name by a ':')
+						// 'user:email:address' will be array['user']['email']['address']
+						$ptr = & $ptr[$subkey];
+					}
+
+					// Set the value
+					$ptr = $val;
+				}
+
+				// Append the result
+				$array[] = $temp;
+			}
+		}
+
+		return $array;
+	}
+
+	/**
+	 * Return an array of all of the primary keys for this object.
+	 *
+	 * @return  array
+	 */
+	public function primary_key_array()
+	{
+		$ids = array();
+		foreach ($this->result as $row)
+		{
+			$ids[] = $row->{$this->primary_key};
+		}
+		return $ids;
+	}
+
+	/**
+	 * Create a key/value array from the results.
+	 *
+	 * @param   string  key column
+	 * @param   string  value column
+	 * @return  array
+	 */
+	public function select_list($key = NULL, $val = NULL)
+	{
+		if ($key === NULL)
+		{
+			// Use the default key
+			$key = $this->primary_key;
+		}
+
+		if ($val === NULL)
+		{
+			// Use the default value
+			$val = $this->primary_val;
+		}
+
+		$array = array();
+		foreach ($this->result as $row)
+		{
+			$array[$row->$key] = $row->$val;
+		}
+		return $array;
+	}
+
+	/**
+	 * Return a range of offsets.
+	 *
+	 * @param   integer  start
+	 * @param   integer  end
+	 * @return  array
+	 */
+	public function range($start, $end)
+	{
+		// Array of objects
+		$array = array();
+
+		if ($this->result->offsetExists($start))
+		{
+			// Import the class name
+			$class = $this->class_name;
+
+			// Set the end offset
+			$end = $this->result->offsetExists($end) ? $end : $this->count();
+
+			for ($i = $start; $i < $end; $i++)
+			{
+				// Insert each object in the range
+				$array[] = new $class($this->result->offsetGet($i));
+			}
+		}
+
+		return $array;
+	}
+
+	/**
+	 * Countable: count
+	 */
+	public function count()
+	{
+		return $this->result->count();
+	}
+
+	/**
+	 * Iterator: current
+	 */
+	public function current()
+	{
+		if ($row = $this->result->current())
+		{
+			// Import class name
+			$class = $this->class_name;
+
+			$row = new $class($row);
+		}
+
+		return $row;
+	}
+
+	/**
+	 * Iterator: key
+	 */
+	public function key()
+	{
+		return $this->result->key();
+	}
+
+	/**
+	 * Iterator: next
+	 */
+	public function next()
+	{
+		return $this->result->next();
+	}
+
+	/**
+	 * Iterator: rewind
+	 */
+	public function rewind()
+	{
+		$this->result->rewind();
+	}
+
+	/**
+	 * Iterator: valid
+	 */
+	public function valid()
+	{
+		return $this->result->valid();
+	}
+
+	/**
+	 * ArrayAccess: offsetExists
+	 */
+	public function offsetExists($offset)
+	{
+		return $this->result->offsetExists($offset);
+	}
+
+	/**
+	 * ArrayAccess: offsetGet
+	 */
+	public function offsetGet($offset)
+	{
+		if ($this->result->offsetExists($offset))
+		{
+			// Import class name
+			$class = $this->class_name;
+
+			return new $class($this->result->offsetGet($offset));
+		}
+	}
+
+	/**
+	 * ArrayAccess: offsetSet
+	 *
+	 * @throws  Kohana_Database_Exception
+	 */
+	public function offsetSet($offset, $value)
+	{
+		throw new Kohana_Database_Exception('database.result_read_only');
+	}
+
+	/**
+	 * ArrayAccess: offsetUnset
+	 *
+	 * @throws  Kohana_Database_Exception
+	 */
+	public function offsetUnset($offset)
+	{
+		throw new Kohana_Database_Exception('database.result_read_only');
+	}
+
+} // End ORM Iterator
\ No newline at end of file
diff --git a/system/libraries/ORM_Validation_Exception.php b/system/libraries/ORM_Validation_Exception.php
new file mode 100644
index 0000000..9044aa6
--- /dev/null
+++ b/system/libraries/ORM_Validation_Exception.php
@@ -0,0 +1,24 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * ORM Validation exceptions.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2008-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class ORM_Validation_Exception_Core extends Database_Exception {
+
+	/**
+	 * Handles Database Validation Exceptions
+	 *
+	 * @param Validation $array
+	 * @return
+	 */
+	public static function handle_validation($table, Validation $array)
+	{
+		$exception = new ORM_Validation_Exception('ORM Validation has failed for :table model',array(':table'=>$table));
+		$exception->validation = $array;
+		throw $exception;
+	}
+} // End ORM_Validation_Exception
\ No newline at end of file
diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php
new file mode 100644
index 0000000..3ac8707
--- /dev/null
+++ b/system/libraries/Profiler.php
@@ -0,0 +1,306 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Adds useful information to the bottom of the current page for debugging and optimization purposes.
+ *
+ * Benchmarks   - The times and memory usage of benchmarks run by the Benchmark library.
+ * Database     - The raw SQL and number of affected rows of Database queries.
+ * Session Data - Data stored in the current session if using the Session library.
+ * POST Data    - The name and values of any POST data submitted to the current page.
+ * Cookie Data  - All cookies sent for the current request.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Profiler_Core {
+
+	protected static $profiles = array();
+	protected static $show;
+
+	/**
+	 * Enable the profiler.
+	 *
+	 * @return  void
+	 */
+	public static function enable()
+	{
+		// Add all built in profiles to event
+		Event::add('profiler.run', array('Profiler', 'benchmarks'));
+		Event::add('profiler.run', array('Profiler', 'database'));
+		Event::add('profiler.run', array('Profiler', 'session'));
+		Event::add('profiler.run', array('Profiler', 'post'));
+		Event::add('profiler.run', array('Profiler', 'cookies'));
+
+		// Add profiler to page output automatically
+		Event::add('system.display', array('Profiler', 'render'));
+
+		Kohana_Log::add('debug', 'Profiler library enabled');
+
+	}
+
+	/**
+	 * Disables the profiler for this page only.
+	 * Best used when profiler is autoloaded.
+	 *
+	 * @return  void
+	 */
+	public static function disable()
+	{
+		// Removes itself from the event queue
+		Event::clear('system.display', array('Profiler', 'render'));
+	}
+
+	/**
+	 * Return whether a profile should be shown.
+	 * Determined by the config setting or GET parameter.
+	 *
+	 * @param   string  profile name
+	 * @return  boolean
+	 */
+	public static function show($name)
+	{
+		return (Profiler::$show === TRUE OR (is_array(Profiler::$show) AND in_array($name, Profiler::$show))) ? TRUE : FALSE;
+	}
+
+	/**
+	 * Add a new profile.
+	 *
+	 * @param   object   profile object
+	 * @return  boolean
+	 * @throws  Kohana_Exception
+	 */
+	public static function add($profile)
+	{
+		if (is_object($profile))
+		{
+			Profiler::$profiles[] = $profile;
+			return TRUE;
+		}
+
+		throw new Kohana_Exception('The profile must be an object');
+	}
+
+	/**
+	 * Render the profiler.
+	 *
+	 * @param   boolean  return the output instead of adding it to bottom of page
+	 * @return  void|string
+	 */
+	public static function render($return = FALSE)
+	{
+		$start = microtime(TRUE);
+
+		// Determine the profiles that should be shown
+		$get = isset($_GET['profiler']) ? explode(',', $_GET['profiler']) : array();
+		Profiler::$show = empty($get) ? Kohana::config('profiler.show') : $get;
+
+		Event::run('profiler.run');
+
+		// Don't display if there's no profiles
+		if (empty(Profiler::$profiles))
+			return Kohana::$output;
+
+		$styles = '';
+		foreach (Profiler::$profiles as $profile)
+		{
+			$styles .= $profile->styles();
+		}
+
+		// Load the profiler view
+		$data = array
+		(
+			'profiles'       => Profiler::$profiles,
+			'styles'         => $styles,
+			'execution_time' => microtime(TRUE) - $start
+		);
+		$view = new View('profiler/profiler', $data);
+
+		// Return rendered view if $return is TRUE
+		if ($return === TRUE)
+			return $view->render();
+
+		// Add profiler data to the output
+		if (stripos(Kohana::$output, '</body>') !== FALSE)
+		{
+			// Closing body tag was found, insert the profiler data before it
+			Kohana::$output = str_ireplace('</body>', $view->render().'</body>', Kohana::$output);
+		}
+		else
+		{
+			// Append the profiler data to the output
+			Kohana::$output .= $view->render();
+		}
+	}
+
+	/**
+	 * Benchmark times and memory usage from the Benchmark library.
+	 *
+	 * @return  void
+	 */
+	public static function benchmarks()
+	{
+		if ( ! Profiler::show('benchmarks'))
+			return;
+
+		$table = new Profiler_Table();
+		$table->add_column();
+		$table->add_column('kp-column kp-data');
+		$table->add_column('kp-column kp-data');
+		$table->add_column('kp-column kp-data');
+		$table->add_row(array(__('Benchmarks'), __('Count'), __('Time'), __('Memory')), 'kp-title', 'background-color: #FFE0E0');
+
+		$benchmarks = Benchmark::get(TRUE);
+
+		// Moves the first benchmark (total execution time) to the end of the array
+		$benchmarks = array_slice($benchmarks, 1) + array_slice($benchmarks, 0, 1);
+
+		text::alternate();
+		foreach ($benchmarks as $name => $benchmark)
+		{
+			// Clean unique id from system benchmark names
+			$name = ucwords(str_replace(array('_', '-'), ' ', str_replace(SYSTEM_BENCHMARK.'_', '', $name)));
+
+			$data = array(__($name), $benchmark['count'], number_format($benchmark['time'], Kohana::config('profiler.time_decimals')), number_format($benchmark['memory'] / 1024 / 1024, Kohana::config('profiler.memory_decimals')).'MB');
+			$class = text::alternate('', 'kp-altrow');
+
+			if ($name == 'Total Execution')
+			{
+				// Clear the count column
+				$data[1] = '';
+				$class = 'kp-totalrow';
+			}
+
+			$table->add_row($data, $class);
+		}
+
+		Profiler::add($table);
+	}
+
+	/**
+	 * Database query benchmarks.
+	 *
+	 * @return  void
+	 */
+	public static function database()
+	{
+		if ( ! Profiler::show('database'))
+			return;
+
+		$queries = Database::$benchmarks;
+
+		// Don't show if there are no queries
+		if (empty($queries)) return;
+
+		$table = new Profiler_Table();
+		$table->add_column();
+		$table->add_column('kp-column kp-data');
+		$table->add_column('kp-column kp-data');
+		$table->add_row(array(__('Queries'), __('Time'), __('Rows')), 'kp-title', 'background-color: #E0FFE0');
+
+		text::alternate();
+		$total_time = $total_rows = 0;
+		foreach ($queries as $query)
+		{
+			$data = array($query['query'], number_format($query['time'], Kohana::config('profiler.time_decimals')), $query['rows']);
+			$class = text::alternate('', 'kp-altrow');
+			$table->add_row($data, $class);
+			$total_time += $query['time'];
+			$total_rows += $query['rows'];
+		}
+
+		$data = array(__('Total: ') . count($queries), number_format($total_time, Kohana::config('profiler.time_decimals')), $total_rows);
+		$table->add_row($data, 'kp-totalrow');
+
+		Profiler::add($table);
+	}
+
+	/**
+	 * Session data.
+	 *
+	 * @return  void
+	 */
+	public static function session()
+	{
+		if (empty($_SESSION)) return;
+
+		if ( ! Profiler::show('session'))
+			return;
+
+		$table = new Profiler_Table();
+		$table->add_column('kp-name');
+		$table->add_column();
+		$table->add_row(array(__('Session'), __('Value')), 'kp-title', 'background-color: #CCE8FB');
+
+		text::alternate();
+		foreach($_SESSION as $name => $value)
+		{
+			if (is_object($value))
+			{
+				$value = get_class($value).' [object]';
+			}
+
+			$data = array($name, $value);
+			$class = text::alternate('', 'kp-altrow');
+			$table->add_row($data, $class);
+		}
+
+		Profiler::add($table);
+	}
+
+	/**
+	 * POST data.
+	 *
+	 * @return  void
+	 */
+	public static function post()
+	{
+		if (empty($_POST)) return;
+
+		if ( ! Profiler::show('post'))
+			return;
+
+		$table = new Profiler_Table();
+		$table->add_column('kp-name');
+		$table->add_column();
+		$table->add_row(array(__('POST'), __('Value')), 'kp-title', 'background-color: #E0E0FF');
+
+		text::alternate();
+		foreach($_POST as $name => $value)
+		{
+			$data = array($name, $value);
+			$class = text::alternate('', 'kp-altrow');
+			$table->add_row($data, $class);
+		}
+
+		Profiler::add($table);
+	}
+
+	/**
+	 * Cookie data.
+	 *
+	 * @return  void
+	 */
+	public static function cookies()
+	{
+		if (empty($_COOKIE)) return;
+
+		if ( ! Profiler::show('cookies'))
+			return;
+
+		$table = new Profiler_Table();
+		$table->add_column('kp-name');
+		$table->add_column();
+		$table->add_row(array(__('Cookies'), __('Value')), 'kp-title', 'background-color: #FFF4D7');
+
+		text::alternate();
+		foreach($_COOKIE as $name => $value)
+		{
+			$data = array($name, $value);
+			$class = text::alternate('', 'kp-altrow');
+			$table->add_row($data, $class);
+		}
+
+		Profiler::add($table);
+	}
+}
diff --git a/system/libraries/Profiler_Table.php b/system/libraries/Profiler_Table.php
new file mode 100644
index 0000000..e590ad7
--- /dev/null
+++ b/system/libraries/Profiler_Table.php
@@ -0,0 +1,67 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Provides a table layout for sections in the Profiler library.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Profiler_Table_Core {
+
+	protected $columns = array();
+	protected $rows = array();
+
+	/**
+	 * Get styles for table.
+	 *
+	 * @return  string
+	 */
+	public function styles()
+	{
+		static $styles_output;
+
+		if ( ! $styles_output)
+		{
+			$styles_output = TRUE;
+			return file_get_contents(Kohana::find_file('views', 'profiler/table', FALSE, 'css'));
+		}
+
+		return '';
+	}
+
+	/**
+	 * Add column to table.
+	 *
+	 * @param  string  CSS class
+	 * @param  string  CSS style
+	 */
+	public function add_column($class = '', $style = '')
+	{
+		$this->columns[] = array('class' => $class, 'style' => $style);
+	}
+
+	/**
+	 * Add row to table.
+	 *
+	 * @param  array   data to go in table cells
+	 * @param  string  CSS class
+	 * @param  string  CSS style
+	 */
+	public function add_row($data, $class = '', $style = '')
+	{
+		$this->rows[] = array('data' => $data, 'class' => $class, 'style' => $style);
+	}
+
+	/**
+	 * Render table.
+	 *
+	 * @return  string
+	 */
+	public function render()
+	{
+		$data['rows'] = $this->rows;
+		$data['columns'] = $this->columns;
+		return View::factory('profiler/table', $data)->render();
+	}
+}
\ No newline at end of file
diff --git a/system/libraries/Router.php b/system/libraries/Router.php
new file mode 100644
index 0000000..c36121d
--- /dev/null
+++ b/system/libraries/Router.php
@@ -0,0 +1,315 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Router
+ *
+ * $Id: Router.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Router_Core {
+
+	protected static $routes;
+
+	public static $current_uri  = '';
+	public static $query_string = '';
+	public static $complete_uri = '';
+	public static $routed_uri   = '';
+	public static $url_suffix   = '';
+
+	public static $segments;
+	public static $rsegments;
+
+	public static $controller;
+	public static $controller_path;
+
+	public static $method    = 'index';
+	public static $arguments = array();
+
+	/**
+	 * Router setup routine. Automatically called during Kohana setup process.
+	 *
+	 * @return  void
+	 */
+	public static function setup()
+	{
+		if ( ! empty($_SERVER['QUERY_STRING']))
+		{
+			// Set the query string to the current query string
+			Router::$query_string = '?'.urldecode(trim($_SERVER['QUERY_STRING'], '&'));
+		}
+
+		if (Router::$routes === NULL)
+		{
+			// Load routes
+			Router::$routes = Kohana::config('routes');
+		}
+
+		// Default route status
+		$default_route = FALSE;
+
+		if (Router::$current_uri === '')
+		{
+			// Make sure the default route is set
+			if (empty(Router::$routes['_default']))
+				throw new Kohana_Exception('Please set a default route in config/routes.php.');
+
+			// Use the default route when no segments exist
+			Router::$current_uri = Router::$routes['_default'];
+
+			// Default route is in use
+			$default_route = TRUE;
+		}
+
+		// Remove all dot-paths from the URI, they are not valid
+		Router::$current_uri = preg_replace('#\.[\s./]*/#', '', Router::$current_uri);
+
+		// At this point routed URI and current URI are the same
+		Router::$routed_uri = Router::$current_uri = trim(Router::$current_uri, '/');
+
+		if ($default_route === TRUE)
+		{
+			Router::$complete_uri = Router::$query_string;
+			Router::$current_uri = '';
+			Router::$segments = array();
+		}
+		else
+		{
+			Router::$complete_uri = Router::$current_uri.Router::$query_string;
+
+			// Explode the segments by slashes
+			Router::$segments = explode('/', Router::$current_uri);
+
+			if (count(Router::$routes) > 1)
+			{
+				// Custom routing
+				Router::$routed_uri = Router::routed_uri(Router::$current_uri);
+			}
+		}
+
+		// Explode the routed segments by slashes
+		Router::$rsegments = explode('/', Router::$routed_uri);
+
+		// Prepare to find the controller
+		$controller_path = '';
+		$method_segment  = NULL;
+
+		// Paths to search
+		$paths = Kohana::include_paths();
+
+		foreach (Router::$rsegments as $key => $segment)
+		{
+			// Add the segment to the search path
+			$controller_path .= $segment;
+
+			$found = FALSE;
+			foreach ($paths as $dir)
+			{
+				// Search within controllers only
+				$dir .= 'controllers/';
+
+				if (is_dir($dir.$controller_path) OR is_file($dir.$controller_path.EXT))
+				{
+					// Valid path
+					$found = TRUE;
+
+					// The controller must be a file that exists with the search path
+					if ($c = str_replace('\\', '/', realpath($dir.$controller_path.EXT))
+					    AND is_file($c) AND strpos($c, $dir) === 0)
+					{
+						// Set controller name
+						Router::$controller = $segment;
+
+						// Change controller path
+						Router::$controller_path = $c;
+
+						// Set the method segment
+						$method_segment = $key + 1;
+
+						// Stop searching
+						break;
+					}
+				}
+			}
+
+			if ($found === FALSE)
+			{
+				// Maximum depth has been reached, stop searching
+				break;
+			}
+
+			// Add another slash
+			$controller_path .= '/';
+		}
+
+		if ($method_segment !== NULL AND isset(Router::$rsegments[$method_segment]))
+		{
+			// Set method
+			Router::$method = Router::$rsegments[$method_segment];
+
+			if (isset(Router::$rsegments[$method_segment + 1]))
+			{
+				// Set arguments
+				Router::$arguments = array_slice(Router::$rsegments, $method_segment + 1);
+			}
+		}
+
+		// Last chance to set routing before a 404 is triggered
+		Event::run('system.post_routing');
+
+		if (Router::$controller === NULL)
+		{
+			// No controller was found, so no page can be rendered
+			Event::run('system.404');
+		}
+	}
+
+	/**
+	 * Attempts to determine the current URI using CLI, GET, PATH_INFO, ORIG_PATH_INFO, or PHP_SELF.
+	 *
+	 * @return  void
+	 */
+	public static function find_uri()
+	{
+		if (Kohana::$server_api === 'cli')
+		{
+			// Command line requires a bit of hacking
+			if (isset($_SERVER['argv'][1]))
+			{
+				Router::$current_uri = $_SERVER['argv'][1];
+
+				// Remove GET string from segments
+				if (strpos(Router::$current_uri, '?') !== FALSE)
+				{
+					list(Router::$current_uri, $query) = explode('?', Router::$current_uri, 2);
+
+					// Parse the query string into $_GET
+					parse_str($query, $_GET);
+
+					// Convert $_GET to UTF-8
+					$_GET = Input::clean($_GET);
+				}
+			}
+		}
+		elseif (isset($_GET['kohana_uri']))
+		{
+			// Use the URI defined in the query string
+			Router::$current_uri = $_GET['kohana_uri'];
+
+			// Remove the URI from $_GET
+			unset($_GET['kohana_uri']);
+
+			// Remove the URI from $_SERVER['QUERY_STRING']
+			$_SERVER['QUERY_STRING'] = preg_replace('~\bkohana_uri\b[^&]*+&?~', '', $_SERVER['QUERY_STRING']);
+		}
+		else
+		{
+			if (isset($_SERVER['PATH_INFO']) AND $_SERVER['PATH_INFO'])
+			{
+				Router::$current_uri = $_SERVER['PATH_INFO'];
+			}
+			elseif (isset($_SERVER['ORIG_PATH_INFO']) AND $_SERVER['ORIG_PATH_INFO'])
+			{
+				Router::$current_uri = $_SERVER['ORIG_PATH_INFO'];
+			}
+			elseif (isset($_SERVER['PHP_SELF']) AND $_SERVER['PHP_SELF'])
+			{
+				// PATH_INFO is empty during requests to the front controller
+				Router::$current_uri = $_SERVER['PHP_SELF'];
+			}
+
+			if (isset($_SERVER['SCRIPT_NAME']) AND $_SERVER['SCRIPT_NAME'])
+			{
+				// Clean up PATH_INFO fallbacks
+				// PATH_INFO may be formatted for ISAPI instead of CGI on IIS
+				if (strncmp(Router::$current_uri, $_SERVER['SCRIPT_NAME'], strlen($_SERVER['SCRIPT_NAME'])) === 0)
+				{
+					// Remove the front controller from the current uri
+					Router::$current_uri = (string) substr(Router::$current_uri, strlen($_SERVER['SCRIPT_NAME']));
+				}
+			}
+		}
+
+		// Remove slashes from the start and end of the URI
+		Router::$current_uri = trim(Router::$current_uri, '/');
+
+		if (Router::$current_uri !== '')
+		{
+			if ($suffix = Kohana::config('core.url_suffix') AND strpos(Router::$current_uri, $suffix) !== FALSE)
+			{
+				// Remove the URL suffix
+				Router::$current_uri = preg_replace('#'.preg_quote($suffix).'$#u', '', Router::$current_uri);
+
+				// Set the URL suffix
+				Router::$url_suffix = $suffix;
+			}
+
+			// Reduce multiple slashes into single slashes
+			Router::$current_uri = preg_replace('#//+#', '/', Router::$current_uri);
+		}
+	}
+
+	/**
+	 * Generates routed URI from given URI.
+	 *
+	 * @param  string  URI to convert
+	 * @return string  Routed uri
+	 */
+	public static function routed_uri($uri)
+	{
+		if (Router::$routes === NULL)
+		{
+			// Load routes
+			Router::$routes = Kohana::config('routes');
+		}
+
+		// Prepare variables
+		$routed_uri = $uri = trim($uri, '/');
+
+		if (isset(Router::$routes[$uri]))
+		{
+			// Literal match, no need for regex
+			$routed_uri = Router::$routes[$uri];
+		}
+		else
+		{
+			// Loop through the routes and see if anything matches
+			foreach (Router::$routes as $key => $val)
+			{
+				if ($key === '_default') continue;
+
+				// Trim slashes
+				$key = trim($key, '/');
+				$val = trim($val, '/');
+
+				if (preg_match('#^'.$key.'$#u', $uri))
+				{
+					if (strpos($val, '$') !== FALSE)
+					{
+						// Use regex routing
+						$routed_uri = preg_replace('#^'.$key.'$#u', $val, $uri);
+					}
+					else
+					{
+						// Standard routing
+						$routed_uri = $val;
+					}
+
+					// A valid route has been found
+					break;
+				}
+			}
+		}
+
+		if (isset(Router::$routes[$routed_uri]))
+		{
+			// Check for double routing (without regex)
+			$routed_uri = Router::$routes[$routed_uri];
+		}
+
+		return trim($routed_uri, '/');
+	}
+
+} // End Router
\ No newline at end of file
diff --git a/system/libraries/Session.php b/system/libraries/Session.php
new file mode 100644
index 0000000..e57908e
--- /dev/null
+++ b/system/libraries/Session.php
@@ -0,0 +1,500 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Session library.
+ *
+ * $Id: Session.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Session_Core {
+
+	// Session singleton
+	protected static $instance;
+
+	// Protected key names (cannot be set by the user)
+	protected static $protect = array('session_id', 'user_agent', 'last_activity', 'ip_address', 'total_hits', '_kf_flash_');
+
+	// Configuration and driver
+	protected static $config;
+	protected static $driver;
+
+	// Flash variables
+	protected static $flash;
+
+	// Input library
+	protected $input;
+
+	// Automatically save the session by default
+	public static $should_save = true;
+
+	/**
+	 * Singleton instance of Session.
+	 *
+	 * @param string Force a specific session_id
+	 */
+	public static function instance($session_id = NULL)
+	{
+		if (Session::$instance == NULL)
+		{
+			// Create a new instance
+			new Session($session_id);
+		}
+		elseif( ! is_null($session_id) AND $session_id != session_id() )
+		{
+			throw new Kohana_Exception('A session (SID: :session:) is already open, cannot open the specified session (SID: :new_session:).', array(':session:' => session_id(), ':new_session:' => $session_id));
+		}
+
+		return Session::$instance;
+	}
+
+	/**
+	 * Be sure to block the use of __clone.
+	 */
+	private function __clone(){}
+
+	/**
+	 * On first session instance creation, sets up the driver and creates session.
+	 *
+	 * @param string Force a specific session_id
+	 */
+	protected function __construct($session_id = NULL)
+	{
+		$this->input = Input::instance();
+
+		// This part only needs to be run once
+		if (Session::$instance === NULL)
+		{
+			// Load config
+			Session::$config = Kohana::config('session');
+
+			// Makes a mirrored array, eg: foo=foo
+			Session::$protect = array_combine(Session::$protect, Session::$protect);
+
+			// Configure garbage collection
+			ini_set('session.gc_probability', (int) Session::$config['gc_probability']);
+			ini_set('session.gc_divisor', 100);
+			ini_set('session.gc_maxlifetime', (Session::$config['expiration'] == 0) ? 86400 : Session::$config['expiration']);
+
+			// Create a new session
+			$this->create(NULL, $session_id);
+
+			if (Session::$config['regenerate'] > 0 AND ($_SESSION['total_hits'] % Session::$config['regenerate']) === 0)
+			{
+				// Regenerate session id and update session cookie
+				$this->regenerate();
+			}
+			else
+			{
+				// Always update session cookie to keep the session alive
+				cookie::set(Session::$config['name'], $_SESSION['session_id'], Session::$config['expiration']);
+			}
+
+			// Close the session on system shutdown (run before sending the headers), so that
+			// the session cookie(s) can be written.
+			Event::add('system.shutdown', array($this, 'write_close'));
+
+			// Singleton instance
+			Session::$instance = $this;
+		}
+
+		Kohana_Log::add('debug', 'Session Library initialized');
+	}
+
+	/**
+	 * Get the session id.
+	 *
+	 * @return  string
+	 */
+	public function id()
+	{
+		return $_SESSION['session_id'];
+	}
+
+	/**
+	 * Create a new session.
+	 *
+	 * @param   array  variables to set after creation
+	 * @param   string Force a specific session_id
+	 * @return  void
+	 */
+	public function create($vars = NULL, $session_id = NULL)
+	{
+		// Destroy any current sessions
+		$this->destroy();
+
+		if (Session::$config['driver'] !== 'native')
+		{
+			// Set driver name
+			$driver = 'Session_'.ucfirst(Session::$config['driver']).'_Driver';
+
+			// Load the driver
+			if ( ! Kohana::auto_load($driver))
+				throw new Kohana_Exception('The :driver: driver for the :library: library could not be found',
+										   array(':driver:' => Session::$config['driver'], ':library:' => get_class($this)));
+
+			// Initialize the driver
+			Session::$driver = new $driver();
+
+			// Validate the driver
+			if ( ! (Session::$driver instanceof Session_Driver))
+				throw new Kohana_Exception('The :driver: driver for the :library: library must implement the :interface: interface',
+										   array(':driver:' => Session::$config['driver'], ':library:' => get_class($this), ':interface:' => 'Session_Driver'));
+
+			// Register non-native driver as the session handler
+			session_set_save_handler
+			(
+				array(Session::$driver, 'open'),
+				array(Session::$driver, 'close'),
+				array(Session::$driver, 'read'),
+				array(Session::$driver, 'write'),
+				array(Session::$driver, 'destroy'),
+				array(Session::$driver, 'gc')
+			);
+		}
+
+		// Validate the session name
+		if ( ! preg_match('~^(?=.*[a-z])[a-z0-9_]++$~iD', Session::$config['name']))
+			throw new Kohana_Exception('The session_name, :session:, is invalid. It must contain only alphanumeric characters and underscores. Also at least one letter must be present.', array(':session:' => Session::$config['name']));
+
+		// Name the session, this will also be the name of the cookie
+		session_name(Session::$config['name']);
+
+		// Set the session cookie parameters
+		session_set_cookie_params
+		(
+			Session::$config['expiration'],
+			Kohana::config('cookie.path'),
+			Kohana::config('cookie.domain'),
+			Kohana::config('cookie.secure'),
+			Kohana::config('cookie.httponly')
+		);
+
+		$cookie = cookie::get(Session::$config['name']);
+		
+		if ($session_id === NULL)
+		{
+			// Reopen session from signed cookie value.
+			$session_id = $cookie;
+		}
+
+		// Reopen an existing session if supplied
+		if ( ! is_null($session_id))
+		{
+			session_id($session_id);
+		}
+
+		// Start the session!
+		session_start();
+
+		// Put session_id in the session variable
+		$_SESSION['session_id'] = session_id();
+
+		// Set defaults
+		if ( ! isset($_SESSION['_kf_flash_']))
+		{
+			$_SESSION['total_hits'] = 0;
+			$_SESSION['_kf_flash_'] = array();
+
+			$_SESSION['user_agent'] = request::user_agent();
+			$_SESSION['ip_address'] = $this->input->ip_address();
+		}
+
+		// Set up flash variables
+		Session::$flash =& $_SESSION['_kf_flash_'];
+
+		// Increase total hits
+		$_SESSION['total_hits'] += 1;
+
+		// Validate data only on hits after one
+		if ($_SESSION['total_hits'] > 1)
+		{
+			// Validate the session
+			foreach (Session::$config['validate'] as $valid)
+			{
+				switch ($valid)
+				{
+					// Check user agent for consistency
+					case 'user_agent':
+						if ($_SESSION[$valid] !== request::user_agent())
+							return $this->create();
+					break;
+
+					// Check ip address for consistency
+					case 'ip_address':
+						if ($_SESSION[$valid] !== $this->input->$valid())
+							return $this->create();
+					break;
+
+					// Check expiration time to prevent users from manually modifying it
+					case 'expiration':
+						if (time() - $_SESSION['last_activity'] > ini_get('session.gc_maxlifetime'))
+							return $this->create();
+					break;
+				}
+			}
+		}
+
+		// Expire flash keys
+		$this->expire_flash();
+
+		// Update last activity
+		$_SESSION['last_activity'] = time();
+
+		// Set the new data
+		Session::set($vars);
+	}
+
+	/**
+	 * Regenerates the global session id.
+	 *
+	 * @return  void
+	 */
+	public function regenerate()
+	{
+		if (Session::$config['driver'] === 'native')
+		{
+			// Generate a new session id
+			// Note: also sets a new session cookie with the updated id
+			session_regenerate_id(TRUE);
+
+			// Update session with new id
+			$_SESSION['session_id'] = session_id();
+		}
+		else
+		{
+			// Pass the regenerating off to the driver in case it wants to do anything special
+			$_SESSION['session_id'] = Session::$driver->regenerate();
+		}
+
+		// Get the session name
+		$name = session_name();
+
+		if (isset($_COOKIE[$name]))
+		{
+			// Change the cookie value to match the new session id to prevent "lag"
+			cookie::set($name, $_SESSION['session_id']);
+		}
+	}
+
+	/**
+	 * Destroys the current session.
+	 *
+	 * @return  void
+	 */
+	public function destroy()
+	{
+		if (session_id() !== '')
+		{
+			// Get the session name
+			$name = session_name();
+
+			// Destroy the session
+			session_destroy();
+
+			// Re-initialize the array
+			$_SESSION = array();
+
+			// Delete the session cookie
+			cookie::delete($name);
+		}
+	}
+
+	/**
+	 * Runs the system.session_write event, then calls session_write_close.
+	 *
+	 * @return  void
+	 */
+	public function write_close()
+	{
+		static $run;
+
+		if ($run === NULL)
+		{
+			$run = TRUE;
+
+			// Run the events that depend on the session being open
+			Event::run('system.session_write');
+
+			// Expire flash keys
+			$this->expire_flash();
+
+			// Close the session
+			session_write_close();
+		}
+	}
+
+	/**
+	 * Set a session variable.
+	 *
+	 * @param   string|array  key, or array of values
+	 * @param   mixed         value (if keys is not an array)
+	 * @return  void
+	 */
+	public function set($keys, $val = FALSE)
+	{
+		if (empty($keys))
+			return FALSE;
+
+		if ( ! is_array($keys))
+		{
+			$keys = array($keys => $val);
+		}
+
+		foreach ($keys as $key => $val)
+		{
+			if (isset(Session::$protect[$key]))
+				continue;
+
+			// Set the key
+			$_SESSION[$key] = $val;
+		}
+	}
+
+	/**
+	 * Set a flash variable.
+	 *
+	 * @param   string|array  key, or array of values
+	 * @param   mixed         value (if keys is not an array)
+	 * @return  void
+	 */
+	public function set_flash($keys, $val = FALSE)
+	{
+		if (empty($keys))
+			return FALSE;
+
+		if ( ! is_array($keys))
+		{
+			$keys = array($keys => $val);
+		}
+
+		foreach ($keys as $key => $val)
+		{
+			if ($key == FALSE)
+				continue;
+
+			Session::$flash[$key] = 'new';
+			Session::set($key, $val);
+		}
+	}
+
+	/**
+	 * Freshen one, multiple or all flash variables.
+	 *
+	 * @param   string  variable key(s)
+	 * @return  void
+	 */
+	public function keep_flash($keys = NULL)
+	{
+		$keys = ($keys === NULL) ? array_keys(Session::$flash) : func_get_args();
+
+		foreach ($keys as $key)
+		{
+			if (isset(Session::$flash[$key]))
+			{
+				Session::$flash[$key] = 'new';
+			}
+		}
+	}
+
+	/**
+	 * Expires old flash data and removes it from the session.
+	 *
+	 * @return  void
+	 */
+	public function expire_flash()
+	{
+		static $run;
+
+		// Method can only be run once
+		if ($run === TRUE)
+			return;
+
+		if ( ! empty(Session::$flash))
+		{
+			foreach (Session::$flash as $key => $state)
+			{
+				if ($state === 'old')
+				{
+					// Flash has expired
+					unset(Session::$flash[$key], $_SESSION[$key]);
+				}
+				else
+				{
+					// Flash will expire
+					Session::$flash[$key] = 'old';
+				}
+			}
+		}
+
+		// Method has been run
+		$run = TRUE;
+	}
+
+	/**
+	 * Get a variable. Access to sub-arrays is supported with key.subkey.
+	 *
+	 * @param   string  variable key
+	 * @param   mixed   default value returned if variable does not exist
+	 * @return  mixed   Variable data if key specified, otherwise array containing all session data.
+	 */
+	public function get($key = FALSE, $default = FALSE)
+	{
+		if (empty($key))
+			return $_SESSION;
+
+		$result = isset($_SESSION[$key]) ? $_SESSION[$key] : Kohana::key_string($_SESSION, $key);
+
+		return ($result === NULL) ? $default : $result;
+	}
+
+	/**
+	 * Get a variable, and delete it.
+	 *
+	 * @param   string  variable key
+	 * @param   mixed   default value returned if variable does not exist
+	 * @return  mixed
+	 */
+	public function get_once($key, $default = FALSE)
+	{
+		$return = Session::get($key, $default);
+		Session::delete($key);
+
+		return $return;
+	}
+
+	/**
+	 * Delete one or more variables.
+	 *
+	 * @param   string  variable key(s)
+	 * @return  void
+	 */
+	public function delete($keys)
+	{
+		$args = func_get_args();
+
+		foreach ($args as $key)
+		{
+			if (isset(Session::$protect[$key]))
+				continue;
+
+			// Unset the key
+			unset($_SESSION[$key]);
+		}
+	}
+
+	/**
+	 * Do not save this session.
+	 * This is a performance feature only, if using the native
+	 * session "driver" the save will NOT be aborted.
+	 *
+	 * @return  void
+	 */
+	public function abort_save()
+	{
+		Session::$should_save = FALSE;
+	}
+
+} // End Session Class
diff --git a/system/libraries/URI.php b/system/libraries/URI.php
new file mode 100644
index 0000000..16d101a
--- /dev/null
+++ b/system/libraries/URI.php
@@ -0,0 +1,279 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * URI library.
+ *
+ * $Id: URI.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class URI_Core extends Router {
+
+	/**
+	 * Returns a singleton instance of URI.
+	 *
+	 * @return  object
+	 */
+	public static function instance()
+	{
+		static $instance;
+
+		if ($instance == NULL)
+		{
+			// Initialize the URI instance
+			$instance = new URI;
+		}
+
+		return $instance;
+	}
+
+	/**
+	 * Retrieve a specific URI segment.
+	 *
+	 * @param   integer|string  segment number or label
+	 * @param   mixed           default value returned if segment does not exist
+	 * @return  string
+	 */
+	public function segment($index = 1, $default = FALSE)
+	{
+		if (is_string($index))
+		{
+			if (($key = array_search($index, URI::$segments)) === FALSE)
+				return $default;
+
+			$index = $key + 2;
+		}
+
+		$index = (int) $index - 1;
+
+		return isset(URI::$segments[$index]) ? URI::$segments[$index] : $default;
+	}
+
+	/**
+	 * Retrieve a specific routed URI segment.
+	 *
+	 * @param   integer|string  rsegment number or label
+	 * @param   mixed           default value returned if segment does not exist
+	 * @return  string
+	 */
+	public function rsegment($index = 1, $default = FALSE)
+	{
+		if (is_string($index))
+		{
+			if (($key = array_search($index, URI::$rsegments)) === FALSE)
+				return $default;
+
+			$index = $key + 2;
+		}
+
+		$index = (int) $index - 1;
+
+		return isset(URI::$rsegments[$index]) ? URI::$rsegments[$index] : $default;
+	}
+
+	/**
+	 * Retrieve a specific URI argument.
+	 * This is the part of the segments that does not indicate controller or method
+	 *
+	 * @param   integer|string  argument number or label
+	 * @param   mixed           default value returned if segment does not exist
+	 * @return  string
+	 */
+	public function argument($index = 1, $default = FALSE)
+	{
+		if (is_string($index))
+		{
+			if (($key = array_search($index, URI::$arguments)) === FALSE)
+				return $default;
+
+			$index = $key + 2;
+		}
+
+		$index = (int) $index - 1;
+
+		return isset(URI::$arguments[$index]) ? URI::$arguments[$index] : $default;
+	}
+
+	/**
+	 * Returns an array containing all the URI segments.
+	 *
+	 * @param   integer  segment offset
+	 * @param   boolean  return an associative array
+	 * @return  array
+	 */
+	public function segment_array($offset = 0, $associative = FALSE)
+	{
+		return $this->build_array(URI::$segments, $offset, $associative);
+	}
+
+	/**
+	 * Returns an array containing all the re-routed URI segments.
+	 *
+	 * @param   integer  rsegment offset
+	 * @param   boolean  return an associative array
+	 * @return  array
+	 */
+	public function rsegment_array($offset = 0, $associative = FALSE)
+	{
+		return $this->build_array(URI::$rsegments, $offset, $associative);
+	}
+
+	/**
+	 * Returns an array containing all the URI arguments.
+	 *
+	 * @param   integer  segment offset
+	 * @param   boolean  return an associative array
+	 * @return  array
+	 */
+	public function argument_array($offset = 0, $associative = FALSE)
+	{
+		return $this->build_array(URI::$arguments, $offset, $associative);
+	}
+
+	/**
+	 * Creates a simple or associative array from an array and an offset.
+	 * Used as a helper for (r)segment_array and argument_array.
+	 *
+	 * @param   array    array to rebuild
+	 * @param   integer  offset to start from
+	 * @param   boolean  create an associative array
+	 * @return  array
+	 */
+	public function build_array($array, $offset = 0, $associative = FALSE)
+	{
+		// Prevent the keys from being improperly indexed
+		array_unshift($array, 0);
+
+		// Slice the array, preserving the keys
+		$array = array_slice($array, $offset + 1, count($array) - 1, TRUE);
+
+		if ($associative === FALSE)
+			return $array;
+
+		$associative = array();
+		$pairs       = array_chunk($array, 2);
+
+		foreach ($pairs as $pair)
+		{
+			// Add the key/value pair to the associative array
+			$associative[$pair[0]] = isset($pair[1]) ? $pair[1] : '';
+		}
+
+		return $associative;
+	}
+
+	/**
+	 * Returns the complete URI as a string.
+	 *
+	 * @return  string
+	 */
+	public function string()
+	{
+		return URI::$current_uri;
+	}
+
+	/**
+	 * Magic method for converting an object to a string.
+	 *
+	 * @return  string
+	 */
+	public function __toString()
+	{
+		return URI::$current_uri;
+	}
+
+	/**
+	 * Returns the total number of URI segments.
+	 *
+	 * @return  integer
+	 */
+	public function total_segments()
+	{
+		return count(URI::$segments);
+	}
+
+	/**
+	 * Returns the total number of re-routed URI segments.
+	 *
+	 * @return  integer
+	 */
+	public function total_rsegments()
+	{
+		return count(URI::$rsegments);
+	}
+
+	/**
+	 * Returns the total number of URI arguments.
+	 *
+	 * @return  integer
+	 */
+	public function total_arguments()
+	{
+		return count(URI::$arguments);
+	}
+
+	/**
+	 * Returns the last URI segment.
+	 *
+	 * @param   mixed   default value returned if segment does not exist
+	 * @return  string
+	 */
+	public function last_segment($default = FALSE)
+	{
+		if (($end = $this->total_segments()) < 1)
+			return $default;
+
+		return URI::$segments[$end - 1];
+	}
+
+	/**
+	 * Returns the last re-routed URI segment.
+	 *
+	 * @param   mixed   default value returned if segment does not exist
+	 * @return  string
+	 */
+	public function last_rsegment($default = FALSE)
+	{
+		if (($end = $this->total_segments()) < 1)
+			return $default;
+
+		return URI::$rsegments[$end - 1];
+	}
+
+	/**
+	 * Returns the path to the current controller (not including the actual
+	 * controller), as a web path.
+	 *
+	 * @param   boolean  return a full url, or only the path specifically
+	 * @return  string
+	 */
+	public function controller_path($full = TRUE)
+	{
+		return ($full) ? url::site(URI::$controller_path) : URI::$controller_path;
+	}
+
+	/**
+	 * Returns the current controller, as a web path.
+	 *
+	 * @param   boolean  return a full url, or only the controller specifically
+	 * @return  string
+	 */
+	public function controller($full = TRUE)
+	{
+		return ($full) ? url::site(URI::$controller_path.URI::$controller) : URI::$controller;
+	}
+
+	/**
+	 * Returns the current method, as a web path.
+	 *
+	 * @param   boolean  return a full url, or only the method specifically
+	 * @return  string
+	 */
+	public function method($full = TRUE)
+	{
+		return ($full) ? url::site(URI::$controller_path.URI::$controller.'/'.URI::$method) : URI::$method;
+	}
+
+} // End URI Class
diff --git a/system/libraries/Validation.php b/system/libraries/Validation.php
new file mode 100644
index 0000000..9917fbb
--- /dev/null
+++ b/system/libraries/Validation.php
@@ -0,0 +1,815 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Validation library.
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Validation_Core extends ArrayObject {
+
+	// Filters
+	protected $pre_filters = array();
+	protected $post_filters = array();
+
+	// Rules and callbacks
+	protected $rules = array();
+	protected $callbacks = array();
+
+	// Rules that are allowed to run on empty fields
+	protected $empty_rules = array('required', 'matches');
+
+	// Errors
+	protected $errors = array();
+	protected $messages = array();
+
+	// Field labels
+	protected $labels = array();
+
+	// Fields that are expected to be arrays
+	protected $array_fields = array();
+
+	/**
+	 * Creates a new Validation instance.
+	 *
+	 * @param   array   array to use for validation
+	 * @return  object
+	 */
+	public static function factory(array $array)
+	{
+		return new Validation($array);
+	}
+
+	/**
+	 * Sets the unique "any field" key and creates an ArrayObject from the
+	 * passed array.
+	 *
+	 * @param   array   array to validate
+	 * @return  void
+	 */
+	public function __construct(array $array)
+	{
+		parent::__construct($array, ArrayObject::ARRAY_AS_PROPS | ArrayObject::STD_PROP_LIST);
+	}
+
+	/**
+	 * Magic clone method, clears errors and messages.
+	 *
+	 * @return  void
+	 */
+	public function __clone()
+	{
+		$this->errors = array();
+		$this->messages = array();
+	}
+
+	/**
+	 * Create a copy of the current validation rules and change the array.
+	 *
+	 * @chainable
+	 * @param   array  new array to validate
+	 * @return  Validation
+	 */
+	public function copy(array $array)
+	{
+		$copy = clone $this;
+
+		$copy->exchangeArray($array);
+
+		return $copy;
+	}
+
+	/**
+	 * Returns an array of all the field names that have filters, rules, or callbacks.
+	 *
+	 * @return  array
+	 */
+	public function field_names()
+	{
+		// All the fields that are being validated
+		$fields = array_keys(array_merge
+		(
+			$this->pre_filters,
+			$this->rules,
+			$this->callbacks,
+			$this->post_filters
+		));
+
+		// Remove wildcard fields
+		$fields = array_diff($fields, array('*'));
+
+		return $fields;
+	}
+
+	/**
+	 * Returns the array values of the current object.
+	 *
+	 * @return  array
+	 */
+	public function as_array()
+	{
+		return $this->getArrayCopy();
+	}
+
+	/**
+	 * Returns the ArrayObject values, removing all inputs without rules.
+	 * To choose specific inputs, list the field name as arguments.
+	 *
+	 * @param   boolean  return only fields with filters, rules, and callbacks
+	 * @return  array
+	 */
+	public function safe_array()
+	{
+		// Load choices
+		$choices = func_get_args();
+		$choices = empty($choices) ? NULL : array_combine($choices, $choices);
+
+		// Get field names
+		$fields = $this->field_names();
+
+		$safe = array();
+		foreach ($fields as $field)
+		{
+			if ($choices === NULL OR isset($choices[$field]))
+			{
+				if (isset($this[$field]))
+				{
+					$value = $this[$field];
+
+					if (is_object($value))
+					{
+						// Convert the value back into an array
+						$value = $value->getArrayCopy();
+					}
+				}
+				else
+				{
+					// Even if the field is not in this array, it must be set
+					$value = NULL;
+				}
+
+				// Add the field to the array
+				$safe[$field] = $value;
+			}
+		}
+
+		return $safe;
+	}
+
+	/**
+	 * Add additional rules that will forced, even for empty fields. All arguments
+	 * passed will be appended to the list.
+	 *
+	 * @chainable
+	 * @param   string   rule name
+	 * @return  object
+	 */
+	public function allow_empty_rules($rules)
+	{
+		// Any number of args are supported
+		$rules = func_get_args();
+
+		// Merge the allowed rules
+		$this->empty_rules = array_merge($this->empty_rules, $rules);
+
+		return $this;
+	}
+
+	/**
+	* Sets or overwrites the label name for a field.
+	*
+	* @param string field name
+	* @param string label
+	* @return $this
+	*/
+	public function label($field, $label = NULL)
+	{
+		if ($label === NULL AND ($field !== TRUE OR $field !== '*') AND ! isset($this->labels[$field]))
+		{
+			// Set the field label to the field name
+			$this->labels[$field] = ucfirst(preg_replace('/[^\pL]+/u', ' ', $field));
+		}
+		elseif ($label !== NULL)
+		{
+			// Set the label for this field
+			$this->labels[$field] = $label;
+		}
+
+		return $this;
+	}
+
+	/**
+	* Sets labels using an array.
+	*
+	* @param array list of field => label names
+	* @return $this
+	*/
+	public function labels(array $labels)
+	{
+		$this->labels = $labels + $this->labels;
+
+		return $this;
+	}
+
+	/**
+	 * Converts a filter, rule, or callback into a fully-qualified callback array.
+	 *
+	 * @return  mixed
+	 */
+	protected function callback($callback)
+	{
+		if (is_string($callback))
+		{
+			if (strpos($callback, '::') !== FALSE)
+			{
+				$callback = explode('::', $callback);
+			}
+			elseif (function_exists($callback))
+			{
+				// No need to check if the callback is a method
+				$callback = $callback;
+			}
+			elseif (method_exists($this, $callback))
+			{
+				// The callback exists in Validation
+				$callback = array($this, $callback);
+			}
+			elseif (method_exists('valid', $callback))
+			{
+				// The callback exists in valid::
+				$callback = array('valid', $callback);
+			}
+		}
+
+		if ( ! is_callable($callback, FALSE))
+		{
+			if (is_array($callback))
+			{
+				if (is_object($callback[0]))
+				{
+					// Object instance syntax
+					$name = get_class($callback[0]).'->'.$callback[1];
+				}
+				else
+				{
+					// Static class syntax
+					$name = $callback[0].'::'.$callback[1];
+				}
+			}
+			else
+			{
+				// Function syntax
+				$name = $callback;
+			}
+
+			throw new Kohana_Exception('Callback %name% used for Validation is not callable', array('%name%' => $name));
+		}
+
+		return $callback;
+	}
+
+	/**
+	 * Add a pre-filter to one or more inputs. Pre-filters are applied before
+	 * rules or callbacks are executed.
+	 *
+	 * @chainable
+	 * @param   callback  filter
+	 * @param   string    fields to apply filter to, use TRUE for all fields
+	 * @return  object
+	 */
+	public function pre_filter($filter, $field = TRUE)
+	{
+		if ($field === TRUE OR $field === '*')
+		{
+			// Use wildcard
+			$fields = array('*');
+		}
+		else
+		{
+			// Add the filter to specific inputs
+			$fields = func_get_args();
+			$fields = array_slice($fields, 1);
+		}
+
+		// Convert to a proper callback
+		$filter = $this->callback($filter);
+
+		foreach ($fields as $field)
+		{
+			// Add the filter to specified field
+			$this->pre_filters[$field][] = $filter;
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Add a post-filter to one or more inputs. Post-filters are applied after
+	 * rules and callbacks have been executed.
+	 *
+	 * @chainable
+	 * @param   callback  filter
+	 * @param   string    fields to apply filter to, use TRUE for all fields
+	 * @return  object
+	 */
+	public function post_filter($filter, $field = TRUE)
+	{
+		if ($field === TRUE)
+		{
+			// Use wildcard
+			$fields = array('*');
+		}
+		else
+		{
+			// Add the filter to specific inputs
+			$fields = func_get_args();
+			$fields = array_slice($fields, 1);
+		}
+
+		// Convert to a proper callback
+		$filter = $this->callback($filter);
+
+		foreach ($fields as $field)
+		{
+			// Add the filter to specified field
+			$this->post_filters[$field][] = $filter;
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Add rules to a field. Validation rules may only return TRUE or FALSE and
+	 * can not manipulate the value of a field.
+	 *
+	 * @chainable
+	 * @param   string    field name
+	 * @param   callback  rules (one or more arguments)
+	 * @return  object
+	 */
+	public function add_rules($field, $rules)
+	{
+		// Get the rules
+		$rules = func_get_args();
+		$rules = array_slice($rules, 1);
+
+		// Set a default field label
+		$this->label($field);
+
+		if ($field === TRUE)
+		{
+			// Use wildcard
+			$field = '*';
+		}
+
+		foreach ($rules as $rule)
+		{
+			// Arguments for rule
+			$args = NULL;
+
+			// False rule
+			$false_rule = FALSE;
+
+			$rule_tmp = trim(is_string($rule) ? $rule : $rule[1]);
+
+			// Should the rule return false?
+			if ($rule_tmp !== ($rule_name = ltrim($rule_tmp, '! ')))
+			{
+				$false_rule = TRUE;
+			}
+
+			if (is_string($rule))
+			{
+				// Use the updated rule name
+				$rule = $rule_name;
+
+				// Have arguments?
+				if (preg_match('/^([^\[]++)\[(.+)\]$/', $rule, $matches))
+				{
+					// Split the rule into the function and args
+					$rule = $matches[1];
+					$args = preg_split('/(?<!\\\\),\s*/', $matches[2]);
+
+					// Replace escaped comma with comma
+					$args = str_replace('\,', ',', $args);
+				}
+			}
+			else
+			{
+				$rule[1] = $rule_name;
+			}
+
+			if ($rule === 'is_array')
+			{
+				// This field is expected to be an array
+				$this->array_fields[$field] = $field;
+			}
+
+			// Convert to a proper callback
+			$rule = $this->callback($rule);
+
+			// Add the rule, with args, to the field
+			$this->rules[$field][] = array($rule, $args, $false_rule);
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Add callbacks to a field. Callbacks must accept the Validation object
+	 * and the input name. Callback returns are not processed.
+	 *
+	 * @chainable
+	 * @param   string     field name
+	 * @param   callbacks  callbacks (unlimited number)
+	 * @return  object
+	 */
+	public function add_callbacks($field, $callbacks)
+	{
+		// Get all callbacks as an array
+		$callbacks = func_get_args();
+		$callbacks = array_slice($callbacks, 1);
+
+		// Set a default field label
+		$this->label($field);
+
+		if ($field === TRUE)
+		{
+			// Use wildcard
+			$field = '*';
+		}
+
+		foreach ($callbacks as $callback)
+		{
+			// Convert to a proper callback
+			$callback = $this->callback($callback);
+
+			// Add the callback to specified field
+			$this->callbacks[$field][] = $callback;
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Validate by processing pre-filters, rules, callbacks, and post-filters.
+	 * All fields that have filters, rules, or callbacks will be initialized if
+	 * they are undefined. Validation will only be run if there is data already
+	 * in the array.
+	 *
+	 * @param   object  Validation object, used only for recursion
+	 * @param   object  name of field for errors
+	 * @return  bool
+	 */
+	public function validate($object = NULL, $field_name = NULL)
+	{
+		if ($object === NULL)
+		{
+			// Use the current object
+			$object = $this;
+		}
+
+		$array = $this->safe_array();
+
+		// Get all defined field names
+		$fields = array_keys($array);
+
+		foreach ($this->pre_filters as $field => $callbacks)
+		{
+			foreach ($callbacks as $callback)
+			{
+				if ($field === '*')
+				{
+					foreach ($fields as $f)
+					{
+						$array[$f] = is_array($array[$f]) ? array_map($callback, $array[$f]) : call_user_func($callback, $array[$f]);
+					}
+				}
+				else
+				{
+					$array[$field] = is_array($array[$field]) ? array_map($callback, $array[$field]) : call_user_func($callback, $array[$field]);
+				}
+			}
+		}
+
+		foreach ($this->rules as $field => $callbacks)
+		{
+			foreach ($callbacks as $callback)
+			{
+				// Separate the callback, arguments and is false bool
+				list ($callback, $args, $is_false) = $callback;
+
+				// Function or method name of the rule
+				$rule = is_array($callback) ? $callback[1] : $callback;
+
+				if ($field === '*')
+				{
+					foreach ($fields as $f)
+					{
+						// Note that continue, instead of break, is used when
+						// applying rules using a wildcard, so that all fields
+						// will be validated.
+
+						if (isset($this->errors[$f]))
+						{
+							// Prevent other rules from being evaluated if an error has occurred
+							continue;
+						}
+
+						if (empty($array[$f]) AND ! in_array($rule, $this->empty_rules))
+						{
+							// This rule does not need to be processed on empty fields
+							continue;
+						}
+
+						$result = ($args === NULL) ? call_user_func($callback, $array[$f]) : call_user_func($callback, $array[$f], $args);
+
+						if (($result == $is_false))
+						{
+							$this->add_error($f, $rule, $args);
+
+							// Stop validating this field when an error is found
+							continue;
+						}
+					}
+				}
+				else
+				{
+					if (isset($this->errors[$field]))
+					{
+						// Prevent other rules from being evaluated if an error has occurred
+						break;
+					}
+
+					if ( ! in_array($rule, $this->empty_rules) AND ! $this->required($array[$field]))
+					{
+						// This rule does not need to be processed on empty fields
+						continue;
+					}
+
+					// Results of our test
+					$result = ($args === NULL) ? call_user_func($callback, $array[$field]) : call_user_func($callback, $array[$field], $args);
+
+					if (($result == $is_false))
+					{
+						$rule = $is_false ? '!'.$rule : $rule;
+						$this->add_error($field, $rule, $args);
+
+						// Stop validating this field when an error is found
+						break;
+					}
+				}
+			}
+		}
+
+		foreach ($this->callbacks as $field => $callbacks)
+		{
+			foreach ($callbacks as $callback)
+			{
+				if ($field === '*')
+				{
+					foreach ($fields as $f)
+					{
+						// Note that continue, instead of break, is used when
+						// applying rules using a wildcard, so that all fields
+						// will be validated.
+
+						if (isset($this->errors[$f]))
+						{
+							// Stop validating this field when an error is found
+							continue;
+						}
+
+						call_user_func($callback, $this, $f);
+					}
+				}
+				else
+				{
+					if (isset($this->errors[$field]))
+					{
+						// Stop validating this field when an error is found
+						break;
+					}
+
+					call_user_func($callback, $this, $field);
+				}
+			}
+		}
+
+		foreach ($this->post_filters as $field => $callbacks)
+		{
+			foreach ($callbacks as $callback)
+			{
+				if ($field === '*')
+				{
+					foreach ($fields as $f)
+					{
+						$array[$f] = is_array($array[$f]) ? array_map($callback, $array[$f]) : call_user_func($callback, $array[$f]);
+					}
+				}
+				else
+				{
+					$array[$field] = is_array($array[$field]) ? array_map($callback, $array[$field]) : call_user_func($callback, $array[$field]);
+				}
+			}
+		}
+
+		// Swap the array back into the object
+		$this->exchangeArray($array);
+
+		// Return TRUE if there are no errors
+		return $this->errors === array();
+	}
+
+	/**
+	 * Add an error to an input.
+	 *
+	 * @chainable
+	 * @param   string  input name
+	 * @param   string  unique error name
+	 * @param   string  arguments to pass to lang file
+	 * @return  object
+	 */
+	public function add_error($field, $name, $args = NULL)
+	{
+		$this->errors[$field] = array($name, $args);
+
+		return $this;
+	}
+
+	/**
+	 * Return the errors array.
+	 *
+	 * @param   boolean  load errors from a message file
+	 * @return  array
+	 */
+	public function errors($file = NULL)
+	{
+		if ($file === NULL)
+		{
+			$errors = array();
+			foreach($this->errors as $field => $error)
+			{
+				$errors[$field] = $error[0];
+			}
+			return $errors;
+		}
+		else
+		{
+			$errors = array();
+			foreach ($this->errors as $input => $error)
+			{
+				// Locations to check for error messages
+				$error_locations = array
+				(
+					"validation/{$file}.{$input}.{$error[0]}",
+					"validation/{$file}.{$input}.default",
+					"validation/default.{$error[0]}"
+				);
+
+				if (($message = Kohana::message($error_locations[0])) !== $error_locations[0])
+				{
+					// Found a message for this field and error
+				}
+				elseif (($message = Kohana::message($error_locations[1])) !== $error_locations[1])
+				{
+					// Found a default message for this field
+				}
+				elseif (($message = Kohana::message($error_locations[2])) !== $error_locations[2])
+				{
+					// Found a default message for this error
+				}
+				else
+				{
+					// No message exists, display the path expected
+					$message = "validation/{$file}.{$input}.{$error[0]}";
+				}
+
+				// Start the translation values list
+				$values = array(':field' => __($this->labels[$input]));
+
+				if ( ! empty($error[1]))
+				{
+					foreach ($error[1] as $key => $value)
+					{
+						// Add each parameter as a numbered value, starting from 1
+						$values[':param'.($key + 1)] = __($value);
+					}
+				}
+
+				// Translate the message using the default language
+				$errors[$input] = __($message, $values);
+			}
+
+			return $errors;
+		}
+	}
+
+	/**
+	 * Rule: required. Generates an error if the field has an empty value.
+	 *
+	 * @param   mixed   input value
+	 * @return  bool
+	 */
+	public function required($str)
+	{
+		if (is_object($str) AND $str instanceof ArrayObject)
+		{
+			// Get the array from the ArrayObject
+			$str = $str->getArrayCopy();
+		}
+
+		if (is_array($str))
+		{
+			return ! empty($str);
+		}
+		else
+		{
+			return ! ($str === '' OR $str === NULL OR $str === FALSE);
+		}
+	}
+
+	/**
+	 * Rule: matches. Generates an error if the field does not match one or more
+	 * other fields.
+	 *
+	 * @param   mixed   input value
+	 * @param   array   input names to match against
+	 * @return  bool
+	 */
+	public function matches($str, array $inputs)
+	{
+		foreach ($inputs as $key)
+		{
+			if ($str !== (isset($this[$key]) ? $this[$key] : NULL))
+				return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	/**
+	 * Rule: length. Generates an error if the field is too long or too short.
+	 *
+	 * @param   mixed   input value
+	 * @param   array   minimum, maximum, or exact length to match
+	 * @return  bool
+	 */
+	public function length($str, array $length)
+	{
+		if ( ! is_string($str))
+			return FALSE;
+
+		$size = mb_strlen($str);
+		$status = FALSE;
+
+		if (count($length) > 1)
+		{
+			list ($min, $max) = $length;
+
+			if ($size >= $min AND $size <= $max)
+			{
+				$status = TRUE;
+			}
+		}
+		else
+		{
+			$status = ($size === (int) $length[0]);
+		}
+
+		return $status;
+	}
+
+	/**
+	 * Rule: depends_on. Generates an error if the field does not depend on one
+	 * or more other fields.
+	 *
+	 * @param   mixed   field name
+	 * @param   array   field names to check dependency
+	 * @return  bool
+	 */
+	public function depends_on($field, array $fields)
+	{
+		foreach ($fields as $depends_on)
+		{
+			if ( ! isset($this[$depends_on]) OR $this[$depends_on] == NULL)
+				return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	/**
+	 * Rule: chars. Generates an error if the field contains characters outside of the list.
+	 *
+	 * @param   string  field value
+	 * @param   array   allowed characters
+	 * @return  bool
+	 */
+	public function chars($value, array $chars)
+	{
+		return ! preg_match('![^'.implode('', $chars).']!u', $value);
+	}
+
+} // End Validation
\ No newline at end of file
diff --git a/system/libraries/View.php b/system/libraries/View.php
new file mode 100644
index 0000000..ba482bb
--- /dev/null
+++ b/system/libraries/View.php
@@ -0,0 +1,329 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Loads and displays Kohana view files. Can also handle output of some binary
+ * files, such as image, Javascript, and CSS files.
+ *
+ * $Id: View.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class View_Core {
+
+	// The view file name and type
+	protected $kohana_filename = FALSE;
+	protected $kohana_filetype = FALSE;
+
+	// View variable storage
+	protected $kohana_local_data = array();
+
+	/**
+	 * Creates a new View using the given parameters.
+	 *
+	 * @param   string  view name
+	 * @param   array   pre-load data
+	 * @param   string  type of file: html, css, js, etc.
+	 * @return  object
+	 */
+	public static function factory($name = NULL, $data = NULL, $type = NULL)
+	{
+		return new View($name, $data, $type);
+	}
+
+	/**
+	 * Attempts to load a view and pre-load view data.
+	 *
+	 * @throws  Kohana_Exception  if the requested view cannot be found
+	 * @param   string  view name
+	 * @param   array   pre-load data
+	 * @param   string  type of file: html, css, js, etc.
+	 * @return  void
+	 */
+	public function __construct($name = NULL, $data = NULL, $type = NULL)
+	{
+		if (is_string($name) AND $name !== '')
+		{
+			// Set the filename
+			$this->set_filename($name, $type);
+		}
+
+		if (is_array($data) AND ! empty($data))
+		{
+			// Preload data using array_merge, to allow user extensions
+			$this->kohana_local_data = array_merge($this->kohana_local_data, $data);
+		}
+	}
+
+	/**
+	 * Magic method access to test for view property
+	 *
+	 * @param   string   View property to test for
+	 * @return  boolean
+	 */
+	public function __isset($key = NULL)
+	{
+		return $this->is_set($key);
+	}
+
+	/**
+	 * Sets the view filename.
+	 *
+	 * @chainable
+	 * @param   string  view filename
+	 * @param   string  view file type
+	 * @return  object
+	 */
+	public function set_filename($name, $type = NULL)
+	{
+		if ($type == NULL)
+		{
+			// Load the filename and set the content type
+			$this->kohana_filename = Kohana::find_file('views', $name, TRUE);
+			$this->kohana_filetype = EXT;
+		}
+		else
+		{
+			// Check if the filetype is allowed by the configuration
+			if ( ! in_array($type, Kohana::config('view.allowed_filetypes')))
+				throw new Kohana_Exception('The requested filetype, .:type:, is not allowed in your view configuration file', array(':type:' => $type));
+
+			// Load the filename and set the content type
+			$this->kohana_filename = Kohana::find_file('views', $name, TRUE, $type);
+			$this->kohana_filetype = Kohana::config('mimes.'.$type);
+
+			if ($this->kohana_filetype == NULL)
+			{
+				// Use the specified type
+				$this->kohana_filetype = $type;
+			}
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Sets a view variable.
+	 *
+	 * @param   string|array  name of variable or an array of variables
+	 * @param   mixed         value when using a named variable
+	 * @return  object
+	 */
+	public function set($name, $value = NULL)
+	{
+		if (is_array($name))
+		{
+			foreach ($name as $key => $value)
+			{
+				$this->__set($key, $value);
+			}
+		}
+		else
+		{
+			$this->__set($name, $value);
+		}
+
+		return $this;
+	}
+
+	/**
+	 * Checks for a property existence in the view locally or globally. Unlike the built in __isset(),
+	 * this method can take an array of properties to test simultaneously.
+	 *
+	 * @param string $key property name to test for
+	 * @param array $key array of property names to test for
+	 * @return boolean property test result
+	 * @return array associative array of keys and boolean test result
+	 */
+	public function is_set( $key = FALSE )
+	{
+		// Setup result;
+		$result = FALSE;
+
+		// If key is an array
+		if (is_array($key))
+		{
+			// Set the result to an array
+			$result = array();
+
+			// Foreach key
+			foreach ($key as $property)
+			{
+				// Set the result to an associative array
+				$result[$property] = (array_key_exists($property, $this->kohana_local_data)) ? TRUE : FALSE;
+			}
+		}
+		else
+		{
+			// Otherwise just check one property
+			$result = (array_key_exists($key, $this->kohana_local_data)) ? TRUE : FALSE;
+		}
+
+		// Return the result
+		return $result;
+	}
+
+	/**
+	 * Sets a bound variable by reference.
+	 *
+	 * @param   string   name of variable
+	 * @param   mixed    variable to assign by reference
+	 * @return  object
+	 */
+	public function bind($name, & $var)
+	{
+		$this->kohana_local_data[$name] =& $var;
+
+		return $this;
+	}
+
+	/**
+	 * Magically sets a view variable.
+	 *
+	 * @param   string   variable key
+	 * @param   string   variable value
+	 * @return  void
+	 */
+	public function __set($key, $value)
+	{
+		$this->kohana_local_data[$key] = $value;
+	}
+
+	/**
+	 * Magically gets a view variable.
+	 *
+	 * @param  string  variable key
+	 * @return mixed   variable value if the key is found
+	 * @return void    if the key is not found
+	 */
+	public function &__get($key)
+	{
+		if (isset($this->kohana_local_data[$key]))
+		{
+			return $this->kohana_local_data[$key];
+		}
+		elseif (isset($this->$key))
+		{
+			return $this->$key;
+		}
+		else
+		{
+			throw new Kohana_Exception('Undefined view variable: :var',
+				array(':var' => $key));
+		}
+	}
+
+	/**
+	 * Magically converts view object to string.
+	 *
+	 * @return  string
+	 */
+	public function __toString()
+	{
+		try
+		{
+			return $this->render();
+		}
+		catch (Exception $e)
+		{
+			Kohana_Exception::handle($e);
+			return (string) '';
+		}
+	}
+
+	/**
+	 * Renders a view.
+	 *
+	 * @param   boolean   set to TRUE to echo the output instead of returning it
+	 * @param   callback  special renderer to pass the output through
+	 * @param   callback  modifier to pass the data through before rendering
+	 * @return  string    if print is FALSE
+	 * @return  void      if print is TRUE
+	 */
+	public function render($print = FALSE, $renderer = FALSE, $modifier = FALSE)
+	{
+		if (empty($this->kohana_filename))
+			throw new Kohana_Exception('You must set the the view filename before calling render');
+
+		if (is_string($this->kohana_filetype))
+		{
+			// Merge global and local data, local overrides global with the same name
+			$data = $this->kohana_local_data;
+
+			if ($modifier !== FALSE AND is_callable($modifier, TRUE))
+			{
+				// Pass the data through the user defined modifier
+				$data = call_user_func($modifier, $data);
+			}
+
+			$output = $this->load_view($this->kohana_filename, $data);
+
+			if ($renderer !== FALSE AND is_callable($renderer, TRUE))
+			{
+				// Pass the output through the user defined renderer
+				$output = call_user_func($renderer, $output);
+			}
+
+			if ($print === TRUE)
+			{
+				// Display the output
+				echo $output;
+				return;
+			}
+		}
+		else
+		{
+			// Set the content type and size
+			header('Content-Type: '.$this->kohana_filetype[0]);
+
+			if ($print === TRUE)
+			{
+				if ($file = fopen($this->kohana_filename, 'rb'))
+				{
+					// Display the output
+					fpassthru($file);
+					fclose($file);
+				}
+				return;
+			}
+
+			// Fetch the file contents
+			$output = file_get_contents($this->kohana_filename);
+		}
+
+		return $output;
+	}
+
+	/**
+	 * Includes a View within the controller scope.
+	 *
+	 * @param   string  view filename
+	 * @param   array   array of view variables
+	 * @return  string
+	 */
+	public function load_view($kohana_view_filename, $kohana_input_data)
+	{
+		if ($kohana_view_filename == '')
+			return;
+
+		// Buffering on
+		ob_start();
+
+		// Import the view variables to local namespace
+		extract($kohana_input_data, EXTR_SKIP);
+
+		try
+		{
+			include $kohana_view_filename;
+		}
+		catch (Exception $e)
+		{
+			ob_end_clean();
+			throw $e;
+		}
+
+		// Fetch the output and close the buffer
+		return ob_get_clean();
+	}
+} // End View
diff --git a/system/libraries/drivers/Cache.php b/system/libraries/drivers/Cache.php
new file mode 100644
index 0000000..9741509
--- /dev/null
+++ b/system/libraries/drivers/Cache.php
@@ -0,0 +1,42 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Cache driver abstract class.
+ *
+ * $Id$
+ *
+ * @package    Cache
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+abstract class Cache_Driver {
+	/**
+	 * Set cache items  
+	 */
+	abstract public function set($items, $tags = NULL, $lifetime = NULL);
+
+	/**
+	 * Get a cache items by key 
+	 */
+	abstract public function get($keys, $single = FALSE);
+
+	/**
+	 * Get cache items by tag 
+	 */
+	abstract public function get_tag($tags);
+
+	/**
+	 * Delete cache item by key 
+	 */
+	abstract public function delete($keys);
+
+	/**
+	 * Delete cache items by tag 
+	 */
+	abstract public function delete_tag($tags);
+
+	/**
+	 * Empty the cache
+	 */
+	abstract public function delete_all();
+} // End Cache Driver
\ No newline at end of file
diff --git a/system/libraries/drivers/Cache/File.php b/system/libraries/drivers/Cache/File.php
new file mode 100644
index 0000000..d6ec037
--- /dev/null
+++ b/system/libraries/drivers/Cache/File.php
@@ -0,0 +1,255 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Memcache-based Cache driver.
+ *
+ * $Id: File.php 4605 2009-09-14 17:22:21Z kiall $
+ *
+ * @package    Cache
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Cache_File_Driver extends Cache_Driver {
+	protected $config;
+	protected $backend;
+
+	public function __construct($config)
+	{
+		$this->config = $config;
+		$this->config['directory'] = str_replace('\\', '/', realpath($this->config['directory'])).'/';
+
+		if ( ! is_dir($this->config['directory']) OR ! is_writable($this->config['directory']))
+			throw new Cache_Exception('The configured cache directory, :directory:, is not writable.', array(':directory:' => $this->config['directory']));
+	}
+
+	/**
+	 * Finds an array of files matching the given id or tag.
+	 *
+	 * @param  string  cache key or tag
+	 * @param  bool    search for tags
+	 * @return array   of filenames matching the id or tag
+	 */
+	public function exists($keys, $tag = FALSE)
+	{
+		if ($keys === TRUE)
+		{
+			// Find all the files
+			return glob($this->config['directory'].'*~*~*');
+		}
+		elseif ($tag === TRUE)
+		{
+			// Find all the files that have the tag name
+			$paths = array();
+
+			foreach ( (array) $keys as $tag)
+			{
+				$paths = array_merge($paths, glob($this->config['directory'].'*~*'.$tag.'*~*'));
+			}
+
+			// Find all tags matching the given tag
+			$files = array();
+
+			foreach ($paths as $path)
+			{
+				// Split the files
+				$tags = explode('~', basename($path));
+
+				// Find valid tags
+				if (count($tags) !== 3 OR empty($tags[1]))
+					continue;
+
+				// Split the tags by plus signs, used to separate tags
+				$item_tags = explode('+', $tags[1]);
+
+				// Check each supplied tag, and match aginst the tags on each item.
+				foreach ($keys as $tag)
+				{
+					if (in_array($tag, $item_tags))
+					{
+						// Add the file to the array, it has the requested tag
+						$files[] = $path;
+					}
+				}
+			}
+
+			return $files;
+		}
+		else
+		{
+			$paths = array();
+
+			foreach ( (array) $keys as $key)
+			{
+				// Find the file matching the given key
+				$paths = array_merge($paths, glob($this->config['directory'].str_replace(array('/', '\\', ' '), '_', $key).'~*'));
+			}
+
+			return $paths;
+		}
+	}
+
+	public function set($items, $tags = NULL, $lifetime = NULL)
+	{
+		if ($lifetime !== 0)
+		{
+			// File driver expects unix timestamp
+			$lifetime += time();
+		}
+
+
+		if ( ! is_null($tags) AND ! empty($tags))
+		{
+			// Convert the tags into a string list
+			$tags = implode('+', (array) $tags);
+		}
+
+		$success = TRUE;
+
+		foreach ($items as $key => $value)
+		{
+			if (is_resource($value))
+				throw new Cache_Exception('Caching of resources is impossible, because resources cannot be serialised.');
+
+			// Remove old cache file
+			$this->delete($key);
+
+			if ( ! (bool) file_put_contents($this->config['directory'].str_replace(array('/', '\\', ' '), '_', $key).'~'.$tags.'~'.$lifetime, serialize($value)))
+			{
+				$success = FALSE;
+			}
+		}
+
+		return $success;
+	}
+
+	public function get($keys, $single = FALSE)
+	{
+		$items = array();
+
+		if ($files = $this->exists($keys))
+		{
+			// Turn off errors while reading the files
+			$ER = error_reporting(0);
+
+			foreach ($files as $file)
+			{
+				// Validate that the item has not expired
+				if ($this->expired($file))
+					continue;
+
+				list($key, $junk) = explode('~', basename($file), 2);
+
+				if (($data = file_get_contents($file)) !== FALSE)
+				{
+					// Unserialize the data
+					$data = unserialize($data);
+				}
+				else
+				{
+					$data = NULL;
+				}
+
+				$items[$key] = $data;
+			}
+
+			// Turn errors back on
+			error_reporting($ER);
+		}
+
+		// Reutrn a single item if only one key was requested
+		if ($single)
+		{
+			return (count($items) > 0) ? current($items) : NULL;
+		}
+		else
+		{
+			return $items;
+		}
+	}
+
+	/**
+	 * Get cache items by tag
+	 */
+	public function get_tag($tags)
+	{
+		// An array will always be returned
+		$result = array();
+
+		if ($paths = $this->exists($tags, TRUE))
+		{
+			// Find all the files with the given tag
+			foreach ($paths as $path)
+			{
+				// Get the id from the filename
+				list($key, $junk) = explode('~', basename($path), 2);
+
+				if (($data = $this->get($key, TRUE)) !== FALSE)
+				{
+					// Add the result to the array
+					$result[$key] = $data;
+				}
+			}
+		}
+
+		return $result;
+	}
+
+	/**
+	 * Delete cache items by keys or tags
+	 */
+	public function delete($keys, $tag = FALSE)
+	{
+		$success = TRUE;
+
+		$paths = $this->exists($keys, $tag);
+
+		// Disable all error reporting while deleting
+		$ER = error_reporting(0);
+
+		foreach ($paths as $path)
+		{
+			// Remove the cache file
+			if ( ! unlink($path))
+			{
+				Kohana_Log::add('error', 'Cache: Unable to delete cache file: '.$path);
+				$success = FALSE;
+			}
+		}
+
+		// Turn on error reporting again
+		error_reporting($ER);
+
+		return $success;
+	}
+
+	/**
+	 * Delete cache items by tag
+	 */
+	public function delete_tag($tags)
+	{
+		return $this->delete($tags, TRUE);
+	}
+
+	/**
+	 * Empty the cache
+	 */
+	public function delete_all()
+	{
+		return $this->delete(TRUE);
+	}
+
+	/**
+	 * Check if a cache file has expired by filename.
+	 *
+	 * @param  string|array   array of filenames
+	 * @return bool
+	 */
+	protected function expired($file)
+	{
+		// Get the expiration time
+		$expires = (int) substr($file, strrpos($file, '~') + 1);
+
+		// Expirations of 0 are "never expire"
+		return ($expires !== 0 AND $expires <= time());
+	}
+} // End Cache Memcache Driver
diff --git a/system/libraries/drivers/Cache/Memcache.php b/system/libraries/drivers/Cache/Memcache.php
new file mode 100644
index 0000000..13d61d8
--- /dev/null
+++ b/system/libraries/drivers/Cache/Memcache.php
@@ -0,0 +1,132 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Memcache-based Cache driver.
+ *
+ * $Id$
+ *
+ * @package    Cache
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Cache_Memcache_Driver extends Cache_Driver {
+	protected $config;
+	protected $backend;
+	protected $flags;
+
+	public function __construct($config)
+	{
+		if ( ! extension_loaded('memcache'))
+			throw new Cache_Exception('The memcache PHP extension must be loaded to use this driver.');
+
+		ini_set('memcache.allow_failover', (isset($config['allow_failover']) AND $config['allow_failover']) ? TRUE : FALSE);
+
+		$this->config = $config;
+		$this->backend = new Memcache;
+
+		$this->flags = (isset($config['compression']) AND $config['compression']) ? MEMCACHE_COMPRESSED : FALSE;
+
+		foreach ($config['servers'] as $server)
+		{
+			// Make sure all required keys are set
+			$server += array('host' => '127.0.0.1',
+			                 'port' => 11211,
+			                 'persistent' => FALSE,
+			                 'weight' => 1,
+			                 'timeout' => 1,
+			                 'retry_interval' => 15
+			);
+
+			// Add the server to the pool
+			$this->backend->addServer($server['host'], $server['port'], (bool) $server['persistent'], (int) $server['weight'], (int) $server['timeout'], (int) $server['retry_interval'], TRUE, array($this,'_memcache_failure_callback'));
+		}
+	}
+
+	public function _memcache_failure_callback($host, $port)
+	{
+		$this->backend->setServerParams($host, $port, 1, -1, FALSE);
+		Kohana_Log::add('error', __('Cache: Memcache server down: :host:::port:',array(':host:' => $host,':port:' => $port)));
+	}
+
+	public function set($items, $tags = NULL, $lifetime = NULL)
+	{
+		if ($lifetime !== 0)
+		{
+			// Memcache driver expects unix timestamp
+			$lifetime += time();
+		}
+
+		if ($tags !== NULL)
+			throw new Cache_Exception('Memcache driver does not support tags');
+
+		foreach ($items as $key => $value)
+		{
+			if (is_resource($value))
+				throw new Cache_Exception('Caching of resources is impossible, because resources cannot be serialised.');
+
+			if ( ! $this->backend->set($key, $value, $this->flags, $lifetime))
+			{
+				return FALSE;
+			}
+		}
+
+		return TRUE;
+	}
+
+	public function get($keys, $single = FALSE)
+	{
+		$items = $this->backend->get($keys);
+
+		if ($single)
+		{
+			if ($items === FALSE)
+			    return NULL;
+
+			return (count($items) > 0) ? current($items) : NULL;
+		}
+		else
+		{
+			return ($items === FALSE) ? array() : $items;
+		}
+	}
+
+	/**
+	 * Get cache items by tag
+	 */
+	public function get_tag($tags)
+	{
+		throw new Cache_Exception('Memcache driver does not support tags');
+	}
+
+	/**
+	 * Delete cache item by key
+	 */
+	public function delete($keys)
+	{
+		foreach ($keys as $key)
+		{
+			if ( ! $this->backend->delete($key))
+			{
+				return FALSE;
+			}
+		}
+
+		return TRUE;
+	}
+
+	/**
+	 * Delete cache items by tag
+	 */
+	public function delete_tag($tags)
+	{
+		throw new Cache_Exception('Memcache driver does not support tags');
+	}
+
+	/**
+	 * Empty the cache
+	 */
+	public function delete_all()
+	{
+		return $this->backend->flush();
+	}
+} // End Cache Memcache Driver
diff --git a/system/libraries/drivers/Cache/Xcache.php b/system/libraries/drivers/Cache/Xcache.php
new file mode 100644
index 0000000..6761983
--- /dev/null
+++ b/system/libraries/drivers/Cache/Xcache.php
@@ -0,0 +1,161 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * XCache-based Cache driver.
+ * 
+ * $Id: Memcache.php 4605 2009-09-14 17:22:21Z kiall $
+ *
+ * @package    Cache
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ * @TODO       Check if XCache cleans its own keys.
+ */
+class Cache_Xcache_Driver extends Cache_Driver {
+	protected $config;
+
+	public function __construct($config)
+	{
+		if ( ! extension_loaded('xcache'))
+			throw new Cache_Exception('The xcache PHP extension must be loaded to use this driver.');
+
+		$this->config = $config;
+	}
+
+	public function set($items, $tags = NULL, $lifetime = NULL)
+	{
+		if ($tags !== NULL)
+		{
+			Kohana_Log::add('debug', __('Cache: XCache driver does not support tags'));
+		}
+
+		foreach ($items as $key => $value)
+		{
+			if (is_resource($value))
+				throw new Cache_Exception('Caching of resources is impossible, because resources cannot be serialised.');
+
+			if ( ! xcache_set($key, $value, $lifetime))
+			{
+				return FALSE;
+			}
+		}
+
+		return TRUE;
+	}
+
+	public function get($keys, $single = FALSE)
+	{
+		$items = array();
+
+		foreach ($keys as $key)
+		{
+			if (xcache_isset($key))
+			{
+				$items[$key] = xcache_get($key);
+			}
+			else
+			{
+				$items[$key] = NULL;
+			}
+		}
+
+		if ($single)
+		{
+			return ($items === FALSE OR count($items) > 0) ? current($items) : NULL;
+		}
+		else
+		{
+			return ($items === FALSE) ? array() : $items;
+		}
+	}
+
+	/**
+	 * Get cache items by tag
+	 */
+	public function get_tag($tags)
+	{
+		Kohana_Log::add('debug', __('Cache: XCache driver does not support tags'));
+		return NULL;
+	}
+
+	/**
+	 * Delete cache item by key
+	 */
+	public function delete($keys)
+	{
+		foreach ($keys as $key)
+		{
+			if ( ! xcache_unset($key))
+			{
+				return FALSE;
+			}
+		}
+
+		return TRUE;
+	}
+
+	/**
+	 * Delete cache items by tag
+	 */
+	public function delete_tag($tags)
+	{
+		Kohana_Log::add('debug', __('Cache: XCache driver does not support tags'));
+		return NULL;
+	}
+
+	/**
+	 * Empty the cache
+	 */
+	public function delete_all()
+	{
+		$this->auth();
+		$result = TRUE;
+
+		for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++)
+		{
+			if (xcache_clear_cache(XC_TYPE_VAR, $i) !== NULL)
+			{
+				$result = FALSE;
+				break;
+			}
+		}
+
+		// Undo the login
+		$this->auth(TRUE);
+
+		return $result;
+	}
+
+	private function auth($reverse = FALSE)
+	{
+		static $backup = array();
+
+		$keys = array('PHP_AUTH_USER', 'PHP_AUTH_PW');
+
+		foreach ($keys as $key)
+		{
+			if ($reverse)
+			{
+				if (isset($backup[$key]))
+				{
+					$_SERVER[$key] = $backup[$key];
+					unset($backup[$key]);
+				}
+				else
+				{
+					unset($_SERVER[$key]);
+				}
+			}
+			else
+			{
+				$value = getenv($key);
+
+				if ( ! empty($value))
+				{
+					$backup[$key] = $value;
+				}
+
+				$_SERVER[$key] = $this->config->{$key};
+			}
+		}
+	}
+} // End Cache XCache Driver
diff --git a/system/libraries/drivers/Config.php b/system/libraries/drivers/Config.php
new file mode 100644
index 0000000..a82684b
--- /dev/null
+++ b/system/libraries/drivers/Config.php
@@ -0,0 +1,257 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Kohana_Config abstract driver to get and set
+ * configuration options.
+ *
+ * Specific drivers should implement caching and encryption
+ * as they deem appropriate.
+ *
+ * $Id: Config.php 4679 2009-11-10 01:45:52Z isaiah $
+ *
+ * @package    Kohana_Config
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ * @abstract
+ */
+abstract class Config_Driver {
+
+	/**
+	 * Internal caching
+	 *
+	 * @var     Cache
+	 */
+	protected $cache;
+
+	/**
+	 * The name of the internal cache
+	 *
+	 * @var     string
+	 */
+	protected $cache_name = 'Kohana_Config_Cache';
+
+	/**
+	 * Cache Lifetime
+	 *
+	 * @var mixed
+	 */
+	protected $cache_lifetime = FALSE;
+
+	/**
+	 * The Encryption library
+	 *
+	 * @var     Encrypt
+	 */
+	protected $encrypt;
+
+	/**
+	 * The config loaded
+	 *
+	 * @var     array
+	 */
+	protected $config = array();
+
+	/**
+	 * The changed status of configuration values,
+	 * current state versus the stored state.
+	 *
+	 * @var     bool
+	 */
+	protected $changed = FALSE;
+
+	/**
+	 * Determines if any config has been loaded yet
+	 */
+	public $loaded = FALSE;
+
+	/**
+	 * Array driver constructor. Sets up the PHP array
+	 * driver, including caching and encryption if
+	 * required
+	 *
+	 * @access  public
+	 */
+	public function __construct($config)
+	{
+
+		if (($cache_setting = $config['internal_cache']) !== FALSE)
+		{
+			$this->cache_lifetime = $cache_setting;
+			// Restore the cached configuration
+			$this->config = $this->load_cache();
+
+			if (count($this->config) > 0)
+				$this->loaded = TRUE;
+
+			// Add the save cache method to system.shutshut event
+			Event::add('system.shutdown', array($this, 'save_cache'));
+		}
+
+	}
+
+	/**
+	 * Gets a value from config. If required is TRUE
+	 * then get will throw an exception if value cannot
+	 * be loaded.
+	 *
+	 * @param   string       key  the setting to get
+	 * @param   bool         slash  remove trailing slashes
+	 * @param   bool         required  is setting required?
+	 * @return  mixed
+	 * @access  public
+	 */
+	public function get($key, $slash = FALSE, $required = FALSE)
+	{
+		// Get the group name from the key
+		$group = explode('.', $key, 2);
+		$group = $group[0];
+
+		// Check for existing value and load it dynamically if required
+		if ( ! isset($this->config[$group]))
+			$this->config[$group] = $this->load($group, $required);
+
+		// Get the value of the key string
+		$value = Kohana::key_string($this->config, $key);
+
+		if ($slash === TRUE AND is_string($value) AND $value !== '')
+		{
+			// Force the value to end with "/"
+			$value = rtrim($value, '/').'/';
+		}
+
+		if (($required === TRUE) AND ($value === null))
+			throw new Kohana_Config_Exception('Value not found in config driver');
+
+		$this->loaded = TRUE;
+		return $value;
+	}
+
+	/**
+	 * Sets a new value to the configuration
+	 *
+	 * @param   string       key
+	 * @param   mixed        value
+	 * @return  bool
+	 * @access  public
+	 */
+	public function set($key, $value)
+	{
+		// Do this to make sure that the config array is already loaded
+		$this->get($key);
+
+		if (substr($key, 0, 7) === 'routes.')
+		{
+			// Routes cannot contain sub keys due to possible dots in regex
+			$keys = explode('.', $key, 2);
+		}
+		else
+		{
+			// Convert dot-noted key string to an array
+			$keys = explode('.', $key);
+		}
+
+		// Used for recursion
+		$conf =& $this->config;
+		$last = count($keys) - 1;
+
+		foreach ($keys as $i => $k)
+		{
+			if ($i === $last)
+			{
+				$conf[$k] = $value;
+			}
+			else
+			{
+				$conf =& $conf[$k];
+			}
+		}
+
+		if (substr($key,0,12) === 'core.modules')
+		{
+			// Reprocess the include paths
+			Kohana::include_paths(TRUE);
+		}
+
+		// Set config to changed
+		return $this->changed = TRUE;
+	}
+
+	/**
+	 * Clear the configuration
+	 *
+	 * @param   string       group
+	 * @return  bool
+	 * @access  public
+	 */
+	public function clear($group)
+	{
+		// Remove the group from config
+		unset($this->config[$group]);
+
+		// Set config to changed
+		return $this->changed = TRUE;
+	}
+
+	/**
+	 * Checks whether the setting exists in
+	 * config
+	 *
+	 * @param   string $key
+	 * @return  bool
+	 * @access  public
+	 */
+	public function setting_exists($key)
+	{
+		return $this->get($key) === NULL;
+	}
+
+	/**
+	 * Loads a configuration group based on the setting
+	 *
+	 * @param   string       group
+	 * @param   bool         required
+	 * @return  array
+	 * @access  public
+	 * @abstract
+	 */
+	abstract public function load($group, $required = FALSE);
+
+	/**
+	 * Loads the cached version of this configuration driver
+	 *
+	 * @return  array
+	 * @access  public
+	 */
+	public function load_cache()
+	{
+		// Load the cache for this configuration
+		$cached_config = Kohana::cache($this->cache_name, $this->cache_lifetime);
+
+		// If the configuration wasn't loaded from the cache
+		if ($cached_config === NULL)
+			$cached_config = array();
+
+		// Return the cached config
+		return $cached_config;
+	}
+
+	/**
+	 * Saves a cached version of this configuration driver
+	 *
+	 * @return  bool
+	 * @access  public
+	 */
+	public function save_cache()
+	{
+		// If this configuration has changed
+		if ($this->get('core.internal_cache') !== FALSE AND $this->changed)
+		{
+			$data = $this->config;
+
+			// Save the cache
+			return Kohana::cache_save($this->cache_name, $data, $this->cache_lifetime);
+		}
+
+		return TRUE;
+	}
+} // End Kohana_Config_Driver
\ No newline at end of file
diff --git a/system/libraries/drivers/Config/Array.php b/system/libraries/drivers/Config/Array.php
new file mode 100644
index 0000000..b2ca19b
--- /dev/null
+++ b/system/libraries/drivers/Config/Array.php
@@ -0,0 +1,83 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Kohana_Config Array driver to get and set
+ * configuration options using PHP arrays.
+ * 
+ * This driver can cache and encrypt settings
+ * if required.
+ *
+ * $Id: Array.php 4679 2009-11-10 01:45:52Z isaiah $
+ *
+ * @package    Kohana_Config
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Config_Array_Driver extends Config_Driver {
+
+	/**
+	 * Internal caching
+	 *
+	 * @var     Cache
+	 */
+	protected $cache;
+
+	/**
+	 * The name of the internal cache
+	 *
+	 * @var     string
+	 */
+	protected $cache_name = 'Kohana_Config_Array_Cache';
+
+	/**
+	 * The Encryption library
+	 *
+	 * @var     Encrypt
+	 */
+	protected $encrypt;
+
+	/**
+	 * Loads a configuration group based on the setting
+	 *
+	 * @param   string       group 
+	 * @param   bool         required 
+	 * @return  array
+	 * @access  public
+	 */
+	public function load($group, $required = FALSE)
+	{
+		if ($group === 'core')
+		{
+			// Load the application configuration file
+			require APPPATH.'config/config'.EXT;
+
+			if ( ! isset($config['site_domain']))
+			{
+				// Invalid config file
+				throw new Kohana_Config_Exception('Your Kohana application configuration file is not valid.');
+			}
+
+			return $config;
+		}
+
+		// Load matching configs
+		$configuration = array();
+
+		if ($files = Kohana::find_file('config', $group, $required))
+		{
+			foreach ($files as $file)
+			{
+				require $file;
+
+				if (isset($config) AND is_array($config))
+				{
+					// Merge in configuration
+					$configuration = array_merge($configuration, $config);
+				}
+			}
+		}
+
+		// Return merged configuration
+		return $configuration;
+	}
+} // End Config_Array_Driver
\ No newline at end of file
diff --git a/system/libraries/drivers/Image.php b/system/libraries/drivers/Image.php
new file mode 100644
index 0000000..39936c3
--- /dev/null
+++ b/system/libraries/drivers/Image.php
@@ -0,0 +1,158 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Image API driver.
+ *
+ * $Id: Image.php 4679 2009-11-10 01:45:52Z isaiah $
+ *
+ * @package    Image
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+abstract class Image_Driver {
+
+	// Reference to the current image
+	protected $image;
+
+	// Reference to the temporary processing image
+	protected $tmp_image;
+
+	// Processing errors
+	protected $errors = array();
+
+	/**
+	 * Executes a set of actions, defined in pairs.
+	 *
+	 * @param   array    actions
+	 * @return  boolean
+	 */
+	public function execute($actions)
+	{
+		foreach ($actions as $func => $args)
+		{
+			if ( ! $this->$func($args))
+				return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	/**
+	 * Sanitize and normalize a geometry array based on the temporary image
+	 * width and height. Valid properties are: width, height, top, left.
+	 *
+	 * @param   array  geometry properties
+	 * @return  void
+	 */
+	protected function sanitize_geometry( & $geometry)
+	{
+		list($width, $height) = $this->properties();
+
+		// Turn off error reporting
+		$reporting = error_reporting(0);
+
+		// Width and height cannot exceed current image size
+		$geometry['width']  = min($geometry['width'], $width);
+		$geometry['height'] = min($geometry['height'], $height);
+
+		// Set standard coordinates if given, otherwise use pixel values
+		if ($geometry['top'] === 'center')
+		{
+			$geometry['top'] = floor(($height / 2) - ($geometry['height'] / 2));
+		}
+		elseif ($geometry['top'] === 'top')
+		{
+			$geometry['top'] = 0;
+		}
+		elseif ($geometry['top'] === 'bottom')
+		{
+			$geometry['top'] = $height - $geometry['height'];
+		}
+
+		// Set standard coordinates if given, otherwise use pixel values
+		if ($geometry['left'] === 'center')
+		{
+			$geometry['left'] = floor(($width / 2) - ($geometry['width'] / 2));
+		}
+		elseif ($geometry['left'] === 'left')
+		{
+			$geometry['left'] = 0;
+		}
+		elseif ($geometry['left'] === 'right')
+		{
+			$geometry['left'] = $width - $geometry['height'];
+		}
+
+		// Restore error reporting
+		error_reporting($reporting);
+	}
+
+	/**
+	 * Return the current width and height of the temporary image. This is mainly
+	 * needed for sanitizing the geometry.
+	 *
+	 * @return  array  width, height
+	 */
+	abstract protected function properties();
+
+	/**
+	 * Process an image with a set of actions.
+	 *
+	 * @param   string   image filename
+	 * @param   array    actions to execute
+	 * @param   string   destination directory path
+	 * @param   string   destination filename
+	 * @param   boolean  render the image
+	 * @param   string   background color
+	 * @return  boolean
+	 */
+	abstract public function process($image, $actions, $dir, $file, $render = FALSE, $background = NULL);
+
+	/**
+	 * Flip an image. Valid directions are horizontal and vertical.
+	 *
+	 * @param   integer   direction to flip
+	 * @return  boolean
+	 */
+	abstract function flip($direction);
+
+	/**
+	 * Crop an image. Valid properties are: width, height, top, left.
+	 *
+	 * @param   array     new properties
+	 * @return  boolean
+	 */
+	abstract function crop($properties);
+
+	/**
+	 * Resize an image. Valid properties are: width, height, and master.
+	 *
+	 * @param   array     new properties
+	 * @return  boolean
+	 */
+	abstract public function resize($properties);
+
+	/**
+	 * Rotate an image. Valid amounts are -180 to 180.
+	 *
+	 * @param   integer   amount to rotate
+	 * @return  boolean
+	 */
+	abstract public function rotate($amount);
+
+	/**
+	 * Sharpen and image. Valid amounts are 1 to 100.
+	 *
+	 * @param   integer  amount to sharpen
+	 * @return  boolean
+	 */
+	abstract public function sharpen($amount);
+
+	/**
+	 * Overlay a second image. Valid properties are: overlay_file, mime, x, y and transparency.
+	 *
+	 * @return  boolean
+	 */
+	abstract public function composite($properties);
+
+} // End Image Driver
\ No newline at end of file
diff --git a/system/libraries/drivers/Image/GD.php b/system/libraries/drivers/Image/GD.php
new file mode 100644
index 0000000..6ffffe8
--- /dev/null
+++ b/system/libraries/drivers/Image/GD.php
@@ -0,0 +1,440 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * GD Image Driver.
+ *
+ * $Id: GD.php 4679 2009-11-10 01:45:52Z isaiah $
+ *
+ * @package    Image
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Image_GD_Driver extends Image_Driver {
+
+	// A transparent PNG as a string
+	protected static $blank_png;
+	protected static $blank_png_width;
+	protected static $blank_png_height;
+
+	public function __construct()
+	{
+		// Make sure that GD2 is available
+		if ( ! function_exists('gd_info'))
+			throw new Kohana_Exception('The Image library requires GD2. Please see http://php.net/gd_info for more information.');
+
+		// Get the GD information
+		$info = gd_info();
+
+		// Make sure that the GD2 is installed
+		if (strpos($info['GD Version'], '2.') === FALSE)
+			throw new Kohana_Exception('The Image library requires GD2. Please see http://php.net/gd_info for more information.');
+	}
+
+	public function process($image, $actions, $dir, $file, $render = FALSE, $background = NULL)
+	{
+		// Set the "create" function
+		switch ($image['type'])
+		{
+			case IMAGETYPE_JPEG:
+				$create = 'imagecreatefromjpeg';
+			break;
+			case IMAGETYPE_GIF:
+				$create = 'imagecreatefromgif';
+			break;
+			case IMAGETYPE_PNG:
+				$create = 'imagecreatefrompng';
+			break;
+		}
+
+		// Set the "save" function
+		switch (strtolower(substr(strrchr($file, '.'), 1)))
+		{
+			case 'jpg':
+			case 'jpeg':
+				$save = 'imagejpeg';
+			break;
+			case 'gif':
+				$save = 'imagegif';
+			break;
+			case 'png':
+				$save = 'imagepng';
+			break;
+		}
+
+		// Make sure the image type is supported for import
+		if (empty($create) OR ! function_exists($create))
+			throw new Kohana_Exception('The specified image, :type:, is not an allowed image type.', array(':type:' => $image['file']));
+
+		// Make sure the image type is supported for saving
+		if (empty($save) OR ! function_exists($save))
+			throw new Kohana_Exception('The specified image, :type:, is not an allowed image type.', array(':type:' => $dir.$file));
+
+		// Load the image
+		$this->image = $image;
+
+		// Create the GD image resource
+		$this->tmp_image = $create($image['file']);
+
+		// Get the quality setting from the actions
+		$quality = arr::remove('quality', $actions);
+
+		if ($status = $this->execute($actions))
+		{
+			// Prevent the alpha from being lost
+			imagealphablending($this->tmp_image, TRUE);
+			imagesavealpha($this->tmp_image, TRUE);
+
+			switch ($save)
+			{
+				case 'imagejpeg':
+					// Default the quality to 95
+					($quality === NULL) and $quality = 95;
+				break;
+				case 'imagegif':
+					// Remove the quality setting, GIF doesn't use it
+					unset($quality);
+				break;
+				case 'imagepng':
+					// Always use a compression level of 9 for PNGs. This does not
+					// affect quality, it only increases the level of compression!
+					$quality = 9;
+				break;
+			}
+
+			if ($render === FALSE)
+			{
+				// Set the status to the save return value, saving with the quality requested
+				$status = isset($quality) ? $save($this->tmp_image, $dir.$file, $quality) : $save($this->tmp_image, $dir.$file);
+			}
+			else
+			{
+				// Output the image directly to the browser
+				switch ($save)
+				{
+					case 'imagejpeg':
+						header('Content-Type: image/jpeg');
+					break;
+					case 'imagegif':
+						header('Content-Type: image/gif');
+					break;
+					case 'imagepng':
+						header('Content-Type: image/png');
+					break;
+				}
+
+				$status = isset($quality) ? $save($this->tmp_image, NULL, $quality) : $save($this->tmp_image);
+			}
+
+			// Destroy the temporary image
+			imagedestroy($this->tmp_image);
+		}
+
+		return $status;
+	}
+
+	public function flip($direction)
+	{
+		// Get the current width and height
+		$width = imagesx($this->tmp_image);
+		$height = imagesy($this->tmp_image);
+
+		// Create the flipped image
+		$flipped = $this->imagecreatetransparent($width, $height);
+
+		if ($direction === Image::HORIZONTAL)
+		{
+			for ($x = 0; $x < $width; $x++)
+			{
+				$status = imagecopy($flipped, $this->tmp_image, $x, 0, $width - $x - 1, 0, 1, $height);
+			}
+		}
+		elseif ($direction === Image::VERTICAL)
+		{
+			for ($y = 0; $y < $height; $y++)
+			{
+				$status = imagecopy($flipped, $this->tmp_image, 0, $y, 0, $height - $y - 1, $width, 1);
+			}
+		}
+		else
+		{
+			// Do nothing
+			return TRUE;
+		}
+
+		if ($status === TRUE)
+		{
+			// Swap the new image for the old one
+			imagedestroy($this->tmp_image);
+			$this->tmp_image = $flipped;
+		}
+
+		return $status;
+	}
+
+	public function crop($properties)
+	{
+		// Sanitize the cropping settings
+		$this->sanitize_geometry($properties);
+
+		// Get the current width and height
+		$width = imagesx($this->tmp_image);
+		$height = imagesy($this->tmp_image);
+
+		// Create the temporary image to copy to
+		$img = $this->imagecreatetransparent($properties['width'], $properties['height']);
+
+		// Execute the crop
+		if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, $properties['left'], $properties['top'], $width, $height, $width, $height))
+		{
+			// Swap the new image for the old one
+			imagedestroy($this->tmp_image);
+			$this->tmp_image = $img;
+		}
+
+		return $status;
+	}
+
+	public function resize($properties)
+	{
+		// Get the current width and height
+		$width = imagesx($this->tmp_image);
+		$height = imagesy($this->tmp_image);
+
+		if (substr($properties['width'], -1) === '%')
+		{
+			// Recalculate the percentage to a pixel size
+			$properties['width'] = round($width * (substr($properties['width'], 0, -1) / 100));
+		}
+
+		if (substr($properties['height'], -1) === '%')
+		{
+			// Recalculate the percentage to a pixel size
+			$properties['height'] = round($height * (substr($properties['height'], 0, -1) / 100));
+		}
+
+		// Recalculate the width and height, if they are missing
+		empty($properties['width'])  and $properties['width']  = round($width * $properties['height'] / $height);
+		empty($properties['height']) and $properties['height'] = round($height * $properties['width'] / $width);
+
+		if ($properties['master'] === Image::AUTO)
+		{
+			// Change an automatic master dim to the correct type
+			$properties['master'] = (($width / $properties['width']) > ($height / $properties['height'])) ? Image::WIDTH : Image::HEIGHT;
+		}
+
+		if (empty($properties['height']) OR $properties['master'] === Image::WIDTH)
+		{
+			// Recalculate the height based on the width
+			$properties['height'] = round($height * $properties['width'] / $width);
+		}
+
+		if (empty($properties['width']) OR $properties['master'] === Image::HEIGHT)
+		{
+			// Recalculate the width based on the height
+			$properties['width'] = round($width * $properties['height'] / $height);
+		}
+
+		// Test if we can do a resize without resampling to speed up the final resize
+		if ($properties['width'] > $width / 2 AND $properties['height'] > $height / 2)
+		{
+			// Presize width and height
+			$pre_width = $width;
+			$pre_height = $height;
+
+			// The maximum reduction is 10% greater than the final size
+			$max_reduction_width  = round($properties['width']  * 1.1);
+			$max_reduction_height = round($properties['height'] * 1.1);
+
+			// Reduce the size using an O(2n) algorithm, until it reaches the maximum reduction
+			while ($pre_width / 2 > $max_reduction_width AND $pre_height / 2 > $max_reduction_height)
+			{
+				$pre_width /= 2;
+				$pre_height /= 2;
+			}
+
+			// Create the temporary image to copy to
+			$img = $this->imagecreatetransparent($pre_width, $pre_height);
+
+			if ($status = imagecopyresized($img, $this->tmp_image, 0, 0, 0, 0, $pre_width, $pre_height, $width, $height))
+			{
+				// Swap the new image for the old one
+				imagedestroy($this->tmp_image);
+				$this->tmp_image = $img;
+			}
+
+			// Set the width and height to the presize
+			$width  = $pre_width;
+			$height = $pre_height;
+		}
+
+		// Create the temporary image to copy to
+		$img = $this->imagecreatetransparent($properties['width'], $properties['height']);
+
+		// Execute the resize
+		if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, 0, 0, $properties['width'], $properties['height'], $width, $height))
+		{
+			// Swap the new image for the old one
+			imagedestroy($this->tmp_image);
+			$this->tmp_image = $img;
+		}
+
+		return $status;
+	}
+
+	public function rotate($amount)
+	{
+		// Use current image to rotate
+		$img = $this->tmp_image;
+
+		// White, with an alpha of 0
+		$transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
+
+		// Rotate, setting the transparent color
+		$img = imagerotate($img, 360 - $amount, $transparent, -1);
+
+		// Fill the background with the transparent "color"
+		imagecolortransparent($img, $transparent);
+
+		// Merge the images
+		if ($status = imagecopymerge($this->tmp_image, $img, 0, 0, 0, 0, imagesx($this->tmp_image), imagesy($this->tmp_image), 100))
+		{
+			// Prevent the alpha from being lost
+			imagealphablending($img, TRUE);
+			imagesavealpha($img, TRUE);
+
+			// Swap the new image for the old one
+			imagedestroy($this->tmp_image);
+			$this->tmp_image = $img;
+		}
+
+		return $status;
+	}
+
+	public function sharpen($amount)
+	{
+		// Make sure that the sharpening function is available
+		if ( ! function_exists('imageconvolution'))
+			throw new Kohana_Exception('Your configured driver does not support the :method: image transformation.', array(':method:' => __FUNCTION__));
+
+		// Amount should be in the range of 18-10
+		$amount = round(abs(-18 + ($amount * 0.08)), 2);
+
+		// Gaussian blur matrix
+		$matrix = array
+		(
+			array(-1,   -1,    -1),
+			array(-1, $amount, -1),
+			array(-1,   -1,    -1),
+		);
+
+		// Perform the sharpen
+		return imageconvolution($this->tmp_image, $matrix, $amount - 8, 0);
+	}
+
+	public function composite($properties)
+	{
+		switch($properties['mime'])
+		{
+			case "image/jpeg":
+				$overlay_img = imagecreatefromjpeg($properties['overlay_file']);
+			break;
+
+			case "image/gif":
+				$overlay_img = imagecreatefromgif($properties['overlay_file']);
+			break;
+
+			case "image/png":
+				$overlay_img = imagecreatefrompng($properties['overlay_file']);
+			break;
+		}
+
+		$this->imagecopymerge_alpha($this->tmp_image, $overlay_img, $properties['x'], $properties['y'], 0, 0, imagesx($overlay_img), imagesy($overlay_img), $properties['transparency']);
+
+		imagedestroy($overlay_img);
+
+		return TRUE;
+	}
+
+	/**
+	 * A replacement for php's imagecopymerge() function that supports the alpha channel
+	 * See php bug #23815:  http://bugs.php.net/bug.php?id=23815
+	 *
+	 * @param  resource		$dst_im		Destination image link resource
+	 * @param  resource		$src_im		Source image link resource
+	 * @param  integer		$dst_x		x-coordinate of destination point
+	 * @param  integer		$dst_y		y-coordinate of destination point
+	 * @param  integer		$src_x		x-coordinate of source point
+	 * @param  integer		$src_y		y-coordinate of source point
+	 * @param  integer		$src_w		Source width
+	 * @param  integer		$src_h		Source height
+	 * @param  integer		$pct		Transparency percent (0 to 100)
+	 */
+	protected function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct)
+	{
+		// Create a new blank image the site of our source image
+		$cut = imagecreatetruecolor($src_w, $src_h);
+
+		// Copy the blank image into the destination image where the source goes
+		imagecopy($cut, $dst_im, 0, 0, $dst_x, $dst_y, $src_w, $src_h);
+
+		// Place the source image in the destination image
+		imagecopy($cut, $src_im, 0, 0, $src_x, $src_y, $src_w, $src_h);
+		imagecopymerge($dst_im, $cut, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct);
+	}
+
+	protected function properties()
+	{
+		return array(imagesx($this->tmp_image), imagesy($this->tmp_image));
+	}
+
+	/**
+	 * Returns an image with a transparent background. Used for rotating to
+	 * prevent unfilled backgrounds.
+	 *
+	 * @param   integer  image width
+	 * @param   integer  image height
+	 * @return  resource
+	 */
+	protected function imagecreatetransparent($width, $height)
+	{
+		if ($width < 1)
+		{
+			$width = 1;
+		}
+
+		if ($height < 1)
+		{
+			$height = 1;
+		}
+
+		if (self::$blank_png === NULL)
+		{
+			// Decode the blank PNG if it has not been done already
+			self::$blank_png = imagecreatefromstring(base64_decode
+			(
+				'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29'.
+				'mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADqSURBVHjaYvz//z/DYAYAAcTEMMgBQAANegcCBN'.
+				'CgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQ'.
+				'AANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoH'.
+				'AgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB'.
+				'3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAgAEAMpcDTTQWJVEAAAAASUVORK5CYII='
+			));
+
+			// Set the blank PNG width and height
+			self::$blank_png_width = imagesx(self::$blank_png);
+			self::$blank_png_height = imagesy(self::$blank_png);
+		}
+
+		$img = imagecreatetruecolor($width, $height);
+
+		// Resize the blank image
+		imagecopyresized($img, self::$blank_png, 0, 0, 0, 0, $width, $height, self::$blank_png_width, self::$blank_png_height);
+
+		// Prevent the alpha from being lost
+		imagealphablending($img, FALSE);
+		imagesavealpha($img, TRUE);
+
+		return $img;
+	}
+
+} // End Image GD Driver
\ No newline at end of file
diff --git a/system/libraries/drivers/Image/GraphicsMagick.php b/system/libraries/drivers/Image/GraphicsMagick.php
new file mode 100644
index 0000000..89b40b4
--- /dev/null
+++ b/system/libraries/drivers/Image/GraphicsMagick.php
@@ -0,0 +1,225 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * GraphicsMagick Image Driver.
+ *
+ * @package    Image
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Image_GraphicsMagick_Driver extends Image_Driver {
+
+	// Directory that GM is installed in
+	protected $dir = '';
+
+	// Command extension (exe for windows)
+	protected $ext = '';
+
+	// Temporary image filename
+	protected $tmp_image;
+
+	/**
+	 * Attempts to detect the GraphicsMagick installation directory.
+	 *
+	 * @throws  Kohana_Exception
+	 * @param   array   configuration
+	 * @return  void
+	 */
+	public function __construct($config)
+	{
+		if (empty($config['directory']))
+		{
+			// Attempt to locate GM by using "which" (only works for *nix!)
+			if ( ! is_file($path = exec('which gm')))
+				throw new Kohana_Exception('The GraphicsMagick directory specified does not contain a required program.');
+
+			$config['directory'] = dirname($path);
+		}
+
+		// Set the command extension
+		$this->ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : '';
+
+		// Check to make sure the provided path is correct
+		if ( ! is_file(realpath($config['directory']).'/gm'.$this->ext))
+			throw new Kohana_Exception('The GraphicsMagick directory specified does not contain a required program, :gm:.', array(':gm:' => 'gm'.$this->ext));
+
+
+		// Set the installation directory
+		$this->dir = str_replace('\\', '/', realpath($config['directory'])).'/';
+	}
+
+	/**
+	 * Creates a temporary image and executes the given actions. By creating a
+	 * temporary copy of the image before manipulating it, this process is atomic.
+	 */
+	public function process($image, $actions, $dir, $file, $render = FALSE, $background = NULL)
+	{
+		// Need to implement $background support
+		if ($background !== NULL)
+			throw new Kohana_Exception('The GraphicsMagick driver does not support setting a background color');
+
+		// We only need the filename
+		$image = $image['file'];
+
+		// Unique temporary filename
+		$this->tmp_image = $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.'));
+
+		// Copy the image to the temporary file
+		copy($image, $this->tmp_image);
+
+		// Quality change is done last
+		$quality = (int) arr::remove('quality', $actions);
+
+		// Use 95 for the default quality
+		empty($quality) and $quality = 95;
+
+		// All calls to these will need to be escaped, so do it now
+		$this->cmd_image = escapeshellarg($this->tmp_image);
+		$this->new_image = ($render)? $this->cmd_image : escapeshellarg($dir.$file);
+
+		if ($status = $this->execute($actions))
+		{
+			// Use convert to change the image into its final version. This is
+			// done to allow the file type to change correctly, and to handle
+			// the quality conversion in the most effective way possible.
+			if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -quality '.$quality.'% '.$this->cmd_image.' '.$this->new_image))
+			{
+				$this->errors[] = $error;
+			}
+			else
+			{
+				// Output the image directly to the browser
+				if ($render !== FALSE)
+				{
+					$contents = file_get_contents($this->tmp_image);
+					switch (substr($file, strrpos($file, '.') + 1))
+					{
+						case 'jpg':
+						case 'jpeg':
+							header('Content-Type: image/jpeg');
+						break;
+						case 'gif':
+							header('Content-Type: image/gif');
+						break;
+						case 'png':
+							header('Content-Type: image/png');
+						break;
+ 					}
+					echo $contents;
+				}
+			}
+		}
+
+		// Remove the temporary image
+		unlink($this->tmp_image);
+		$this->tmp_image = '';
+
+		return $status;
+	}
+
+	public function crop($prop)
+	{
+		// Sanitize and normalize the properties into geometry
+		$this->sanitize_geometry($prop);
+
+		// Set the IM geometry based on the properties
+		$geometry = escapeshellarg($prop['width'].'x'.$prop['height'].'+'.$prop['left'].'+'.$prop['top']);
+
+		if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -crop '.$geometry.' '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	public function flip($dir)
+	{
+		// Convert the direction into a GM command
+		$dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip';
+
+		if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' '.$dir.' '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	public function resize($prop)
+	{
+		switch ($prop['master'])
+		{
+			case Image::WIDTH:  // Wx
+				$dim = escapeshellarg($prop['width'].'x');
+			break;
+			case Image::HEIGHT: // xH
+				$dim = escapeshellarg('x'.$prop['height']);
+			break;
+			case Image::AUTO:   // WxH
+				$dim = escapeshellarg($prop['width'].'x'.$prop['height']);
+			break;
+			case Image::NONE:   // WxH!
+				$dim = escapeshellarg($prop['width'].'x'.$prop['height'].'!');
+			break;
+		}
+
+		// Use "convert" to change the width and height
+		if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -resize '.$dim.' '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	public function rotate($amt)
+	{
+		if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -rotate '.escapeshellarg($amt).' -background transparent '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	public function sharpen($amount)
+	{
+		// Set the sigma, radius, and amount. The amount formula allows a nice
+		// spread between 1 and 100 without pixelizing the image badly.
+		$sigma  = 0.5;
+		$radius = $sigma * 2;
+		$amount = round(($amount / 80) * 3.14, 2);
+
+		// Convert the amount to an GM command
+		$sharpen = escapeshellarg($radius.'x'.$sigma.'+'.$amount.'+0');
+
+		if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -unsharp '.$sharpen.' '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	public function composite($properties)
+	{
+		if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' composite').' -geometry ' . escapeshellarg('+'.$properties['x'].'+'.$properties['y']).' -dissolve '.escapeshellarg($properties['transparency']).' '.escapeshellarg($properties['overlay_file']).' '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+		return TRUE;
+	}
+
+	protected function properties()
+	{
+		return array_slice(getimagesize($this->tmp_image), 0, 2, FALSE);
+	}
+
+} // End Image GraphicsMagick Driver
\ No newline at end of file
diff --git a/system/libraries/drivers/Image/ImageMagick.php b/system/libraries/drivers/Image/ImageMagick.php
new file mode 100644
index 0000000..55c0ba2
--- /dev/null
+++ b/system/libraries/drivers/Image/ImageMagick.php
@@ -0,0 +1,233 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * ImageMagick Image Driver.
+ *
+ * $Id: ImageMagick.php 4679 2009-11-10 01:45:52Z isaiah $
+ *
+ * @package    Image
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Image_ImageMagick_Driver extends Image_Driver {
+
+	// Directory that IM is installed in
+	protected $dir = '';
+
+	// Command extension (exe for windows)
+	protected $ext = '';
+
+	// Temporary image filename
+	protected $tmp_image;
+
+	/**
+	 * Attempts to detect the ImageMagick installation directory.
+	 *
+	 * @throws  Kohana_Exception
+	 * @param   array   configuration
+	 * @return  void
+	 */
+	public function __construct($config)
+	{
+		if (empty($config['directory']))
+		{
+			// Attempt to locate IM by using "which" (only works for *nix!)
+			if ( ! is_file($path = exec('which convert')))
+				throw new Kohana_Exception('The ImageMagick directory specified does not contain a required program.');
+
+			$config['directory'] = dirname($path);
+		}
+
+		// Set the command extension
+		$this->ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : '';
+
+		// Check to make sure the provided path is correct
+		if ( ! is_file(realpath($config['directory']).'/convert'.$this->ext))
+			throw new Kohana_Exception('The ImageMagick directory specified does not contain a required program, :im:', array(':im:' => 'convert'.$this->ext));
+
+		// Set the installation directory
+		$this->dir = str_replace('\\', '/', realpath($config['directory'])).'/';
+	}
+
+	/**
+	 * Creates a temporary image and executes the given actions. By creating a
+	 * temporary copy of the image before manipulating it, this process is atomic.
+	 */
+	public function process($image, $actions, $dir, $file, $render = FALSE, $background = NULL)
+	{
+		// We only need the filename
+		$image = $image['file'];
+
+		// Unique temporary filename
+		$this->tmp_image = $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.'));
+
+		// Copy the image to the temporary file
+		copy($image, $this->tmp_image);
+
+		// Quality change is done last
+		$quality = (int) arr::remove('quality', $actions);
+
+		// Use 95 for the default quality
+		empty($quality) and $quality = 95;
+
+		if (is_string($background))
+		{
+			// Set the background color
+			$this->background = escapeshellarg($background);
+		}
+		else
+		{
+			// Use a transparent background
+			$this->background = 'transparent';
+		}
+
+		// All calls to these will need to be escaped, so do it now
+		$this->cmd_image = escapeshellarg($this->tmp_image);
+		$this->new_image = $render ? $this->cmd_image : escapeshellarg($dir.$file);
+
+		if ($status = $this->execute($actions))
+		{
+			// Use convert to change the image into its final version. This is
+			// done to allow the file type to change correctly, and to handle
+			// the quality conversion in the most effective way possible.
+			if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -background '.$this->background.' -flatten -quality '.$quality.'% '.$this->cmd_image.' '.$this->new_image))
+			{
+				$this->errors[] = $error;
+			}
+			else
+			{
+				// Output the image directly to the browser
+				if ($render === TRUE)
+				{
+					$contents = file_get_contents($this->tmp_image);
+					switch (substr($file, strrpos($file, '.') + 1))
+					{
+						case 'jpg':
+						case 'jpeg':
+							header('Content-Type: image/jpeg');
+						break;
+						case 'gif':
+							header('Content-Type: image/gif');
+						break;
+						case 'png':
+							header('Content-Type: image/png');
+						break;
+ 					}
+					echo $contents;
+				}
+			}
+		}
+
+		// Remove the temporary image
+		unlink($this->tmp_image);
+		$this->tmp_image = '';
+
+		return $status;
+	}
+
+	public function crop($prop)
+	{
+		// Sanitize and normalize the properties into geometry
+		$this->sanitize_geometry($prop);
+
+		// Set the IM geometry based on the properties
+		$geometry = escapeshellarg($prop['width'].'x'.$prop['height'].'+'.$prop['left'].'+'.$prop['top']);
+
+		if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -background '.$this->background.' -flatten -crop '.$geometry.'! '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	public function flip($dir)
+	{
+		// Convert the direction into a IM command
+		$dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip';
+
+		if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -background '.$this->background.' -flatten '.$dir.' '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	public function resize($prop)
+	{
+		switch ($prop['master'])
+		{
+			case Image::WIDTH:  // Wx
+				$dim = escapeshellarg($prop['width'].'x');
+			break;
+			case Image::HEIGHT: // xH
+				$dim = escapeshellarg('x'.$prop['height']);
+			break;
+			case Image::AUTO:   // WxH
+				$dim = escapeshellarg($prop['width'].'x'.$prop['height']);
+			break;
+			case Image::NONE:   // WxH!
+				$dim = escapeshellarg($prop['width'].'x'.$prop['height'].'!');
+			break;
+		}
+
+		// Use "convert" to change the width and height
+		if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -background '.$this->background.' -flatten -resize '.$dim.' '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	public function rotate($amt)
+	{
+		if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -background '.$this->background.' -flatten -rotate '.escapeshellarg($amt).' -background transparent '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	public function sharpen($amount)
+	{
+		// Set the sigma, radius, and amount. The amount formula allows a nice
+		// spread between 1 and 100 without pixelizing the image badly.
+		$sigma  = 0.5;
+		$radius = $sigma * 2;
+		$amount = round(($amount / 80) * 3.14, 2);
+
+		// Convert the amount to an IM command
+		$sharpen = escapeshellarg($radius.'x'.$sigma.'+'.$amount.'+0');
+
+		if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -background '.$this->background.' -flatten -unsharp '.$sharpen.' '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	public function composite($properties)
+	{
+		if ($error = exec(escapeshellcmd($this->dir.'composite'.$this->ext).' -geometry ' . escapeshellarg('+'.$properties['x'].'+'.$properties['y']).' -dissolve '.escapeshellarg($properties['transparency']).' '.escapeshellarg($properties['overlay_file']).' '.$this->cmd_image.' '.$this->cmd_image))
+		{
+			$this->errors[] = $error;
+			return FALSE;
+		}
+		return TRUE;
+	}
+
+	protected function properties()
+	{
+		return array_slice(getimagesize($this->tmp_image), 0, 2, FALSE);
+	}
+
+} // End Image ImageMagick Driver
\ No newline at end of file
diff --git a/system/libraries/drivers/Log.php b/system/libraries/drivers/Log.php
new file mode 100644
index 0000000..cd6dba7
--- /dev/null
+++ b/system/libraries/drivers/Log.php
@@ -0,0 +1,22 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Log API driver.
+ *
+ * $Id: Log.php 4679 2009-11-10 01:45:52Z isaiah $
+ *
+ * @package    Kohana_Log
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+abstract class Log_Driver {
+
+	protected $config = array();
+
+	public function __construct(array $config)
+	{
+		$this->config = $config;
+	}
+
+	abstract public function save(array $messages);
+}
\ No newline at end of file
diff --git a/system/libraries/drivers/Log/Database.php b/system/libraries/drivers/Log/Database.php
new file mode 100644
index 0000000..19db974
--- /dev/null
+++ b/system/libraries/drivers/Log/Database.php
@@ -0,0 +1,40 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Log API driver.
+ *
+ * $Id: Database.php 4679 2009-11-10 01:45:52Z isaiah $
+ *
+ * @package    Kohana_Log
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Log_Database_Driver extends Log_Driver {
+
+	public function save(array $messages)
+	{
+		$insert = db::build($this->config['group'])
+						->insert($this->config['table'])
+						->columns(array('date', 'level', 'message'));
+
+		$run_insert = FALSE;
+
+		foreach ($messages AS $message)
+		{
+			if ($this->config['log_levels'][$message['type']] <= $this->config['log_threshold'])
+			{
+				// Add new message to database
+				$insert->values($message);
+
+				// There is data to insert
+				$run_insert = TRUE;
+			}
+		}
+
+		// Update the database
+		if ($run_insert)
+		{
+			$insert->execute();
+		}
+	}
+}
\ No newline at end of file
diff --git a/system/libraries/drivers/Log/File.php b/system/libraries/drivers/Log/File.php
new file mode 100644
index 0000000..6ad565b
--- /dev/null
+++ b/system/libraries/drivers/Log/File.php
@@ -0,0 +1,44 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Log API driver.
+ *
+ * $Id: File.php 4679 2009-11-10 01:45:52Z isaiah $
+ *
+ * @package    Kohana_Log
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Log_File_Driver extends Log_Driver {
+
+	public function save(array $messages)
+	{
+		// Filename of the log
+		$filename = $this->config['log_directory'].'/'.date('Y-m-d').'.log'.EXT;
+
+		if ( ! is_file($filename))
+		{
+			// Write the SYSPATH checking header
+			file_put_contents($filename,
+				'<?php defined(\'SYSPATH\') or die(\'No direct script access.\'); ?>'.PHP_EOL.PHP_EOL);
+
+			// Prevent external writes
+			chmod($filename, $this->config['posix_permissions']);
+		}
+
+		foreach ($messages AS $message)
+		{
+			if ($this->config['log_levels'][$message['type']] <= $this->config['log_threshold'])
+			{
+				// Add a new message line
+				$messages_to_write[] = date($this->config['date_format'], $message['date']).' --- '.$message['type'].': '.$message['message'];
+			}
+		}
+
+		if ( ! empty($messages_to_write))
+		{
+			// Write messages to log file
+			file_put_contents($filename, implode(PHP_EOL, $messages_to_write).PHP_EOL, FILE_APPEND);
+		}
+	}
+}
\ No newline at end of file
diff --git a/system/libraries/drivers/Log/Syslog.php b/system/libraries/drivers/Log/Syslog.php
new file mode 100644
index 0000000..5da5d25
--- /dev/null
+++ b/system/libraries/drivers/Log/Syslog.php
@@ -0,0 +1,34 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Log API driver.
+ *
+ * @package    Kohana_Log
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Log_Syslog_Driver extends Log_Driver {
+
+	protected $syslog_levels = array('error' => LOG_ERR,
+	                                 'alert' => LOG_WARNING,
+	                                 'info'  => LOG_INFO,
+	                                 'debug' => LOG_DEBUG);
+
+	public function save(array $messages)
+	{
+		// Open the connection to syslog
+		openlog($this->config['ident'], LOG_CONS, LOG_USER);
+
+		do
+		{
+			// Load the next message
+			list ($date, $type, $text) = array_shift($messages);
+
+			syslog($this->syslog_levels[$type], $text);
+		}
+		while ( ! empty($messages));
+
+		// Close connection to syslog
+		closelog();
+	}
+}
\ No newline at end of file
diff --git a/system/libraries/drivers/Session.php b/system/libraries/drivers/Session.php
new file mode 100644
index 0000000..e591b91
--- /dev/null
+++ b/system/libraries/drivers/Session.php
@@ -0,0 +1,70 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Session driver interface
+ *
+ * $Id: Session.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+interface Session_Driver {
+
+	/**
+	 * Opens a session.
+	 *
+	 * @param   string   save path
+	 * @param   string   session name
+	 * @return  boolean
+	 */
+	public function open($path, $name);
+
+	/**
+	 * Closes a session.
+	 *
+	 * @return  boolean
+	 */
+	public function close();
+
+	/**
+	 * Reads a session.
+	 *
+	 * @param   string  session id
+	 * @return  string
+	 */
+	public function read($id);
+
+	/**
+	 * Writes a session.
+	 *
+	 * @param   string   session id
+	 * @param   string   session data
+	 * @return  boolean
+	 */
+	public function write($id, $data);
+
+	/**
+	 * Destroys a session.
+	 *
+	 * @param   string   session id
+	 * @return  boolean
+	 */
+	public function destroy($id);
+
+	/**
+	 * Regenerates the session id.
+	 *
+	 * @return  string
+	 */
+	public function regenerate();
+
+	/**
+	 * Garbage collection.
+	 *
+	 * @param   integer  session expiration period
+	 * @return  boolean
+	 */
+	public function gc($maxlifetime);
+
+} // End Session Driver Interface
\ No newline at end of file
diff --git a/system/libraries/drivers/Session/Cache.php b/system/libraries/drivers/Session/Cache.php
new file mode 100644
index 0000000..459f8b0
--- /dev/null
+++ b/system/libraries/drivers/Session/Cache.php
@@ -0,0 +1,108 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Session cache driver.
+ *
+ * Cache library config goes in the session.storage config entry:
+ * $config['storage'] = array(
+ *     'driver' => 'apc',
+ *     'requests' => 10000
+ * );
+ * Lifetime does not need to be set as it is
+ * overridden by the session expiration setting.
+ *
+ * $Id: Cache.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Session_Cache_Driver implements Session_Driver {
+
+	protected $cache;
+	protected $encrypt;
+
+	public function __construct()
+	{
+		// Load Encrypt library
+		if (Kohana::config('session.encryption'))
+		{
+			$this->encrypt = new Encrypt;
+		}
+
+		Kohana_Log::add('debug', 'Session Cache Driver Initialized');
+	}
+
+	public function open($path, $name)
+	{
+		$config = Kohana::config('session.storage');
+
+		if (empty($config))
+		{
+			// Load the default group
+			$config = Kohana::config('cache.default');
+		}
+		elseif (is_string($config))
+		{
+			$name = $config;
+
+			// Test the config group name
+			if (($config = Kohana::config('cache.'.$config)) === NULL)
+				throw new Kohana_Exception('The :group: group is not defined in your configuration.', array(':group:' => $name));
+		}
+
+		$config['lifetime'] = (Kohana::config('session.expiration') == 0) ? 86400 : Kohana::config('session.expiration');
+		$this->cache = new Cache($config);
+
+		return is_object($this->cache);
+	}
+
+	public function close()
+	{
+		return TRUE;
+	}
+
+	public function read($id)
+	{
+		$id = 'session_'.$id;
+		if ($data = $this->cache->get($id))
+		{
+			return Kohana::config('session.encryption') ? $this->encrypt->decode($data) : $data;
+		}
+
+		// Return value must be string, NOT a boolean
+		return '';
+	}
+
+	public function write($id, $data)
+	{
+		if ( ! Session::$should_save)
+			return TRUE;
+
+		$id = 'session_'.$id;
+		$data = Kohana::config('session.encryption') ? $this->encrypt->encode($data) : $data;
+
+		return $this->cache->set($id, $data);
+	}
+
+	public function destroy($id)
+	{
+		$id = 'session_'.$id;
+		return $this->cache->delete($id);
+	}
+
+	public function regenerate()
+	{
+		session_regenerate_id(TRUE);
+
+		// Return new session id
+		return session_id();
+	}
+
+	public function gc($maxlifetime)
+	{
+		// Just return, caches are automatically cleaned up
+		return TRUE;
+	}
+
+} // End Session Cache Driver
diff --git a/system/libraries/drivers/Session/Cookie.php b/system/libraries/drivers/Session/Cookie.php
new file mode 100644
index 0000000..88f5e21
--- /dev/null
+++ b/system/libraries/drivers/Session/Cookie.php
@@ -0,0 +1,83 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Session cookie driver.
+ *
+ * $Id: Cookie.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Session_Cookie_Driver implements Session_Driver {
+
+	protected $cookie_name;
+	protected $encrypt; // Library
+
+	public function __construct()
+	{
+		$this->cookie_name = Kohana::config('session.name').'_data';
+
+		if (Kohana::config('session.encryption'))
+		{
+			$this->encrypt = Encrypt::instance();
+		}
+
+		Kohana_Log::add('debug', 'Session Cookie Driver Initialized');
+	}
+
+	public function open($path, $name)
+	{
+		return TRUE;
+	}
+
+	public function close()
+	{
+		return TRUE;
+	}
+
+	public function read($id)
+	{
+		$data = (string) cookie::get($this->cookie_name);
+
+		if ($data == '')
+			return $data;
+
+		return empty($this->encrypt) ? base64_decode($data) : $this->encrypt->decode($data);
+	}
+
+	public function write($id, $data)
+	{
+		if ( ! Session::$should_save)
+			return TRUE;
+
+		$data = empty($this->encrypt) ? base64_encode($data) : $this->encrypt->encode($data);
+
+		if (strlen($data) > 4048)
+		{
+			Kohana_Log::add('error', 'Session ('.$id.') data exceeds the 4KB limit, ignoring write.');
+			return FALSE;
+		}
+
+		return cookie::set($this->cookie_name, $data, Kohana::config('session.expiration'));
+	}
+
+	public function destroy($id)
+	{
+		return cookie::delete($this->cookie_name);
+	}
+
+	public function regenerate()
+	{
+		session_regenerate_id(TRUE);
+
+		// Return new id
+		return session_id();
+	}
+
+	public function gc($maxlifetime)
+	{
+		return TRUE;
+	}
+
+} // End Session Cookie Driver Class
\ No newline at end of file
diff --git a/system/libraries/drivers/Session/Database.php b/system/libraries/drivers/Session/Database.php
new file mode 100644
index 0000000..7b372d2
--- /dev/null
+++ b/system/libraries/drivers/Session/Database.php
@@ -0,0 +1,178 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Session database driver.
+ *
+ * $Id: Database.php 4729 2009-12-29 20:35:19Z isaiah $
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2007-2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+class Session_Database_Driver implements Session_Driver {
+
+	/*
+	CREATE TABLE sessions
+	(
+		session_id VARCHAR(127) NOT NULL,
+		last_activity INT(10) UNSIGNED NOT NULL,
+		data TEXT NOT NULL,
+		PRIMARY KEY (session_id)
+	);
+	*/
+
+	// Database settings
+	protected $db = 'default';
+	protected $table = 'sessions';
+
+	// Encryption
+	protected $encrypt;
+
+	// Session settings
+	protected $session_id;
+	protected $written = FALSE;
+
+	public function __construct()
+	{
+		// Load configuration
+		$config = Kohana::config('session');
+
+		if ( ! empty($config['encryption']))
+		{
+			// Load encryption
+			$this->encrypt = Encrypt::instance();
+		}
+
+		if (is_array($config['storage']))
+		{
+			if ( ! empty($config['storage']['group']))
+			{
+				// Set the group name
+				$this->db = $config['storage']['group'];
+			}
+
+			if ( ! empty($config['storage']['table']))
+			{
+				// Set the table name
+				$this->table = $config['storage']['table'];
+			}
+		}
+
+		Kohana_Log::add('debug', 'Session Database Driver Initialized');
+	}
+
+	public function open($path, $name)
+	{
+		return TRUE;
+	}
+
+	public function close()
+	{
+		return TRUE;
+	}
+
+	public function read($id)
+	{
+		// Load the session
+		$query = db::select('data')
+			->from($this->table)
+			->where('session_id', '=', $id)
+			->limit(1)
+			->execute($this->db);
+
+		if ($query->count() === 0)
+		{
+			// No current session
+			$this->session_id = NULL;
+
+			return '';
+		}
+
+		// Set the current session id
+		$this->session_id = $id;
+
+		// Load the data
+		$data = $query->current()->data;
+
+		return ($this->encrypt === NULL) ? base64_decode($data) : $this->encrypt->decode($data);
+	}
+
+	public function write($id, $data)
+	{
+		if ( ! Session::$should_save)
+			return TRUE;
+
+		$data = array
+		(
+			'session_id' => $id,
+			'last_activity' => time(),
+			'data' => ($this->encrypt === NULL) ? base64_encode($data) : $this->encrypt->encode($data)
+		);
+
+		if ($this->session_id === NULL)
+		{
+			// Insert a new session
+			$query = db::insert($this->table, $data)
+				->execute($this->db);
+		}
+		elseif ($id === $this->session_id)
+		{
+			// Do not update the session_id
+			unset($data['session_id']);
+
+			// Update the existing session
+			$query = db::update($this->table)
+				->set($data)
+				->where('session_id', '=', $id)
+				->execute($this->db);
+		}
+		else
+		{
+			// Update the session and id
+			$query = db::update($this->table)
+				->set($data)
+				->where('session_id', '=', $this->session_id)
+				->execute($this->db);
+
+			// Set the new session id
+			$this->session_id = $id;
+		}
+
+		return (bool) $query->count();
+	}
+
+	public function destroy($id)
+	{
+		// Delete the requested session
+		db::delete($this->table)
+			->where('session_id', '=', $id)
+			->execute($this->db);
+
+		// Session id is no longer valid
+		$this->session_id = NULL;
+
+		return TRUE;
+	}
+
+	public function regenerate()
+	{
+		// Generate a new session id
+		session_regenerate_id();
+
+		// Return new session id
+		return session_id();
+	}
+
+	public function gc($maxlifetime)
+	{
+		// Delete all expired sessions
+		$query = db::delete($this->table)
+			->where('last_activity', '<', time() - $maxlifetime)
+			->execute($this->db);
+
+		Kohana_Log::add('debug', 'Session garbage collected: '.$query->count().' row(s) deleted.');
+
+		return TRUE;
+	}
+
+} // End Session Database Driver
diff --git a/system/messages/kohana/core.php b/system/messages/kohana/core.php
new file mode 100644
index 0000000..0fa66b0
--- /dev/null
+++ b/system/messages/kohana/core.php
@@ -0,0 +1,37 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Core Kohana messages
+ *
+ * @package    Kohana
+ * @author     Kohana Team
+ * @copyright  (c) 2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+$messages = array
+(
+	'errors' => array
+	(
+		E_KOHANA             => 'Framework Error',
+		E_PAGE_NOT_FOUND     => 'Page Not Found',
+		E_DATABASE_ERROR     => 'Database Error',
+		E_RECOVERABLE_ERROR  => 'Recoverable Error',
+		E_ERROR              => 'Fatal Error',
+		E_COMPILE_ERROR      => 'Fatal Error',
+		E_CORE_ERROR         => 'Fatal Error',
+		E_USER_ERROR         => 'Fatal Error',
+		E_PARSE              => 'Syntax Error',
+		E_WARNING            => 'Warning Message',
+		E_COMPILE_WARNING    => 'Warning Message',
+		E_CORE_WARNING       => 'Warning Message',
+		E_USER_WARNING       => 'Warning Message',
+		E_STRICT             => 'Strict Mode Error',
+		E_NOTICE             => 'Runtime Message',
+		E_USER_NOTICE        => 'Runtime Message',
+	),
+);
+
+// E_DEPRECATED is only defined in PHP >= 5.3.0
+if (defined('E_DEPRECATED'))
+{
+	$messages['errors'][E_DEPRECATED] = 'Deprecated';
+}
\ No newline at end of file
diff --git a/system/messages/validation/default.php b/system/messages/validation/default.php
new file mode 100644
index 0000000..88580a6
--- /dev/null
+++ b/system/messages/validation/default.php
@@ -0,0 +1,25 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Default validation messages
+ *
+ * @package    Validation
+ * @author     Kohana Team
+ * @copyright  (c) 2009 Kohana Team
+ * @license    http://kohanaphp.com/license
+ */
+
+$messages = array(
+	'required'      => 'The :field field is required',
+	'length'        => 'The :field field must be between :param1 and :param2 characters long',
+	'depends_on'    => 'The :field field requires the :param1 field',
+	'matches'       => 'The :field field must be the same as :param1',
+	'email'         => 'The :field field must be a valid email address',
+	'decimal'       => 'The :field field must be a decimal with :param1 places',
+	'digit'         => 'The :field field must be a digit',
+	'in_array'      => 'The :field field must be one of the available options',
+	'alpha_numeric' => 'The :field field must consist only of alphabetical or numeric characters',
+	'alpha_dash '   => 'The :field field must consist only of alphabetical, numeric, underscore and dash characters',
+	'numeric '      => 'The :field field must be a valid number',
+	'url'           => 'The :field field must be a valid url',
+	'phone'         => 'The :field field must be a valid phone number',
+);
diff --git a/system/views/kohana/error.php b/system/views/kohana/error.php
new file mode 100644
index 0000000..aa6770c
--- /dev/null
+++ b/system/views/kohana/error.php
@@ -0,0 +1,252 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+// Unique error identifier
+$error_id = uniqid('error');
+?>
+<style type="text/css">
+
+	#kohana_error {
+		background: #CFF292;
+		font-size: 1em;
+		font-family: sans-serif;
+		text-align: left;
+		color: #111;
+	}
+
+	#kohana_error h1, #kohana_error h2 {
+		margin: 0;
+		padding: 1em;
+		font-size: 1em;
+		font-weight: normal;
+		background: #CFF292;
+		color: #000000;
+	}
+
+	#kohana_error h1 a, #kohana_error h2 a {
+		color: #000;
+	}
+
+	#kohana_error h2 {
+		background: #CFF292;
+		border-top: 1px dotted;
+	}
+
+	#kohana_error h3 {
+		margin: 0;
+		padding: 0.4em 0 0;
+		font-size: 1em;
+		font-weight: normal;
+	}
+
+	#kohana_error p {
+		margin: 0;
+		padding: 0.2em 0;
+	}
+
+	#kohana_error a {
+		color: #1b323b;
+	}
+
+	#kohana_error pre {
+		overflow: auto;
+		white-space: pre-wrap;
+	}
+
+	#kohana_error table {
+		width: 100%;
+		display: block;
+		margin: 0 0 0.4em;
+		padding: 0;
+		border-collapse: collapse;
+		background: #fff;
+	}
+
+	#kohana_error table td {
+		border: solid 1px #ddd;
+		text-align: left;
+		vertical-align: top;
+		padding: 0.4em;
+	}
+
+	#kohana_error div.content {
+		padding: 0.4em 1em 1em;
+		overflow: hidden;
+		border-top: 1px dotted;
+	}
+
+	#kohana_error pre.source {
+		margin: 0 0 1em;
+		padding: 0.4em;
+		background: #fff;
+		border: dotted 1px #b7c680;
+		line-height: 1.2em;
+	}
+
+	#kohana_error pre.source span.line {
+		display: block;
+	}
+
+	#kohana_error pre.source span.highlight {
+		background: #f0eb96;
+	}
+
+	#kohana_error pre.source span.line span.number {
+		color: #666;
+	}
+
+	#kohana_error ol.trace {
+		display: block;
+		margin: 0 0 0 2em;
+		padding: 0;
+		list-style: decimal;
+	}
+
+	#kohana_error ol.trace li {
+		margin: 0;
+		padding: 0;
+	}
+</style>
+<script type="text/javascript">
+	document.write('<style type="text/css"> .collapsed { display: none; } </style>');
+	function koggle(elem)
+	{
+		elem = document.getElementById(elem);
+
+		if (elem.style && elem.style['display'])
+			// Only works with the "style" attr
+			var disp = elem.style['display'];
+		else
+			if (elem.currentStyle)
+				// For MSIE, naturally
+				var disp = elem.currentStyle['display'];
+			else
+				if (window.getComputedStyle)
+					// For most other browsers
+					var disp = document.defaultView.getComputedStyle(elem, null).getPropertyValue('display');
+
+		// Toggle the state of the "display" style
+		elem.style.display = disp == 'block' ? 'none' : 'block';
+		return false;
+	}
+</script>
+<div id="kohana_error">
+	<h1>
+		<span class="type">
+<?php echo $type?> [ <?php echo __($code)?> ]:
+		</span>
+		<span class="message">
+<?php echo $message?>
+		</span>
+	</h1>
+	<div id="<?php echo $error_id ?>" class="content">
+		<p>
+			<span class="file">
+<?php echo Kohana_Exception::debug_path($file)?>[ <?php echo $line?> ]
+			</span>
+		</p>
+
+<?php if (Kohana_Exception::$source_output AND $source_code = Kohana_Exception::debug_source($file, $line)) : ?>
+		<pre class="source"><code><?php foreach ($source_code as $num => $row) : ?><span class="line <?php if ($num == $line) echo 'highlight' ?>"><span class="number"><?php echo $num ?></span><?php echo htmlspecialchars($row, ENT_NOQUOTES, Kohana::CHARSET) ?></span><?php endforeach ?></code></pre>
+<?php endif ?>
+
+<?php if (Kohana_Exception::$trace_output) : ?>
+		<ol class="trace">
+			<?php foreach (Kohana_Exception::trace($trace) as $i=>$step): ?>
+			<li>
+				<p>
+					<span class="file">
+						<?php if ($step['file']): $source_id = $error_id.'source'.$i; ?>
+						<?php if (Kohana_Exception::$source_output AND $step['source']) : ?>
+						<a href="#<?php echo $source_id ?>" onclick="return koggle('<?php echo $source_id ?>')"><?php echo Kohana_Exception::debug_path($step['file'])?>[ <?php echo $step['line']?> ]</a>
+						<?php else : ?>
+						<span class="file"><?php echo Kohana_Exception::debug_path($step['file'])?>[ <?php echo $step['line']?> ]</span>
+						<?php endif ?>
+						<?php else : ?>
+						{<?php echo __('PHP internal call')?>}
+						<?php endif?>
+					</span>
+					&raquo;
+					<?php echo $step['function']?>(<?php if ($step['args']): $args_id = $error_id.'args'.$i; ?><a href="#<?php echo $args_id ?>" onclick="return koggle('<?php echo $args_id ?>')"><?php echo __('arguments')?></a>
+<?php endif?>)
+				</p>
+				<?php if (isset($args_id)): ?>
+				<div id="<?php echo $args_id ?>" class="collapsed">
+					<table cellspacing="0">
+						<?php foreach ($step['args'] as $name=>$arg): ?>
+						<tr>
+							<td>
+								<code>
+<?php echo $name?>
+								</code>
+							</td>
+							<td>
+								<pre><?php echo Kohana_Exception::dump($arg) ?></pre>
+							</td>
+						</tr>
+						<?php endforeach?>
+					</table>
+				</div>
+				<?php endif?>
+				<?php if (Kohana_Exception::$source_output AND $step['source'] AND isset($source_id)): ?>
+				<pre id="<?php echo $source_id ?>" class="source collapsed"><code><?php foreach ($step['source'] as $num => $row) : ?><span class="line <?php if ($num == $step['line']) echo 'highlight' ?>"><span class="number"><?php echo $num ?></span><?php echo htmlspecialchars($row, ENT_NOQUOTES, Kohana::CHARSET) ?></span><?php endforeach ?></code></pre>
+				<?php endif?>
+			</li>
+			<?php unset($args_id, $source_id); ?>
+			<?php endforeach?>
+		</ol>
+<?php endif ?>
+
+	</div>
+	<h2><a href="#<?php echo $env_id = $error_id.'environment' ?>" onclick="return koggle('<?php echo $env_id ?>')"><?php echo __('Environment')?></a></h2>
+	<div id="<?php echo $env_id ?>" class="content collapsed">
+		<?php $included = get_included_files()?>
+		<h3><a href="#<?php echo $env_id = $error_id.'environment_included' ?>" onclick="return koggle('<?php echo $env_id ?>')"><?php echo __('Included files')?></a>(<?php echo count($included)?>)</h3>
+		<div id="<?php echo $env_id ?>" class="collapsed">
+			<table cellspacing="0">
+				<?php foreach ($included as $file): ?>
+				<tr>
+					<td>
+						<code>
+<?php echo Kohana_Exception::debug_path($file)?>
+						</code>
+					</td>
+				</tr>
+				<?php endforeach?>
+			</table>
+		</div>
+		<?php $included = get_loaded_extensions()?>
+		<h3><a href="#<?php echo $env_id = $error_id.'environment_loaded' ?>" onclick="return koggle('<?php echo $env_id ?>')"><?php echo __('Loaded extensions')?></a>(<?php echo count($included)?>)</h3>
+		<div id="<?php echo $env_id ?>" class="collapsed">
+			<table cellspacing="0">
+				<?php foreach ($included as $file): ?>
+				<tr>
+					<td>
+						<code>
+<?php echo Kohana_Exception::debug_path($file)?>
+						</code>
+					</td>
+				</tr>
+				<?php endforeach?>
+			</table>
+		</div>
+		<?php foreach (array('_SESSION', '_GET', '_POST', '_FILES', '_COOKIE', '_SERVER') as $var): ?>
+		<?php if ( empty($GLOBALS[$var]) OR ! is_array($GLOBALS[$var])) continue ?>
+		<h3><a href="#<?php echo $env_id = $error_id.'environment'.strtolower($var) ?>" onclick="return koggle('<?php echo $env_id ?>')">$<?php echo $var?></a></h3>
+		<div id="<?php echo $env_id ?>" class="collapsed">
+			<table cellspacing="0">
+				<?php foreach ($GLOBALS[$var] as $key=>$value): ?>
+				<tr>
+					<td>
+						<code>
+<?php echo $key?>
+						</code>
+					</td>
+					<td>
+						<pre><?php echo Kohana_Exception::dump($value) ?></pre>
+					</td>
+				</tr>
+				<?php endforeach?>
+			</table>
+		</div>
+		<?php endforeach?>
+	</div>
+</div>
diff --git a/system/views/kohana/error_disabled.php b/system/views/kohana/error_disabled.php
new file mode 100644
index 0000000..1024eb1
--- /dev/null
+++ b/system/views/kohana/error_disabled.php
@@ -0,0 +1,19 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.'); ?>
+ <!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" xml:lang="en" lang="en">
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+		<title><?php echo htmlspecialchars(__('Unable to Complete Request'), ENT_QUOTES, Kohana::CHARSET) ?></title>
+	</head>
+	<body>
+		<div id="framework_error" style="width:24em;margin:50px auto;">
+			<h3 style="text-align:center"><?php echo htmlspecialchars(__('Unable to Complete Request'), ENT_QUOTES, Kohana::CHARSET) ?></h3>
+			<p style="text-align:center">
+<?php
+	echo __('You can go to the <a href="%site%">home page</a> or <a href="%uri%">try again</a>.',
+		array('%site%' => htmlspecialchars(url::site(), ENT_QUOTES, Kohana::CHARSET), '%uri%' => htmlspecialchars(url::site(Router::$current_uri), ENT_QUOTES, Kohana::CHARSET)));
+?>
+			</p>
+		</div>
+	</body>
+</html>
diff --git a/system/views/kohana/template.php b/system/views/kohana/template.php
new file mode 100644
index 0000000..84ddbff
--- /dev/null
+++ b/system/views/kohana/template.php
@@ -0,0 +1,36 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.'); ?>
+<!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" xml:lang="en" lang="en">
+<head>
+
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+	<title><?php echo html::chars(__($title)) ?></title>
+
+	<style type="text/css">
+	html { background: #83c018 url(<?php echo url::base(FALSE) ?>kohana.png) 50% 0 no-repeat; }
+	body { width: 52em; margin: 200px auto 2em; font-size: 76%; font-family: Arial, sans-serif; color: #273907; line-height: 1.5; text-align: center; }
+	h1 { font-size: 3em; font-weight: normal; text-transform: uppercase; color: #fff; }
+	a { color: inherit; }
+	code { font-size: 1.3em; }
+	ul { list-style: none; padding: 2em 0; }
+	ul li { display: inline; padding-right: 1em; text-transform: uppercase; }
+	ul li a { padding: 0.5em 1em; background: #69ad0f; border: 1px solid #569f09; color: #fff; text-decoration: none; }
+	ul li a:hover { background: #569f09; }
+	.box { padding: 2em; background: #98cc2b; border: 1px solid #569f09; }
+	.copyright { font-size: 0.9em; text-transform: uppercase; color: #557d10; }
+	</style>
+
+</head>
+<body>
+
+	<h1><?php echo html::chars(__($title)) ?></h1>
+	<?php echo $content ?>
+
+	<p class="copyright">
+		<?php echo __('Rendered in {execution_time} seconds, using {memory_usage} of memory')?><br />
+		Copyright ©2007–2008 Kohana Team
+	</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/system/views/profiler/profiler.php b/system/views/profiler/profiler.php
new file mode 100644
index 0000000..7b9ae95
--- /dev/null
+++ b/system/views/profiler/profiler.php
@@ -0,0 +1,37 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.'); ?>
+<style type="text/css">
+#kohana-profiler
+{
+	font-family: Monaco, 'Courier New';
+	background-color: #F8FFF8;
+	margin-top: 20px;
+	clear: both;
+	padding: 10px 10px 0;
+	border: 1px solid #E5EFF8;
+	text-align: left;
+}
+#kohana-profiler pre
+{
+	margin: 0;
+	font: inherit;
+}
+#kohana-profiler .kp-meta
+{
+	margin: 0 0 10px;
+	padding: 4px;
+	background: #FFF;
+	border: 1px solid #E5EFF8;
+	color: #A6B0B8;
+	text-align: center;
+}
+<?php echo $styles ?>
+</style>
+<div id="kohana-profiler">
+<?php
+foreach ($profiles as $profile)
+{
+	echo $profile->render();
+}
+?>
+<p class="kp-meta"><?php echo __('Profiler executed in :execution_timess', array(':execution_times' => number_format($execution_time, 3))) ?></p>
+</div>
\ No newline at end of file
diff --git a/system/views/profiler/table.css b/system/views/profiler/table.css
new file mode 100644
index 0000000..41a1c9a
--- /dev/null
+++ b/system/views/profiler/table.css
@@ -0,0 +1,53 @@
+#kohana-profiler .kp-table
+{
+	font-size: 1.0em;
+	color: #4D6171;
+	width: 100%;
+	border-collapse: collapse;
+	border-top: 1px solid #E5EFF8;
+	border-right: 1px solid #E5EFF8;
+	border-left: 1px solid #E5EFF8;
+	margin-bottom: 10px;
+}
+#kohana-profiler .kp-table td
+{
+	background-color: #FFFFFF;
+	border-bottom: 1px solid #E5EFF8;
+	padding: 3px;
+	vertical-align: top;
+}
+#kohana-profiler .kp-table .kp-title td
+{
+	font-weight: bold;
+	background-color: inherit;
+}
+#kohana-profiler .kp-table .kp-altrow td
+{
+	background-color: #F7FBFF;
+}
+#kohana-profiler .kp-table .kp-totalrow td
+{
+	background-color: #FAFAFA;
+	border-top: 1px solid #D2DCE5;
+	font-weight: bold;
+}
+#kohana-profiler .kp-table .kp-column
+{
+	width: 100px;
+	border-left: 1px solid #E5EFF8;
+	text-align: center;
+}
+#kohana-profiler .kp-table .kp-data, #kohana-profiler .kp-table .kp-name
+{
+	background-color: #FAFAFB;
+	vertical-align: top;
+}
+#kohana-profiler .kp-table .kp-name
+{
+	width: 200px;
+	border-right: 1px solid #E5EFF8;
+}
+#kohana-profiler .kp-table .kp-altrow .kp-data, #kohana-profiler .kp-table .kp-altrow .kp-name
+{
+	background-color: #F6F8FB;
+}
\ No newline at end of file
diff --git a/system/views/profiler/table.php b/system/views/profiler/table.php
new file mode 100644
index 0000000..7cdf79d
--- /dev/null
+++ b/system/views/profiler/table.php
@@ -0,0 +1,24 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.'); ?>
+<table class="kp-table">
+<?php
+foreach ($rows as $row):
+
+$class = empty($row['class']) ? '' : ' class="'.$row['class'].'"';
+$style = empty($row['style']) ? '' : ' style="'.$row['style'].'"';
+?>
+	<tr<?php echo $class; echo $style; ?>>
+		<?php
+		foreach ($columns as $index => $column)
+		{
+			$class = empty($column['class']) ? '' : ' class="'.$column['class'].'"';
+			$style = empty($column['style']) ? '' : ' style="'.$column['style'].'"';
+			$value = $row['data'][$index];
+			$value = (is_array($value) OR is_object($value)) ? '<pre>'.htmlspecialchars(print_r($value, TRUE), ENT_QUOTES, Kohana::CHARSET).'</pre>' : htmlspecialchars($value, ENT_QUOTES, Kohana::CHARSET);
+			echo '<td' . $style . $class . '>' . wordwrap($value, 100, '<br />', true) . '</td>';
+		}
+		?>
+	</tr>
+<?php
+endforeach;
+?>
+</table>
diff --git a/themes/admin_wind/css/fix-ie.css b/themes/admin_wind/css/fix-ie.css
new file mode 100644
index 0000000..4546f9f
--- /dev/null
+++ b/themes/admin_wind/css/fix-ie.css
@@ -0,0 +1,18 @@
+/**
+ * Fix display in IE 6 and 7
+ */
+
+.g-unavailable {
+  filter: alpha(opacity=40);
+}
+
+.g-unavailable:hover {
+  filter: alpha(opacity=100);
+}
+
+tr.g-error td,
+tr.g-info td,
+tr.g-success td,
+tr.g-warning td {
+  background: none !important;
+}
diff --git a/themes/admin_wind/css/screen-rtl.css b/themes/admin_wind/css/screen-rtl.css
new file mode 100644
index 0000000..79afabb
--- /dev/null
+++ b/themes/admin_wind/css/screen-rtl.css
@@ -0,0 +1,400 @@
+/**
+ * Gallery 3 Admin Wind Theme Right-to-Left Screen Styles
+ */
+
+.rtl {
+  direction: rtl;
+}
+
+#g-header,
+#g-content,
+#g-sidebar,
+#g-footer,
+caption,
+th,
+#g-dialog,
+.g-context-menu li a,
+.g-message-box li,
+#g-site-status li {
+  text-align: right;
+}
+
+.g-text-right {
+  text-align: left;
+}
+
+/* Lists ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-text li,
+.g-text li {
+  margin-left: 0;
+  margin-right: 1em;
+}
+
+/* Messages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-error,
+.g-info,
+.g-success,
+.g-warning,
+#g-add-photos-status .g-success,
+#g-add-photos-status .g-error {
+  background-position: center right;
+  padding-right: 30px !important;
+}
+
+form li.g-error,
+form li.g-info,
+form li.g-success,
+form li.g-warning {
+  padding-right: 0 !important;
+}
+
+.g-left,
+.g-inline li,
+#g-content #g-album-grid .g-item,
+.sf-menu li,
+.g-breadcrumbs li,
+.g-paginator li,
+.g-buttonset li,
+.ui-icon-left .ui-icon,
+.g-short-form li,
+form ul ul li,
+input[type="submit"],
+input[type="reset"],
+input.checkbox,
+input[type=checkbox],
+input.radio,
+input[type=radio] {
+  float: right;
+}
+
+.g-right,
+.ui-icon-right .ui-icon {
+  float: left;
+}
+
+.g-inline li {
+  margin-right: 1em;
+}
+
+.g-inline li.g-first {
+  margin-right: 0;
+}
+
+.g-breadcrumbs li {
+  background: transparent url('../images/ico-separator-rtl.gif') no-repeat scroll right center;
+  padding: 1em 18px 1em 8px;
+}
+
+.g-breadcrumbs .g-first {
+  background: none;
+  padding-right: 0;
+}
+
+input.checkbox,
+input[type="checkbox"],
+input.radio,
+input[type="radio"] {
+  margin-right: 0;
+  margin-left: .4em;
+}
+
+#g-add-comment {
+  right: inherit;
+  left: 0;
+}
+
+.ui-icon-left .ui-icon {
+  margin-left: .2em;
+}
+
+.ui-icon-right .ui-icon {
+  margin-right: .2em;
+}
+
+.g-group h4 {
+  padding: .5em .5em .5em 0;
+}
+
+.g-group .g-user {
+  padding: .2em .5em 0 0;
+}
+
+/* RTL Corner radius ~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-buttonset .ui-corner-tl {
+  -moz-border-radius-topleft: 0;
+  -webkit-border-top-left-radius: 0;
+  border-top-left-radius: 0;
+  -moz-border-radius-topright: 5px !important;
+  -webkit-border-top-right-radius: 5px !important;
+  border-top-right-radius: 5px !important;
+}
+
+.g-buttonset .ui-corner-tr {
+  -moz-border-radius-topright: 0;
+  -webkit-border-top-right-radius: 0;
+  border-top-right-radius: 0;
+  -moz-border-radius-topleft: 5px !important;
+  -webkit-border-top-left-radius: 5px !important;
+  border-top-left-radius: 5px !important;
+}
+
+.g-buttonset .ui-corner-bl {
+  -moz-border-radius-bottomleft: 0;
+  -webkit-border-bottom-left-radius: 0;
+  border-bottom-left-radius: 0;
+  -moz-border-radius-bottomright: 5px !important;
+  -webkit-border-bottom-right-radius: 5px !important;
+  border-bottom-right-radius: 5px !important;
+}
+
+.g-buttonset .ui-corner-br {
+  -moz-border-radius-bottomright: 0;
+  -webkit-border-bottom-right-radius: 0;
+  border-bottom-right-radius: 0;
+  -moz-border-radius-bottomleft: 5px !important;
+  -webkit-border-bottom-left-radius: 5px !important;
+  border-bottom-left-radius: 5px !important;
+}
+
+.g-buttonset .ui-corner-right,
+.ui-progressbar .ui-corner-right {
+  -moz-border-radius-topright: 0;
+  -webkit-border-top-right-radius: 0;
+  border-top-right-radius: 0;
+  -moz-border-radius-topleft: 5px !important;
+  -webkit-border-top-left-radius: 5px !important;
+  border-top-left-radius: 5px !important;
+  -moz-border-radius-bottomright: 0;
+  -webkit-border-bottom-right-radius: 0;
+  border-bottom-right-radius: 0;
+  -moz-border-radius-bottomleft: 5px !important;
+  -webkit-border-bottom-left-radius: 5px !important;
+  border-bottom-left-radius: 5px !important;
+}
+
+.g-buttonset .ui-corner-left,
+.ui-progressbar .ui-corner-left {
+  -moz-border-radius-topleft: 0;
+  -webkit-border-top-left-radius: 0;
+  border-top-left-radius: 0;
+  -moz-border-radius-topright: 5px !important;
+  -webkit-border-top-right-radius: 5px !important;
+  border-top-right-radius: 5px !important;
+  -moz-border-radius-bottomleft: 0;
+  -webkit-border-bottom-left-radius: 0;
+  border-bottom-left-radius: 0;
+  -moz-border-radius-bottomright: 5px !important;
+  -webkit-border-bottom-right-radius: 5px !important;
+  border-bottom-right-radius: 5px !important;
+}
+
+/* RTL Superfish ~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.sf-menu a {
+  border-left: none;
+  border-right:1px solid #fff;
+}
+
+.sf-menu a.sf-with-ul {
+  padding-left: 2.25em;
+  padding-right: 1em;
+}
+
+.sf-sub-indicator {
+  left: .75em !important;
+  right: auto;
+  background: url('../../../lib/superfish/images/arrows-ffffff-rtl.png') no-repeat -10px -100px;
+}
+
+a > .sf-sub-indicator {
+  top: .8em;
+  background-position: -10px -100px;
+}
+
+a:focus > .sf-sub-indicator,
+a:hover > .sf-sub-indicator,
+a:active > .sf-sub-indicator,
+li:hover > a > .sf-sub-indicator,
+li.sfHover > a > .sf-sub-indicator {
+  background-position: 0 -100px;
+}
+
+.sf-menu ul .sf-sub-indicator {
+  background-position: 0 0;
+}
+
+.sf-menu ul a > .sf-sub-indicator {
+  background-position: -10px 0;
+}
+
+.sf-menu ul a:focus > .sf-sub-indicator,
+.sf-menu ul a:hover > .sf-sub-indicator,
+.sf-menu ul a:active > .sf-sub-indicator,
+.sf-menu ul li:hover > a > .sf-sub-indicator,
+.sf-menu ul li.sfHover > a > .sf-sub-indicator {
+  background-position: 0 0;
+}
+
+.sf-menu li:hover ul,
+.sf-menu li.sfHover ul {
+  right: 0;
+  left: auto;
+}
+
+ul.sf-menu li li:hover ul,
+ul.sf-menu li li.sfHover ul {
+  right: 12em;
+  left: auto;
+}
+ul.sf-menu li li li:hover ul,
+ul.sf-menu li li li.sfHover ul {
+  right: 12em;
+  left: auto;
+}
+
+.sf-shadow ul {
+  background:	url('../../../lib/superfish/images/shadow.png') no-repeat bottom left;
+  padding: 0 0 9px 8px;
+  border-top-right-radius: 0;
+  border-bottom-left-radius: 0;
+  -moz-border-radius-topright: 0;
+  -moz-border-radius-bottomleft: 0;
+  -webkit-border-top-right-radius: 0;
+  -webkit-border-bottom-left-radius: 0;
+  -moz-border-radius-topleft: 17px;
+  -moz-border-radius-bottomright: 17px;
+  -webkit-border-top-left-radius: 17px;
+  -webkit-border-bottom-right-radius: 17px;
+  border-top-left-radius: 17px;
+  border-bottom-right-radius: 17px;
+}
+
+/* RTL ThemeRoller ~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.ui-dialog .ui-dialog-titlebar {
+  padding: 0.5em 1em 0.3em 0.3em;
+}
+
+.ui-dialog .ui-dialog-title {
+  float: right;
+}
+
+.ui-dialog .ui-dialog-titlebar-close {
+  left: 0.3em;
+  right: auto;
+}
+
+.ui-tabs .ui-tabs-nav li {
+  float: right;	
+}
+
+#g-content #g-album-grid .g-item,
+#g-site-theme,
+#g-admin-theme,
+.g-selected img,
+.g-available .g-block img,
+#g-content #g-photo-stream .g-item,
+li.g-group,
+#g-server-add-admin {
+  float: right;
+}
+
+#g-site-theme {
+  margin-right: 0;
+  margin-left: 1em;
+}
+
+#g-admin-graphics .g-available .g-block {
+  float: right;
+  margin-left: 1em;
+  margin-right: 0em;
+}
+
+#g-site-admin-menu {
+  left: auto;
+  right: 150px;
+}
+
+#g-header #g-login-menu {
+  float: left;
+}
+
+#g-header #g-login-menu li {
+  margin-left: 0;
+  padding-left: 0;
+  padding-right: 1.2em;
+}
+
+#g-sidebar .g-block-content {
+  padding-left: 0em;
+  padding-right: 1em;
+}
+
+.g-selected img,
+.g-available .g-block img {
+  margin: 0 0 1em 1em;
+}
+
+.g-button {
+  margin: 0 0 0 4px;
+}
+
+/* RTL paginator ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-paginator .g-info {
+  width: 35%;
+}
+
+.g-paginator .g-text-right {
+  margin-left: 0;
+}
+
+.g-paginator .ui-icon-seek-end {
+  background-position: -80px -160px;
+}
+
+.g-paginator .ui-icon-seek-next {
+  background-position: -48px -160px;
+}
+
+.g-paginator .ui-icon-seek-prev {
+  background-position: -32px -160px;
+}
+
+.g-paginator .ui-icon-seek-first {
+  background-position: -64px -160px;
+}
+
+#g-header #g-login-menu,
+#g-header #g-quick-search-form {
+  clear: left;
+  float: left;
+}
+
+#g-header #g-login-menu li {
+  margin-left: 0;
+  padding-left: 0;
+  padding-right: 1.2em;
+}
+
+#g-site-menu {
+  left: auto;
+  right: 240px;
+}
+
+#g-view-menu #g-slideshow-link {
+  background-image: url('../images/ico-view-slideshow-rtl.png');
+}
+
+#g-sidebar .g-block-content {
+  padding-right: 1em;
+  padding-left: 0;
+}
+
+#g-footer #g-credits li {
+  padding-left: 1.2em !important;
+  padding-right: 0;
+}
diff --git a/themes/admin_wind/css/screen.css b/themes/admin_wind/css/screen.css
new file mode 100644
index 0000000..5894238
--- /dev/null
+++ b/themes/admin_wind/css/screen.css
@@ -0,0 +1,1058 @@
+/**
+ * Gallery 3 Admin Wind Theme Screen Styles
+ *
+ * @requires YUI reset, font, grids CSS
+ *
+ * Sheet organization:
+ *   1)  Basic HTML elements
+ *   2)  Reusable content blocks
+ *   3)  Page layout containers
+ *   4)  Content blocks in specific layout containers
+ *   5)  States and interactions
+ *   6)  Positioning and order
+ *   7)  Navigation and menus
+ *   8)  jQuery and jQuery UI
+ *
+ * @todo Review g-buttonset-vertical
+ */
+
+/** *******************************************************************
+ * 1) Basic HTML elements
+ **********************************************************************/
+
+body, html {
+  background-color: #ccc;
+  font-family: 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+}
+
+p,
+#g-content ul,
+#g-content ol,
+#g-content dl {
+  margin-bottom: 1em;
+}
+
+em {
+  font-style: oblique;
+}
+
+h1, h2, h3, h4, h5, strong, th {
+  font-weight: bold;
+}
+
+h1 {
+  font-size: 1.7em;
+}
+
+#g-dialog h1 {
+  font-size: 1.1em;
+}
+
+h2 {
+  font-size: 1.4em;
+}
+
+#g-sidebar .g-block h2 {
+  font-size: 1.2em;
+}
+
+#g-sidebar .g-block li {
+  margin-bottom: .6em;
+}
+
+h3 {
+  font-size: 1.2em;
+}
+
+/* Links ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+a,
+.g-menu a,
+#g-dialog a,
+.g-button,
+.g-button:hover,
+.g-button:active,
+a.ui-state-hover,
+input.ui-state-hover,
+button.ui-state-hover {
+  color: #5382BF !important;
+  text-decoration: none;
+  -moz-outline-style: none;
+}
+
+a:hover,
+#g-dialog a:hover {
+  text-decoration: underline;
+}
+
+.g-menu a:hover {
+  text-decoration: none;
+}
+
+/* Lists ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+ul.g-text li,
+.g-text ul li {
+  list-style-type: disc;
+}
+
+ol.g-text li,
+.g-text ol li {
+  list-style-type: decimal;
+}
+
+.g-text li,
+.g-text li {
+  margin-left: 1em;
+}
+
+/* Forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+form {
+  margin: 0;
+}
+
+fieldset {
+  border: 1px solid #ccc;
+  padding: 0 1em .8em 1em;
+}
+
+#g-banner fieldset,
+#g-sidebar fieldset {
+  border: none;
+  padding: 0;
+}
+
+legend {
+  font-weight: bold;
+  margin: 0;
+  padding: 0 .2em;
+}
+
+#g-banner legend,
+#g-sidebar legend,
+input[type="hidden"] {
+  display: none;
+}
+
+input.textbox,
+input[type="text"],
+input[type="password"],
+textarea {
+  border: 1px solid #e8e8e8;
+  border-top-color: #ccc;
+  border-left-color: #ccc;
+  clear: both;
+  color: #333;
+  width: 50%;
+}
+
+textarea {
+  height: 12em;
+  width: 97%;
+}
+
+input:focus,
+input.textbox:focus,
+input[type=text]:focus,
+textarea:focus,
+option:focus {
+  background-color: #ffc;
+  color: #000;
+}
+
+input.checkbox,
+input[type=checkbox],
+input.radio,
+input[type=radio] {
+  float: left;
+  margin-right: .4em;
+}
+
+/* Form layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+form li {
+  margin: 0;
+  padding: 0 0 .2em 0;
+}
+
+form ul {
+  margin-top: 0;
+}
+
+form ul ul {
+  clear: both;
+}
+
+form ul ul li {
+  float: left;
+}
+
+input,
+select,
+textarea {
+  display: block;
+  clear: both;
+  padding: .2em;
+}
+
+input[type="submit"],
+input[type="reset"] {
+  display: inline;
+  clear: none;
+  float: left;
+}
+
+/* Forms in dialogs and panels ~~~~~~~~~ */
+
+#g-dialog ul li {
+  padding-bottom: .8em;
+}
+
+#g-dialog fieldset,
+#g-panel fieldset {
+  border: none;
+  padding: 0;
+}
+
+#g-panel legend {
+  display: none;
+}
+
+input[readonly] {
+  background-color: #F4F4FC;
+}
+
+#g-dialog input.textbox,
+#g-dialog input[type=text],
+#g-dialog input[type=password],
+#g-dialog textarea {
+  width: 97%;
+}
+
+/* Short forms ~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-short-form legend,
+.g-short-form label {
+  display: none;
+}
+
+.g-short-form fieldset {
+  border: none;
+  padding: 0;
+}
+
+.g-short-form li {
+  float: left;
+  margin: 0 !important;
+  padding: .4em 0;
+}
+
+.g-short-form .textbox,
+.g-short-form input[type=text] {
+  color: #666;
+  padding: .3em .6em;
+  width: 100%;
+}
+
+.g-short-form .textbox.g-error {
+  border: 1px solid #f00;
+  color: #f00;
+  padding-left: 24px;
+}
+
+.g-short-form .g-cancel {
+  display: block;
+  margin: .3em .8em;
+}
+
+#g-sidebar .g-short-form li {
+  padding-left: 0;
+  padding-right: 0;
+}
+
+fieldset {
+  margin-bottom: 1em;
+}
+
+#g-content form ul li {
+  padding: .4em 0;
+}
+
+#g-dialog form {
+  width: 270px;
+}
+
+#g-dialog fieldset {
+  margin-bottom: 0;
+}
+
+/* Tables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+table {
+  width: 100%;
+}
+
+#g-content table {
+  margin: .6em 0 2em 0;
+}
+
+caption,
+th {
+  text-align: left;
+}
+
+th,
+td {
+  border: none;
+  border-bottom: 1px solid #ccc;
+  padding: .5em;
+  vertical-align: middle;
+}
+
+th {
+  vertical-align: bottom;
+  white-space: nowrap;
+}
+
+/* Text ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-text-small {
+  font-size: .8em;
+}
+
+.g-text-big {
+  font-size: 1.2em;
+}
+
+.g-text-right {
+  text-align: right;
+}
+
+/** *******************************************************************
+ * 2) Reusable content blocks
+ *********************************************************************/
+
+.g-block,
+#g-content #g-admin-dashboard .g-block {
+  background-color: #fff;
+  border: 1px solid #ccc;
+  padding: 1em;
+}
+
+.g-block h2 {
+  background-color: #e8e8e8;
+  padding: .3em .8em;
+}
+
+.g-block-content {
+  margin-top: 1em;
+}
+
+#g-content .g-block {
+  border: none;
+  padding: 0;
+}
+
+#g-content .g-selected,
+#g-content .g-available .g-block {
+  border: 1px solid #ccc;
+  padding: .8em;
+}
+
+.g-selected img,
+.g-available .g-block img {
+  float: left;
+  margin: 0 1em 1em 0;
+}
+
+.g-selected {
+  background: #e8e8e8;
+}
+
+.g-available .g-installed-toolkit:hover {
+  cursor: pointer;
+  background: #eee;
+}
+
+.g-available .g-button {
+  width: 96%;
+}
+
+.g-selected .g-button {
+  display: none;
+}
+
+.g-unavailable {
+  border-color: #999;
+  color: black;
+  opacity: .6;
+}
+
+.g-info td {
+  background-color: transparent;
+  background-image: none;
+}
+
+.g-success td {
+  background-color: transparent;
+  background-image: none;
+}
+
+.g-error td {
+  background-color: #f6cbca;
+  background-image: none;
+}
+
+.g-warning td {
+  background-color: #fcf9ce;
+  background-image: none;
+}
+
+.g-module-status.g-info,
+#g-log-entries .g-info,
+.g-module-status.g-success,
+#g-log-entries .g-success {
+  background-color: #fff;
+}
+
+/*** ******************************************************************
+ * 3) Page layout containers
+ *********************************************************************/
+
+/* Dimension and scale ~~~~~~~~~~~~~~~~~~~ */
+
+.g-one-quarter {
+  width: 25%;
+}
+
+.g-one-third {
+  width: 33%;
+}
+
+.g-one-half {
+  width: 50%;
+}
+
+.g-two-thirds {
+  width: 66%;
+}
+
+.g-three-quarters {
+  width: 75%;
+}
+
+.g-whole {
+  width: 100%;
+}
+
+/* Header  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-header #g-login-menu {
+  margin-top: 1em;
+  float: right;
+}
+
+/* View container ~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-view {
+  background-color: #fff;
+  border: 1px solid #ccc;
+  border-bottom: none;
+  min-width: 974px !important;
+}
+
+/* Layout containers ~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-header {
+  background-color: #e8e8e8;
+  border-bottom: 1px solid #ccc;
+  font-size: .8em;
+  margin-bottom: 20px;
+  padding: 0 20px;
+  position: relative;
+}
+
+#g-content {
+  font-size: 1.1em;
+  padding: 0 2em;
+  width: 96%;
+}
+
+#g-sidebar {
+  background-color: #fff;
+  font-size: .9em;
+  padding: 0 20px;
+  width: 220px;
+}
+
+#g-footer {
+  background-color: #e8e8e8;
+  border-top: 1px solid #ccc;
+  font-size: .8em;
+  margin-top: 20px;
+  padding: 10px 20px;
+}
+
+/** *******************************************************************
+ * 4) Content blocks in specific layout containers
+ *********************************************************************/
+
+/* Header  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-header #g-logo {
+  background: transparent url('../../../lib/images/logo.png') no-repeat 0 .5em;
+  color: #A5A5A5 !important;
+  display: block;
+  height: 65px;
+  padding-top: 5px;
+  width: 105px;
+}
+
+#g-header #g-logo:hover {
+  color: #f60 !important;
+  text-decoration: none;
+}
+
+#g-content .g-block h2 {
+  background-color: transparent;
+  padding-left: 0;
+}
+
+#g-sidebar .g-block-content {
+  padding-left: 1em;
+}
+
+.g-block .ui-dialog-titlebar {
+  margin: -1em -1em 0;
+}
+
+#g-sidebar .g-block h2 {
+  background: none;
+}
+
+/* Photo stream ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-photo-stream {
+  background-color: #e8e8e8;
+}
+
+#g-photo-stream .g-block-content ul {
+  border-right: 1px solid #e8e8e8;
+  height: 135px;
+  overflow: auto;
+  overflow: -moz-scrollbars-horizontal; /* for FF */
+  overflow-x: scroll; /* scroll horizontal */
+  overflow-y: hidden; /* Hide vertical*/
+}
+
+#g-content #g-photo-stream .g-item {
+  background-color: #fff;
+  border: 1px solid #e8e8e8;
+  border-right-color: #ccc;
+  border-bottom-color: #ccc;
+  float: left;
+  height: 90px;
+  overflow: hidden;
+  text-align: center;
+  width: 90px;
+}
+
+#g-content .g-item {
+  background-color: #fff;
+  border: 1px solid #e8e8e8;
+  border-right-color: #ccc;
+  border-bottom-color: #ccc;
+  height: 90px;
+  padding: 14px 8px;
+  text-align: center;
+  width: 90px;
+}
+
+/* Graphics settings ~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-admin-graphics .g-available .g-block {
+  clear: none;
+  float: left;
+  margin-right: 1em;
+  width: 30%;
+}
+
+/* Appearance settings ~~~~~~~~~~~~~~~~~~~ */
+
+#g-site-theme,
+#g-admin-theme {
+  float: left;
+  width: 48%;
+}
+
+#g-site-theme {
+  margin-right: 1em;
+}
+
+/* Block admin  ~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-admin-blocks-list {
+  float: left;
+  margin: 0 2em 2em 0;
+  width: 30%;
+}
+
+.g-admin-blocks-list div:last-child {
+  border: .1em solid;
+  height: 100%;
+}
+
+.g-admin-blocks-list ul {
+  height: 98%;
+  margin: .1em .1em;
+  padding: .1em;
+}
+
+.g-admin-blocks-list ul li.g-draggable {
+  background-color: #e8e8e8;
+  margin: .5em;
+  padding: .3em .8em;
+}
+
+/* In-line editing  ~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-in-place-edit-message {
+  background-color: #FFF;
+}
+
+/* Language options  ~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-share-translations-form fieldset {
+  border: 0px;
+  margin: 0px;
+  padding: 0px;
+}
+
+#g-share-translations-form fieldset legend {
+  display: none;
+}
+
+/** *******************************************************************
+ *  5) States and interactions
+ **********************************************************************/
+
+.g-active,
+.g-enabled,
+.g-available,
+.g-selected,
+.g-highlight {
+  font-weight: bold;
+}
+
+.g-inactive,
+.g-disabled,
+.g-unavailable,
+.g-uneditable,
+.g-locked,
+.g-deselected,
+.g-understate {
+  color: #ccc;
+  font-weight: normal;
+}
+
+.g-editable {
+  padding: .2em .3em;
+}
+
+.g-editable:hover {
+  background-color: #ffc;
+  cursor: text;
+}
+
+.g-error,
+.g-info,
+.g-success,
+.g-warning {
+  padding-left: 30px;
+}
+
+form li.g-error,
+form li.g-info,
+form li.g-success,
+form li.g-warning {
+  background-image: none;
+  padding: .3em .8em .3em 0;
+}
+
+.g-short-form li.g-error {
+  padding: .3em 0;
+}
+
+form.g-error input[type="text"],
+li.g-error input[type="text"],
+form.g-error input[type="password"],
+li.g-error input[type="password"],
+form.g-error input[type="checkbox"],
+li.g-error input[type="checkbox"],
+form.g-error input[type="radio"],
+li.g-error input[type="radio"],
+form.g-error textarea,
+li.g-error textarea,
+form.g-error select,
+li.g-error select {
+  border: 2px solid #f00;
+  margin-bottom: .2em;
+}
+
+.g-error,
+.g-denied,
+tr.g-error td.g-error,
+#g-add-photos-status .g-error {
+  background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%;
+  color: #f00;
+}
+
+.g-info {
+  background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%;
+}
+
+.g-success,
+.g-allowed,
+#g-add-photos-status .g-success {
+  background: #d9efc2 url('../images/ico-success.png') no-repeat .4em 50%;
+}
+
+tr.g-success {
+  background-image: none;
+}
+
+tr.g-success td.g-success {
+  background-image: url('../images/ico-success.png');
+}
+
+.g-warning,
+tr.g-warning td.g-warning {
+  background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%;
+}
+
+form .g-error {
+  background-color: #fff;
+  padding-left: 20px;
+}
+
+.g-open {
+}
+
+.g-closed {
+}
+
+.g-installed {
+  background-color: #eeeeee;
+}
+
+.g-default {
+  background-color: #c5dbec;
+  font-weight: bold;
+}
+
+.g-draggable {
+  cursor: move;
+}
+
+.g-draggable:hover {
+  border: 1px dashed #000;
+}
+
+.ui-sortable .g-target,
+.ui-state-highlight {
+  background-color: #fcf9ce;
+  border: 2px dotted #999;
+  height: 2em;
+  margin: 1em 0;
+}
+
+/* Ajax loading indicator ~~~~~~~~~~~~~~~~ */
+
+.g-loading-large,
+.g-dialog-loading-large {
+  background: #e8e8e8 url('../images/loading-large.gif') no-repeat center center !important;
+}
+
+.g-loading-small {
+  background: #e8e8e8 url('../images/loading-small.gif') no-repeat center center !important;
+}
+
+/** *******************************************************************
+ *  6) Positioning and order
+ **********************************************************************/
+
+.g-left {
+  clear: none;
+  float: left;
+}
+
+.g-right {
+  clear: none;
+  float: right;
+}
+
+.g-first {
+}
+
+.g-last {
+}
+
+.g-even {
+  background-color: #fff;
+}
+
+.g-odd {
+  background-color: #eee;
+}
+
+/** *******************************************************************
+ *  7) Navigation and menus
+ *********************************************************************/
+
+/* Site Menu  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-site-admin-menu {
+  bottom: 0;
+  font-size: 1.2em;
+  left: 140px;
+  position: absolute;
+}
+
+#g-site-admin-menu ul {
+  margin-bottom: 0;
+}
+
+/** *******************************************************************
+ *  8) jQuery and jQuery UI
+ *********************************************************************/
+
+/* Generic block container ~~~~~~~~~~~~~~~ */
+
+.g-block {
+  clear: both;
+  margin-bottom: 2.5em;
+}
+
+.g-block-content {
+}
+
+/* Buttons ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-button {
+  display: inline-block;
+  margin: 0 4px 0 0;
+  padding: .2em .4em;
+}
+
+.g-button,
+.g-button:hover,
+.g-button:active {
+  cursor: pointer !important;
+  outline: 0;
+  text-decoration: none;
+  -moz-outline-style: none;
+}
+
+button {
+  padding: 2px 4px 2px 4px;
+}
+
+/* jQuery UI ThemeRoller buttons ~~~~~~~~~ */
+
+.g-buttonset {
+  padding-left: 1px;
+}
+
+.g-buttonset li {
+  float: left;
+}
+
+.g-buttonset .g-button {
+  margin: 0;
+}
+
+.ui-icon-left .ui-icon {
+  float: left;
+  margin-right: .2em;
+}
+
+.ui-icon-right .ui-icon {
+  float: right;
+  margin-left: .2em;
+}
+
+/* Rotate icon, ThemeRoller only provides one of these */
+
+.ui-icon-rotate-ccw {
+  background-position: -192px -64px;
+}
+
+.ui-icon-rotate-cw {
+  background-position: -208px -64px;
+}
+
+.g-progress-bar {
+  height: 1em;
+  width: 100%;
+  margin: .5em 0;
+  display: inline-block;
+}
+
+/* Status and validation messages ~~~~ */
+
+.g-message-block {
+  background-position: .4em .3em;
+  border: 1px solid #ccc;
+  padding: 0;
+  margin-bottom: 1em;
+}
+
+#g-action-status {
+}
+
+#g-action-status li,
+p#g-action-status,
+div#g-action-status {
+  padding: .3em .3em .3em 30px;
+}
+
+#g-site-status li {
+  border-bottom: 1px solid #ccc;
+  padding: .3em .3em .3em 30px;
+}
+
+.g-module-status {
+  clear: both;
+  margin-bottom: 1em;
+}
+
+.g-message {
+  background-position: 0 50%;
+}
+
+/* Breadcrumbs ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-breadcrumbs {
+  clear: both;
+  padding: 0 20px;
+}
+
+.g-breadcrumbs li {
+  background: transparent url('../images/ico-separator.gif') no-repeat scroll left center;
+  float: left;
+  padding: 1em 8px 1em 18px;
+}
+
+.g-breadcrumbs .g-first {
+  background: none;
+  padding-left: 0;
+}
+
+.g-breadcrumbs li a,
+.g-breadcrumbs li span {
+  display: block;
+}
+
+#g-dialog ul.g-breadcrumbs {
+  margin-left: 0;
+  padding-left: 0;
+}
+
+/* Pagination ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-paginator {
+  padding: .2em 0;
+  width: 100%;
+}
+
+.g-paginator li {
+  float: left;
+  width: 30%;
+}
+
+.g-paginator .g-info {
+  background: none;
+  padding: .2em 0;
+  text-align: center;
+  width: 40%;
+}
+
+/* Dialogs and panels ~~~~~~~~~~~~~~~~~~ */
+
+#g-dialog {
+  text-align: left;
+}
+
+#g-dialog legend {
+  display: none;
+}
+
+#g-dialog .g-cancel {
+  margin: .4em 1em;
+}
+
+#g-panel {
+  display: none;
+  padding: 1em;
+}
+
+/* Inline layout  ~~~~~~~~~~ */
+
+.g-inline li {
+  float: left;
+  margin-left: 1.8em;
+  padding-left: 0 !important;
+}
+
+.g-inline li.g-first {
+  margin-left: 0;
+}
+
+/* Superfish menu overrides ~~~~~~~~~~~~~~ */
+
+.sf-menu ul {
+  width: 12em;
+}
+
+ul.sf-menu li li:hover ul,
+ul.sf-menu li li.sfHover ul {
+  left: 12em;
+}
+
+ul.sf-menu li li li:hover ul,
+ul.sf-menu li li li.sfHover ul {
+  left: 12em;
+}
+
+
+.sf-menu li li,
+.sf-menu li li ul li {
+  background-color: #bdd2ff;
+}
+
+.sf-menu li:hover {
+  background-color: #dfe9ff;
+}
+
+/* jQuery UI Dialog ~~~~~~~~~~~~~~~~~~~~~~ */
+
+.ui-widget-overlay {
+  background: #000;
+  opacity: .7;
+}
+
+#g-admin-dashboard .ui-state-highlight,
+#g-sidebar .ui-state-highlight {
+  height: 2em;
+  margin-bottom: 1em;
+}
+
+.g-buttonset-vertical a {
+  width: 8em !important;
+}
+
+#g-admin-dashboard .ui-dialog-titlebar,
+#g-admin-dashboard-sidebar .ui-dialog-titlebar {
+  padding: .2em .4em;
+}
diff --git a/themes/admin_wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png b/themes/admin_wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 0000000..5b5dab2
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png b/themes/admin_wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png
new file mode 100644
index 0000000..47acaad
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png b/themes/admin_wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png
new file mode 100644
index 0000000..9fb564f
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png b/themes/admin_wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png
new file mode 100644
index 0000000..0149515
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png b/themes/admin_wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 0000000..4443fdc
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png b/themes/admin_wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
new file mode 100644
index 0000000..0cdbda3
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png b/themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
new file mode 100644
index 0000000..4f3faf8
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
new file mode 100644
index 0000000..38c3833
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-icons_217bc0_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_217bc0_256x240.png
new file mode 100644
index 0000000..7719d48
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-icons_217bc0_256x240.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-icons_2e83ff_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_2e83ff_256x240.png
new file mode 100644
index 0000000..d9897d2
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-icons_2e83ff_256x240.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-icons_469bdd_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_469bdd_256x240.png
new file mode 100644
index 0000000..d816185
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-icons_469bdd_256x240.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-icons_6da8d5_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_6da8d5_256x240.png
new file mode 100644
index 0000000..b3c7d66
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-icons_6da8d5_256x240.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 0000000..2db88b7
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png
new file mode 100644
index 0000000..2c8aac4
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png differ
diff --git a/themes/admin_wind/css/themeroller/images/ui-icons_f9bd01_256x240.png b/themes/admin_wind/css/themeroller/images/ui-icons_f9bd01_256x240.png
new file mode 100644
index 0000000..e81603f
Binary files /dev/null and b/themes/admin_wind/css/themeroller/images/ui-icons_f9bd01_256x240.png differ
diff --git a/themes/admin_wind/css/themeroller/ui.base.css b/themes/admin_wind/css/themeroller/ui.base.css
new file mode 100644
index 0000000..1a1810c
--- /dev/null
+++ b/themes/admin_wind/css/themeroller/ui.base.css
@@ -0,0 +1,7 @@
+@import "ui.core.css";
+@import "ui.theme.css";
+@import "ui.datepicker.css";
+@import "ui.dialog.css";
+@import "ui.progressbar.css";
+@import "ui.resizable.css";
+@import "ui.tabs.css";
diff --git a/themes/admin_wind/css/themeroller/ui.core.css b/themes/admin_wind/css/themeroller/ui.core.css
new file mode 100644
index 0000000..d832ad7
--- /dev/null
+++ b/themes/admin_wind/css/themeroller/ui.core.css
@@ -0,0 +1,37 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+*/
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
\ No newline at end of file
diff --git a/themes/admin_wind/css/themeroller/ui.datepicker.css b/themes/admin_wind/css/themeroller/ui.datepicker.css
new file mode 100644
index 0000000..92986c9
--- /dev/null
+++ b/themes/admin_wind/css/themeroller/ui.datepicker.css
@@ -0,0 +1,62 @@
+/* Datepicker
+----------------------------------*/
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month, 
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:left; width:100%; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+    display: none; /*sorry for IE5*/
+    display/**/: block; /*sorry for IE5*/
+    position: absolute; /*must have*/
+    z-index: -1; /*must have*/
+    filter: mask(); /*must have*/
+    top: -4px; /*must have*/
+    left: -4px; /*must have*/
+    width: 200px; /*must have*/
+    height: 200px; /*must have*/
+}
\ No newline at end of file
diff --git a/themes/admin_wind/css/themeroller/ui.dialog.css b/themes/admin_wind/css/themeroller/ui.dialog.css
new file mode 100644
index 0000000..f10f409
--- /dev/null
+++ b/themes/admin_wind/css/themeroller/ui.dialog.css
@@ -0,0 +1,13 @@
+/* Dialog
+----------------------------------*/
+.ui-dialog { position: relative; padding: .2em; width: 300px; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative;  }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
\ No newline at end of file
diff --git a/themes/admin_wind/css/themeroller/ui.progressbar.css b/themes/admin_wind/css/themeroller/ui.progressbar.css
new file mode 100644
index 0000000..bc0939e
--- /dev/null
+++ b/themes/admin_wind/css/themeroller/ui.progressbar.css
@@ -0,0 +1,4 @@
+/* Progressbar
+----------------------------------*/
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff --git a/themes/admin_wind/css/themeroller/ui.resizable.css b/themes/admin_wind/css/themeroller/ui.resizable.css
new file mode 100644
index 0000000..44efeb2
--- /dev/null
+++ b/themes/admin_wind/css/themeroller/ui.resizable.css
@@ -0,0 +1,13 @@
+/* Resizable
+----------------------------------*/
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
\ No newline at end of file
diff --git a/themes/admin_wind/css/themeroller/ui.tabs.css b/themes/admin_wind/css/themeroller/ui.tabs.css
new file mode 100644
index 0000000..70ed3ef
--- /dev/null
+++ b/themes/admin_wind/css/themeroller/ui.tabs.css
@@ -0,0 +1,9 @@
+/* Tabs
+----------------------------------*/
+.ui-tabs {padding: .2em;}
+.ui-tabs .ui-tabs-nav { padding: .2em .2em 0 .2em;  position: relative; }
+.ui-tabs .ui-tabs-nav li { float: left; border-bottom: 0 !important; margin: 0 .2em -1px 0; padding: 0; list-style: none; }
+.ui-tabs .ui-tabs-nav li a { display:block; text-decoration: none; padding: .5em 1em; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected {  padding-bottom: .1em; border-bottom: 0; }
+.ui-tabs .ui-tabs-panel { padding: 1em 1.4em;  display: block; border: 0; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
\ No newline at end of file
diff --git a/themes/admin_wind/css/themeroller/ui.theme.css b/themes/admin_wind/css/themeroller/ui.theme.css
new file mode 100644
index 0000000..477252e
--- /dev/null
+++ b/themes/admin_wind/css/themeroller/ui.theme.css
@@ -0,0 +1,243 @@
+
+
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+* To view and modify this theme, visit http://ui.jquery.com/themeroller/?tr=&ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+*/
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; }
+.ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
+.ui-widget-header a { color: #ffffff; }
+.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; outline: none; }
+.ui-state-default a { color: #2e6e9e; text-decoration: none; outline: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; outline: none; }
+.ui-state-hover a { color: #1d5987; text-decoration: none; outline: none; }
+.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; outline: none; }
+.ui-state-active a { color: #e17009; outline: none; text-decoration: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; }
+.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
+.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-right {  -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
+.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }
\ No newline at end of file
diff --git a/themes/admin_wind/images/avatar.jpg b/themes/admin_wind/images/avatar.jpg
new file mode 100644
index 0000000..acad931
Binary files /dev/null and b/themes/admin_wind/images/avatar.jpg differ
diff --git a/themes/admin_wind/images/ico-denied-inactive.png b/themes/admin_wind/images/ico-denied-inactive.png
new file mode 100644
index 0000000..56db3ff
Binary files /dev/null and b/themes/admin_wind/images/ico-denied-inactive.png differ
diff --git a/themes/admin_wind/images/ico-denied-passive.png b/themes/admin_wind/images/ico-denied-passive.png
new file mode 100644
index 0000000..1e99223
Binary files /dev/null and b/themes/admin_wind/images/ico-denied-passive.png differ
diff --git a/themes/admin_wind/images/ico-denied.png b/themes/admin_wind/images/ico-denied.png
new file mode 100644
index 0000000..08f2493
Binary files /dev/null and b/themes/admin_wind/images/ico-denied.png differ
diff --git a/themes/admin_wind/images/ico-error.png b/themes/admin_wind/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/admin_wind/images/ico-error.png differ
diff --git a/themes/admin_wind/images/ico-info.png b/themes/admin_wind/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/admin_wind/images/ico-info.png differ
diff --git a/themes/admin_wind/images/ico-lock.png b/themes/admin_wind/images/ico-lock.png
new file mode 100644
index 0000000..2ebc4f6
Binary files /dev/null and b/themes/admin_wind/images/ico-lock.png differ
diff --git a/themes/admin_wind/images/ico-separator-rtl.gif b/themes/admin_wind/images/ico-separator-rtl.gif
new file mode 100644
index 0000000..d9061a4
Binary files /dev/null and b/themes/admin_wind/images/ico-separator-rtl.gif differ
diff --git a/themes/admin_wind/images/ico-separator.gif b/themes/admin_wind/images/ico-separator.gif
new file mode 100644
index 0000000..3de2d0d
Binary files /dev/null and b/themes/admin_wind/images/ico-separator.gif differ
diff --git a/themes/admin_wind/images/ico-success-inactive.png b/themes/admin_wind/images/ico-success-inactive.png
new file mode 100644
index 0000000..74b2032
Binary files /dev/null and b/themes/admin_wind/images/ico-success-inactive.png differ
diff --git a/themes/admin_wind/images/ico-success-passive.png b/themes/admin_wind/images/ico-success-passive.png
new file mode 100644
index 0000000..dc8d1de
Binary files /dev/null and b/themes/admin_wind/images/ico-success-passive.png differ
diff --git a/themes/admin_wind/images/ico-success.png b/themes/admin_wind/images/ico-success.png
new file mode 100644
index 0000000..a9925a0
Binary files /dev/null and b/themes/admin_wind/images/ico-success.png differ
diff --git a/themes/admin_wind/images/ico-warning.png b/themes/admin_wind/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/admin_wind/images/ico-warning.png differ
diff --git a/themes/admin_wind/images/loading-large.gif b/themes/admin_wind/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/admin_wind/images/loading-large.gif differ
diff --git a/themes/admin_wind/images/loading-small.gif b/themes/admin_wind/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/admin_wind/images/loading-small.gif differ
diff --git a/themes/admin_wind/js/ui.init.js b/themes/admin_wind/js/ui.init.js
new file mode 100644
index 0000000..4ed912f
--- /dev/null
+++ b/themes/admin_wind/js/ui.init.js
@@ -0,0 +1,62 @@
+/**
+ * Initialize jQuery UI and Gallery Plugins
+ * @todo Move ui-corner-all assignments to theme admin views
+ */
+
+$(document).ready(function(){
+
+  // Initialize Superfish menus
+  $("#g-site-admin-menu .g-menu").hide().addClass("sf-menu");
+  $("#g-site-admin-menu .g-menu").superfish({
+    delay: 500,
+    animation: {
+      opacity: "show",
+      height: "show"
+    },
+    pathClass: "g-selected",
+    speed: "fast"
+  }).show();
+
+  // Initialize status message effects
+  $("#g-action-status li").gallery_show_message();
+
+  // Initialize modal dialogs
+  $(".g-dialog-link").gallery_dialog();
+
+  // Initialize short forms
+  $(".g-short-form").gallery_short_form();
+
+  // Initialize ajax links
+  $(".g-ajax-link").gallery_ajax();
+
+  // Initialize panels
+  $(".g-panel-link").gallery_panel();
+
+  if ($("#g-photo-stream").length) {
+    // Vertically align thumbs in photostream
+    $(".g-item").gallery_valign();
+  }
+
+  // Apply jQuery UI button css to submit inputs
+  $("input[type=submit]:not(.g-short-form input)").addClass("ui-state-default ui-corner-all");
+
+  // Round view menu buttons
+  if ($("#g-admin-comments-menu").length) {
+    $("#g-admin-comments-menu ul").removeClass("g-menu");
+    $("#g-admin-comments-menu").addClass("g-buttonset");
+    $("#g-admin-comments-menu a").addClass("g-button ui-state-default");
+    $("#g-admin-comments-menu ul li:first a").addClass("ui-corner-left");
+    $("#g-admin-comments-menu ul li:last a").addClass("ui-corner-right");
+  }
+
+  // Round corners
+  $(".g-selected").addClass("ui-corner-all");
+  $(".g-available .g-block").addClass("ui-corner-all");
+  $(".g-unavailable").addClass("ui-corner-all");
+
+  // Remove titles for menu options since we're displaying that text anyway
+  $(".sf-menu a, .sf-menu li").removeAttr("title");
+
+  // Initialize button hover effect
+  $.fn.gallery_hover_init();
+});
diff --git a/themes/admin_wind/theme.info b/themes/admin_wind/theme.info
new file mode 100644
index 0000000..e2be928
--- /dev/null
+++ b/themes/admin_wind/theme.info
@@ -0,0 +1,10 @@
+name = "Gallery Wind"
+description = "A crisp Site Administration theme with soft colors and drop down menus."
+version = 1
+author = "Gallery Team"
+admin = 1
+site = 0
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Themes:admin_wind"
+discuss_url = "http://galleryproject.org/forum_theme_admin_wind"
diff --git a/themes/admin_wind/thumbnail.png b/themes/admin_wind/thumbnail.png
new file mode 100644
index 0000000..b07a4cc
Binary files /dev/null and b/themes/admin_wind/thumbnail.png differ
diff --git a/themes/admin_wind/views/admin.html.php b/themes/admin_wind/views/admin.html.php
new file mode 100644
index 0000000..9a14914
--- /dev/null
+++ b/themes/admin_wind/views/admin.html.php
@@ -0,0 +1,104 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" <?= $theme->html_attributes() ?> xml:lang="en" lang="en">
+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+    <? $theme->start_combining("script,css") ?>
+    <title>
+      <? if ($page_title): ?>
+        <?= t("Gallery Admin: %page_title", array("page_title" => $page_title)) ?>
+      <? else: ?>
+        <?= t("Admin dashboard") ?>
+      <? endif ?>
+    </title>
+    <link rel="shortcut icon"
+          href="<?= url::file(module::get_var("gallery", "favicon_url")) ?>"
+          type="image/x-icon" />
+    <link rel="apple-touch-icon-precomposed"
+          href="<?= url::file(module::get_var("gallery", "apple_touch_icon_url")) ?>" />
+
+    <?= $theme->script("jquery.js") ?>
+    <?= $theme->script("jquery.form.js") ?>
+    <?= $theme->script("jquery-ui.js") ?>
+    <?= $theme->script("gallery.common.js") ?>
+    <? /* MSG_CANCEL is required by gallery.dialog.js */ ?>
+    <script type="text/javascript">
+    var MSG_CANCEL = <?= t("Cancel")->for_js() ?>;
+    </script>
+    <?= $theme->script("gallery.ajax.js") ?>
+    <?= $theme->script("gallery.dialog.js") ?>
+    <?= $theme->script("superfish/js/superfish.js") ?>
+    <?= $theme->script("jquery.scrollTo.js") ?>
+
+    <?= $theme->admin_head() ?>
+
+    <? /* Theme specific CSS/JS goes last so that it can override module CSS/JS */ ?>
+    <?= $theme->script("ui.init.js") ?>
+    <?= $theme->css("yui/reset-fonts-grids.css") ?>
+    <?= $theme->css("themeroller/ui.base.css") ?>
+    <?= $theme->css("superfish/css/superfish.css") ?>
+    <?= $theme->css("screen.css") ?>
+    <? if (locales::is_rtl()): ?>
+    <?= $theme->css("screen-rtl.css") ?>
+    <? endif; ?>
+    <!--[if lt IE 8]>
+    <link rel="stylesheet" type="text/css" href="<?= $theme->url("css/fix-ie.css") ?>"
+          media="screen,print,projection" />
+    <![endif]-->
+
+    <!-- LOOKING FOR YOUR CSS? It's all been combined into the link below -->
+    <?= $theme->get_combined("css") ?>
+
+    <!-- LOOKING FOR YOUR JAVASCRIPT? It's all been combined into the link below -->
+    <?= $theme->get_combined("script") ?>
+  </head>
+
+  <body <?= $theme->body_attributes() ?>>
+    <?= $theme->admin_page_top() ?>
+    <? if ($sidebar): ?>
+    <div id="doc3" class="yui-t5 g-view">
+    <? else: ?>
+    <div id="doc3" class="yui-t7 g-view">
+    <? endif; ?>
+      <?= $theme->site_status() ?>
+      <div id="g-header" class="ui-helper-clearfix">
+        <?= $theme->admin_header_top() ?>
+        <a id="g-logo" class="g-left" href="<?= item::root()->url() ?>" title="<?= t("go back to the Gallery")->for_html_attr() ?>">
+          &larr; <?= t("back to the ...") ?>
+        </a>
+        <?= $theme->user_menu() ?>
+        <!-- hide the menu until after the page has loaded, to minimize menu flicker -->
+        <div id="g-site-admin-menu" class="ui-helper-clearfix" style="visibility: hidden">
+          <?= $theme->admin_menu() ?>
+        </div>
+        <script type="text/javascript"> $(document).ready(function() { $("#g-site-admin-menu").css("visibility", "visible"); }) </script>
+        <?= $theme->admin_header_bottom() ?>
+      </div>
+      <div id="bd">
+        <div id="yui-main">
+          <div class="yui-b">
+            <div id="g-content" class="yui-g">
+              <?= $theme->messages() ?>
+              <?= $content ?>
+            </div>
+          </div>
+        </div>
+        <? if ($sidebar): ?>
+        <div id="g-sidebar" class="yui-b">
+          <?= $sidebar ?>
+        </div>
+        <? endif ?>
+      </div>
+      <div id="g-footer" class="g-inline ui-helper-clearfix">
+        <?= $theme->admin_footer() ?>
+        <? if (module::get_var("gallery", "show_credits")): ?>
+        <ul id="g-credits" class="g-inline">
+          <?= $theme->admin_credits() ?>
+        </ul>
+        <? endif ?>
+      </div>
+    </div>
+    <?= $theme->admin_page_bottom() ?>
+  </body>
+</html>
diff --git a/themes/admin_wind/views/block.html.php b/themes/admin_wind/views/block.html.php
new file mode 100644
index 0000000..d1d2d08
--- /dev/null
+++ b/themes/admin_wind/views/block.html.php
@@ -0,0 +1,18 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? if ($anchor): ?>
+<a name="<?= $anchor ?>"></a>
+<? endif ?>
+<div block_id="<?= $id ?>" id="<?= $css_id ?>" class="g-block ui-widget">
+  <div class="ui-dialog-titlebar ui-widget-header ui-helper-clearfix ui-icon-right">
+    <? if ($css_id != "g-block-adder"): ?>
+    <a href="<?= url::site("admin/dashboard/remove_block/$id?csrf=$csrf") ?>"
+       class="ui-dialog-titlebar-close ui-corner-all">
+      <span class="ui-icon ui-icon-closethick">remove</span>
+    </a>
+    <? endif ?>
+    <?= $title ?>
+  </div>
+  <div class="g-block-content">
+    <?= $content ?>
+  </div>
+</div>
diff --git a/themes/admin_wind/views/paginator.html.php b/themes/admin_wind/views/paginator.html.php
new file mode 100644
index 0000000..b46d974
--- /dev/null
+++ b/themes/admin_wind/views/paginator.html.php
@@ -0,0 +1,88 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?
+// This is a generic paginator for admin collections.  Depending on the page type, there are
+// different sets of variables available.  With this data, you can make a paginator that
+// lets you say "You're viewing photo 5 of 35", or "You're viewing photos 10 - 18 of 37"
+// for album views.
+
+//
+// Available variables for all page types:
+//   $page_type               - "collection", "item", or "other"
+//   $page_subtype            - "album", "movie", "photo", "tag", etc.
+//   $previous_page_url       - the url to the previous page, if there is one
+//   $next_page_url           - the url to the next page, if there is one
+//   $total                   - the total number of photos in this album
+//
+// Available for the "collection" page types:
+//   $page                    - what page number we're on
+//   $max_pages               - the maximum page number
+//   $page_size               - the page size
+//   $first_page_url          - the url to the first page, or null if we're on the first page
+//   $last_page_url           - the url to the last page, or null if we're on the last page
+//   $first_visible_position  - the position number of the first visible photo on this page
+//   $last_visible_position   - the position number of the last visible photo on this page
+//
+// Available for "item" page types:
+//   $position                - the position number of this photo
+//
+?>
+
+<? if ($total): ?>
+<ul class="g-paginator ui-helper-clearfix">
+  <li class="g-first">
+  <? if ($page_type == "collection"): ?>
+    <? if (isset($first_page_url)): ?>
+      <a href="<?= $first_page_url ?>" class="g-button ui-icon-left ui-state-default ui-corner-all">
+        <span class="ui-icon ui-icon-seek-first"></span><?= t("First") ?></a>
+    <? else: ?>
+      <a class="g-button ui-icon-left ui-state-disabled ui-corner-all">
+        <span class="ui-icon ui-icon-seek-first"></span><?= t("First") ?></a>
+    <? endif ?>
+  <? endif ?>
+
+  <? if (isset($previous_page_url)): ?>
+    <a href="<?= $previous_page_url ?>" class="g-button ui-icon-left ui-state-default ui-corner-all">
+      <span class="ui-icon ui-icon-seek-prev"></span><?= t("Previous") ?></a>
+  <? else: ?>
+    <a class="g-button ui-icon-left ui-state-disabled ui-corner-all">
+      <span class="ui-icon ui-icon-seek-prev"></span><?= t("Previous") ?></a>
+  <? endif ?>
+  </li>
+
+  <li class="g-info">
+    <? if ($total): ?>
+      <? if ($page_type == "collection"): ?>
+        <?= /* @todo This message isn't easily localizable */
+            t2("Viewing %from_number of %count",
+               "Viewing %from_number - %to_number of %count",
+               $total,
+               array("from_number" => $first_visible_position,
+                     "to_number" => $last_visible_position,
+                     "count" => $total)) ?>
+      <? else: ?>
+        <?= t("%position of %total", array("position" => $position, "total" => $total)) ?>
+      <? endif ?>
+    <? endif ?>
+  </li>
+
+  <li class="g-text-right">
+  <? if (isset($next_page_url)): ?>
+    <a href="<?= $next_page_url ?>" class="g-button ui-icon-right ui-state-default ui-corner-all">
+      <span class="ui-icon ui-icon-seek-next"></span><?= t("Next") ?></a>
+  <? else: ?>
+    <a class="g-button ui-state-disabled ui-icon-right ui-corner-all">
+      <span class="ui-icon ui-icon-seek-next"></span><?= t("Next") ?></a>
+  <? endif ?>
+
+  <? if ($page_type == "collection"): ?>
+    <? if (isset($last_page_url)): ?>
+      <a href="<?= $last_page_url ?>" class="g-button ui-icon-right ui-state-default ui-corner-all">
+        <span class="ui-icon ui-icon-seek-end"></span><?= t("Last") ?></a>
+    <? else: ?>
+      <a class="g-button ui-state-disabled ui-icon-right ui-corner-all">
+        <span class="ui-icon ui-icon-seek-end"></span><?= t("Last") ?></a>
+    <? endif ?>
+  <? endif ?>
+  </li>
+</ul>
+<? endif ?>
\ No newline at end of file
diff --git a/themes/greydragon/admin/controllers/admin_theme_options.php b/themes/greydragon/admin/controllers/admin_theme_options.php
new file mode 100644
index 0000000..e8094e8
--- /dev/null
+++ b/themes/greydragon/admin/controllers/admin_theme_options.php
@@ -0,0 +1,860 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?    
+class Admin_Theme_Options_Controller extends Admin_Controller {
+
+  protected $min_gallery_ver = 49;
+
+  private function load_theme_info() {
+    $file = THEMEPATH . "greydragon/theme.info";
+    $theme_info = new ArrayObject(parse_ini_file($file), ArrayObject::ARRAY_AS_PROPS);
+    return $theme_info;
+  }
+
+  private function get_theme_version() {
+    $theme_info = $this->load_theme_info();
+    return ($theme_info->version);
+  }
+
+  private function get_theme_name() {
+    $theme_info = $this->load_theme_info();
+    return ($theme_info->name);
+  }
+
+  private function get_packlist($type, $filename) {
+    $packlist = array();
+    $packroot = THEMEPATH . 'greydragon/css/' . $type . '/';
+
+    foreach (scandir($packroot) as $pack_name):
+      if (file_exists($packroot . "$pack_name/css/" . $filename . ".css")):
+        if ($pack_name[0] == "."):
+          continue;
+        endif;
+
+        $packlist[$pack_name] = t($pack_name);
+      endif;
+    endforeach;
+    return $packlist;
+  }
+
+  private function get_colorpacks() {
+    return $this->get_packlist('colorpacks', 'colors');
+  }
+
+  private function get_framepacks() {
+    return $this->get_packlist('framepacks', 'frame');
+  }
+
+  private function prerequisite_check($group, $id, $is_ok, $caption, $caption_ok, $caption_failed, $iswarning, $msg_error) {
+    $confirmation_caption = ($is_ok)? $caption_ok : $caption_failed;
+    $checkbox = $group->checkbox($id)
+      ->label($caption . " " . $confirmation_caption)
+      ->checked($is_ok)
+      ->disabled(true);
+    if ($is_ok):
+      $checkbox->class("g-success");
+    elseif ($iswarning):
+      $checkbox->class("g-prerequisite g-warning")->error_messages("failed", $msg_error)->add_error("failed", 1);
+    else:
+      $checkbox->class("g-error")->error_messages("failed", $msg_error)->add_error("failed", 1);
+    endif;
+  }
+
+  /* Convert old values ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+  protected function upgrade_settings() {
+    if (module::get_var("th_greydragon", "hide_thumbmeta")):
+      module::set_var("th_greydragon", "thumb_metamode", "hide");
+      module::clear_var("th_greydragon", "hide_thumbmeta");
+    endif;
+
+    if (module::get_var("gallery", "appletouchicon_url")):
+      $temp = module::get_var("gallery", "appletouchicon_url");
+      module::set_var("gallery", "apple_touch_icon_url", $temp);
+      module::clear_var("gallery", "appletouchicon_url");
+    endif;
+
+    if (module::get_var("th_greydragon", "flex_rows", FALSE)):
+      module::set_var("th_greydragon", "column_count", -1);
+      module::clear_var("th_greydragon", "flex_rows");
+    endif;
+
+    if (module::get_var("th_greydragon", "thumb_descmode") == "overlay_static"):
+      module::set_var("th_greydragon", "thumb_descmode", "overlay_top");
+    endif;
+
+    if (module::get_var("th_greydragon", "mainmenu_position") == "1"):
+      module::set_var("th_greydragon", "mainmenu_position", "top");
+    endif;
+
+    if (module::get_var("th_greydragon", "hide_breadcrumbs")):
+      module::set_var("th_greydragon", "breadcrumbs_position", "hide");
+      module::clear_var("th_greydragon", "hide_breadcrumbs");
+    endif;
+
+    if (module::get_var("th_greydragon", "photonav_position")):
+      $temp = module::get_var("th_greydragon", "photonav_position");
+      module::set_var("th_greydragon", "paginator_album", $temp);
+      module::set_var("th_greydragon", "paginator_photo", $temp);
+      module::clear_var("th_greydragon", "photonav_position");
+    endif;
+
+    if (module::get_var("th_greydragon", "sidebar_allowed") == "none"):
+      module::set_var("th_greydragon", "sidebar_allowed", "default");
+    endif;
+
+    if (module::get_var("th_greydragon", "thumb_topalign")):
+      module::set_var("th_greydragon", "thumb_imgalign", "top");
+      module::clear_var("th_greydragon", "thumb_topalign");
+    elseif ((module::get_var("th_greydragon", "thumb_ratio") == "photo") && (!module::get_var("th_greydragon", "thumb_imgalign"))):
+      module::set_var("th_greydragon", "thumb_imgalign", "center");
+    endif;
+  }
+
+  protected function isCurlInstalled() {
+    if (in_array('curl', get_loaded_extensions())) {
+      return true;
+    } else {
+      return false;
+    }
+  } 
+
+  protected function get_edit_form_admin() {
+    $this->upgrade_settings();
+
+    $form = new Forge("admin/theme_options/save/", "", null, array("id" =>"g-theme-options-form"));
+
+    $rssmodulecheck = (module::is_active("rss") && module::info("rss"));
+
+    /* Prerequisites ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("requirements")->label(t("Prerequisites"));
+    $gallery_ver = module::get_version("gallery");
+    $this->prerequisite_check($group, "vercheck", $gallery_ver >= $this->min_gallery_ver, 
+      t("Gallery 3 Core v.") . $this->min_gallery_ver . "+", t("Installed"), t("Required"), FALSE, sprintf(t("Check Failed. Minimum Required Version is %s. Found %s."), $this->min_gallery_ver, $gallery_ver));
+    if (module::get_var("th_greydragon", "allow_root_page")):
+      $this->prerequisite_check($group, "rsscheck", $rssmodulecheck, 
+        t("RSS Module"), t("Found"), t("not Found"), TRUE, t("Install RSS module to Enable Root Page Support"));
+    endif;
+    $this->prerequisite_check($group, "curlcheck", ($this->isCurlInstalled()), 
+      t("PHP CURL Support is"), t("Enabled"), t("Disabled"), TRUE, t("Please make sure CURL support is enabled in PHP"));
+
+    /* Suggested Modules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("recommended")->label(t("Suggested Modules"));
+
+    $check_infos = array();
+    if (!module::get_var("th_greydragon", "hide_thumbmeta")):
+      $this->prerequisite_check($group, "info", (module::is_active("info") and module::info("info")), 
+        t("Info Module"), t("Found"), t("Required"), FALSE, t("Check Failed. Module is required to display Thumb metadata."));
+    endif;
+
+    if (module::is_active("fancybox") && module::info("fancybox")):
+      $check_infos[] = array("module" => "fancybox",  "module_name" => "Fancybox",  "link" => '<a href="http://codex.gallery2.org/Gallery3:Modules:fancybox" target="_blank">');
+    endif;
+    if (module::is_active("colorbox") && module::info("colorbox")):
+      $check_infos[] = array("module" => "colorbox",  "module_name" => "Colorbox",  "link" => '<a href="http://codex.gallery2.org/Gallery3:Modules:colorbox" target="_blank">');
+    endif;
+    if (module::is_active("shadowbox") && module::info("shadowbox")):
+      $check_infos[] = array("module" => "shadowbox", "module_name" => "Shadowbox", "link" => '<a href="http://codex.gallery2.org/Gallery3:Modules:shadowbox" target="_blank">');
+    endif;
+
+    switch (count($check_infos)):
+      case 0:
+        $check_infos[] = array("module" => "fancybox",  "module_name" => "Fancybox",  "link" => '<a href="http://codex.gallery2.org/Gallery3:Modules:fancybox" target="_blank">');
+        $this->prerequisite_check($group, "fancybox", FALSE, 
+          t("Fancybox/Colorbox/Shadowbox") . " " . t("Module"), t("Found"), t("not Found"), TRUE, sprintf(t("Install %smodule%s to Enable %s Support"), '<a href="http://codex.gallery2.org/Gallery3:Modules:fancybox" target="_blank">', '</a>', t("Fancybox")));
+        break;
+      case 1:
+        $check_info = $check_infos[0];
+        $this->prerequisite_check($group, $check_info["module"], TRUE, 
+          t($check_info["module_name"]) . " " . t("Module"), t("Found"), t("not Found"), TRUE, sprintf(t("Install %smodule%s to Enable %s Support"), $check_info["link"], '</a>', t($check_info["module_name"])));
+        break;
+      default:
+        $list = "";
+        $first = TRUE;
+        foreach ($check_infos as $key => $check_info):
+          if ($first):
+            $list .= $check_infos[$key]["module_name"];
+            $first = FALSE;
+          else:
+            $list .= ", " . $check_infos[$key]["module_name"];
+          endif;
+        endforeach;
+  
+        $this->prerequisite_check($group, "fancybox", FALSE, 
+            t($list . " Modules are Active"),
+            "",
+            "",
+            TRUE,
+            t("Slideshow feature would not work correctly. Please activate just one of these modules."));
+
+        break;
+    endswitch;
+
+    $check_info = $check_infos[0];
+    $thumbnavcheck = module::is_active("thumbnav") and module::info("thumbnav");
+
+    $this->prerequisite_check($group, "kbdnavcheck", ((module::is_active("kbd_nav")) and (module::info("kbd_nav"))), 
+      t("Kbd Navigation Module"), t("Found"), t("not Found"), TRUE, sprintf(t("Install %smodule%s to Enable Keyboard Navigation Support"), '<a href="http://codex.gallery2.org/Gallery3:Modules:kbd_nav" target="_blank">', '</a>'));
+    $this->prerequisite_check($group, "thumbnavcheck", $thumbnavcheck, 
+      t("ThumbNav Module"), t("Found"), t("not Found"), TRUE, sprintf(t("Install %smodule%s to Enable Thumb Navigation Support"), '<a href="http://codex.gallery2.org/Gallery3:Modules:thumbnav" target="_blank">', '</a>'));
+
+    $thumb_ratio = module::get_var("th_greydragon", "thumb_ratio", "photo");
+    $thumb_ratio_ex = FALSE;
+    switch ($thumb_ratio):
+      case "photo_ex":
+        $thumb_ratio = "photo";
+        $thumb_ratio_ex = TRUE;
+        break;
+      case "film_ex":
+        $thumb_ratio = "film";
+        $thumb_ratio_ex = TRUE;
+        break;
+      case "digital_ex":
+        $thumb_ratio = "digital";
+        $thumb_ratio_ex = TRUE;
+        break;
+      case "wide_ex":
+        $thumb_ratio = "wide";
+        $thumb_ratio_ex = TRUE;
+        break;
+      default:
+        break;
+    endswitch;
+
+    /* General Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $sidebar_allowed = module::get_var("th_greydragon", "sidebar_allowed");
+    $sidebar_visible = module::get_var("th_greydragon", "sidebar_visible");
+
+    $group = $form->group("edit_theme")->label(t("General Settings"));
+    $group->hidden("g_auto_delay")
+      ->value(module::get_var("th_greydragon", "auto_delay", 30));
+    $group->input("row_count")
+      ->label(t("Rows per Album Page"))
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("th_greydragon", "row_count", 3));
+    $group->dropdown("column_count")
+      ->label(t("Columns per Album Page"))
+      ->options(array("2" => t("2 columns"), "3" => t("3 columns"), "4" => t("4 columns"), "5" => t("5 columns"), "-1" => t("Flexible (3 x Number of Rows)")))
+      ->selected(module::get_var("th_greydragon", "column_count", 3));
+    $group->input("resize_size")
+      ->label(t("Resized Image Size (in pixels)"))
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("gallery", "resize_size"));
+    $group->input("logo_path")
+      ->label(t("Alternate Logo Image"))
+      ->value(module::get_var("th_greydragon", "logo_path"));
+    $group->input("favicon")
+      ->label(t("URL (or relative path) to your favicon.ico"))
+      ->value(module::get_var("gallery", "favicon_url"));
+    $group->input("appletouchicon")
+      ->label(t("URL (or relative path) to your Apple Touch icon"))
+      ->value(module::get_var("gallery", "apple_touch_icon_url"));
+    $group->input("header_text")
+      ->label(t("Header Text"))
+      ->value(module::get_var("gallery", "header_text"));
+    $group->input("footer_text")
+      ->label(t("Footer Text"))
+      ->value(module::get_var("gallery", "footer_text"));
+    $group->input("copyright")
+      ->label(t("Copyright Message"))
+      ->value(module::get_var("th_greydragon", "copyright"));
+    $group->dropdown("colorpack")
+      ->label(t("Color Pack/Site theme"))
+      ->options(self::get_colorpacks())
+      ->selected(module::get_var("th_greydragon", "color_pack", "greydragon"));
+    $group->dropdown("framepack")
+      ->label(t("Thumb Frame Pack"))
+      ->options(self::get_framepacks())
+      ->selected(module::get_var("th_greydragon", "frame_pack", "greydragon"));
+
+    /* Advanced Options - General ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_adv_main")->label(t("Advanced Options - General"));
+    $group->dropdown("viewmode")
+      ->label(t("Theme View Mode"))
+      ->options(array("default" => t("Full Mode (Default)"), "mini" => t("Mini Mode")))
+      ->selected(module::get_var("th_greydragon", "viewmode", "default"));
+    $group->dropdown("mainmenu_position")
+      ->label(t("Main Menu Position"))
+      ->options(array("default" => t("Bottom-Left (Default)"), "top" => t("Top-Left"), "bar" => t("Top Bar")))
+      ->selected(module::get_var("th_greydragon", "mainmenu_position"));
+    $group->dropdown("loginmenu_position")
+      ->label(t("Login Menu Position"))
+      ->options(array("header" => t("Header"), "default" => t("Footer (Default)"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "loginmenu_position", "default"));
+    $group->dropdown("breadcrumbs_position")
+      ->label(t("Breadcrumbs Position"))
+      ->options(array("default" => t("Bottom-Right (Default)"), "bottom-left" => t("Bottom-Left"), "top-right" => t("Top-Right"), "top-left" => t("Top-Left"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "breadcrumbs_position"));
+    $group->dropdown("title_source")
+      ->label(t("Title Source"))
+      ->options(array("default" => t("Title (Default)"), "no-filename" => t("Title/Suppress File Name"), "description" => t("Description")))
+      ->selected(module::get_var("th_greydragon", "title_source", "default"));
+    $group->input("custom_css_path")
+      ->label(t("File Name of custom.css or equivalent"))
+      ->value(module::get_var("th_greydragon", "custom_css_path"));
+    $group->input("resize_quality")
+      ->label(t("Resized Image Quallity (in %)"))
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("gallery", "image_quality", 100));
+    $group->input("visible_title_length")
+      ->label(t("Visible Title Length"))
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("gallery", "visible_title_length", 15));
+
+    $group->checkbox("show_guest_menu")
+      ->label(t("Show Main Menu for Guest Users"))
+      ->checked(module::get_var("th_greydragon", "show_guest_menu"));
+    $group->checkbox("toolbar_large")
+      ->label(t("Use Large Toolbar Buttons"))
+      ->checked(module::get_var("th_greydragon", "toolbar_large"));
+    $group->checkbox("show_credits")
+      ->label(t("Show Site Credits"))
+      ->checked(module::get_var("gallery", "show_credits"));
+    $group->checkbox("breadcrumbs_showinroot")
+      ->label(t("Show Breadcrumbs in root album/root page"))
+      ->checked(module::get_var("th_greydragon", "breadcrumbs_showinroot"));
+    $group->checkbox("disable_seosupport")
+      ->label(t("Disallow Search Engine Indexing (No Bots)"))
+      ->checked(module::get_var("th_greydragon", "disable_seosupport"));
+    $group->checkbox("desc_allowbbcode")
+      ->label(t("Allow BBCode/HTML in Descriptions"))
+      ->checked(module::get_var("th_greydragon", "desc_allowbbcode"));
+    $group->checkbox("use_permalinks")
+      ->label(t("Use Permalinks for Navigation"))
+      ->checked(module::get_var("th_greydragon", "use_permalinks"));
+
+    /* Advanced Options - Album page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_adv_album")->label(t("Advanced Options - Album Page"));
+    $group->dropdown("paginator_album")
+      ->label(t("Paginator Position"))
+      ->options(array("top" => t("Top"), "bottom" => t("Bottom"), "both" => t("Both"), "none" => t("None")))
+      ->selected(module::get_var("th_greydragon", "paginator_album"));
+    $group->dropdown("album_descmode")
+      ->label(t("Description Display Mode"))
+      ->options(array("hide" => t("Hide"), "top" => t("Top"), "bottom" => t("Bottom")))
+      ->selected(module::get_var("th_greydragon", "album_descmode"));
+    $group->checkbox("disablephotopage")
+      ->label(t("Disable Photo Page (use Slideshow Mode)"))
+      ->checked(module::get_var("th_greydragon", "disablephotopage"));
+    $group->checkbox("hidecontextmenu")
+      ->label(t("Hide Context Menu"))
+      ->checked(module::get_var("th_greydragon", "hidecontextmenu"));
+
+    /* Advanced Options - Album page - Thumbs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_adv_thumb")->label(t("Advanced Options - Album page - Thumbs"));
+    $group->dropdown("thumb_ratio")
+      ->label(t("Aspect Ratio"))
+      ->options(array("photo" => t("Actual"), "film" => t("Film/Full Frame 3:2"), "digital" => t("Digital 4:3"), "wide" => t("Wide/HDTV 16:9")))
+      ->selected($thumb_ratio);
+    $group->checkbox("thumb_ratio_ex")
+      ->label(t("Expanded Aspect Ratio (300px wide)"))
+      ->checked($thumb_ratio_ex);
+    $group->dropdown("thumb_imgalign")
+      ->label(t("Thumb Image Align"))
+      ->options(array("top" => t("Top"), "center" => t("Center"), "bottom" => t("Bottom"), "fit" => t("Fit")))
+      ->selected(module::get_var("th_greydragon", "thumb_imgalign"));
+
+    $group->dropdown("thumb_descmode_a")
+      ->label(t("Title Display Mode (Album)"))
+      ->options(array("overlay" => t("Overlay Top"), "overlay_top" => t("Overlay Top (Static)"), 
+          "overlay_bottom" => t("Overlay Bottom (Static)"), "bottom" => t("Bottom"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "thumb_descmode_a"));
+    $group->dropdown("thumb_descmode")
+      ->label(t("Title Display Mode (Photo)"))
+      ->options(array("overlay" => t("Overlay Top"), "overlay_top" => t("Overlay Top (Static)"), 
+          "overlay_bottom" => t("Overlay Bottom (Static)"), "bottom" => t("Bottom"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "thumb_descmode"));
+    $group->dropdown("thumb_metamode")
+      ->label(t("Meta Data Display Mode"))
+      ->options(array("default" => t("Overlay (Default)"), "merged" => t("Merge with Title"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "thumb_metamode", "default"));
+    $group->checkbox("thumb_random")
+      ->label(t("Randomize Thumb Image"))
+      ->checked(module::get_var("th_greydragon", "thumb_random"));
+
+    /* Advanced Options - Photo page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_adv_photo")->label(t("Advanced Options - Photo Page"));
+    $group->dropdown("paginator_photo")
+      ->label(t("Paginator Position"))
+      ->options(array("top" => t("Top"), "bottom" => t("Bottom"), "both" => t("Both"), "none" => t("None")))
+      ->selected(module::get_var("th_greydragon", "paginator_photo"));
+    $group->dropdown("photo_descmode")
+      ->label(t("Description Display Mode"))
+      ->options(array("overlay_top" => t("Overlay Top"), "overlay_bottom" => t("Overlay Bottom"), "overlay_top_s" => t("Overlay Top (Static)"),
+         "overlay_bottom_s" => t("Overlay Bottom (Static)"), "bottom" => t("Bottom"), "top" => t("Top"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "photo_descmode"));
+    $group->dropdown("photo_popupbox")
+      ->label(t($check_info["module_name"]) . " " . t("Mode"))
+      ->options(array("default" => t("Default (Slideshow/Preview)"), "preview" => t("Preview Only"), "none" => t("Disable")))
+      ->selected(module::get_var("th_greydragon", "photo_popupbox"));
+    $group->checkbox("thumb_inpage")
+      ->label(t("Keep Thumb Nav Block on the side"))
+      ->checked(module::get_var("th_greydragon", "thumb_inpage"));
+    if (!$thumbnavcheck):
+      $group->thumb_inpage->disabled(true);
+    endif;
+    $group->checkbox("hide_photometa")
+      ->label(t("Hide Item Meta Data"))
+      ->checked(module::get_var("th_greydragon", "hide_photometa", TRUE));
+
+    /* Advanced Options - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_adv_root")->label(t("Advanced Options - Root Page"));
+    $group->checkbox("allow_root_page")
+      ->label(t("Allow root page"))
+      ->checked(module::get_var("th_greydragon", "allow_root_page"));
+    $group->checkbox("show_root_desc")
+      ->label(t("Show Gallery Description"))
+      ->checked(!module::get_var("th_greydragon", "hide_root_desc"));
+    $group->input("root_feed")
+      ->label(t("Slideshow RSS Feed URL"))
+      ->value(module::get_var("th_greydragon", "root_feed", "/gallery3/index.php/rss/feed/gallery/latest"));
+    $group->dropdown("root_cyclemode")
+      ->label(t("Cycle Effect (Default: Fade)"))
+      ->options(array("fade" => t("Fade"), "fadeout" => t("Fade Out"), "fadeZoom" => t("Fade Zoom"), "blindX" => t("Blind X"), "blindY" => t("Blind Y"), 
+          "blindZ" => t("Blind Z"), "cover" => t("Cover"), "curtainX" => t("Curtain X"), "curtainY" => t("Curtain Y"), "growX" => t("Grow X"),
+          "growY" => t("Grow Y"), "none" => t("None"), "scrollUp" => t("Scroll Up"), "scrollDown" => t("Scroll Down"), "scrollLeft" => t("Scroll Left"),
+          "scrollRight" => t("Scroll Right"), "scrollHorz" => t("Scroll Horz"), "scrollVert" => t("Scroll Vert"), "shuffle" => t("Shuffle"),      
+          "slideX" => t("Slide X"), "slideY" => t("Slide Y"), "toss" => t("Toss"), "turnUp" => t("Turn Up"), "turnDown" => t("Turn Down"),
+          "turnLeft" => t("Turn Left"), "turnRight" => t("Turn Right"), "uncover" => t("Uncover"), "wipe" => t("Wipe"), "zoom" => t("Zoom")))
+      ->selected(module::get_var("th_greydragon", "root_cyclemode"));
+    $group->input("root_delay")
+      ->label(t("Slideshow Delay (Default: 15)"))
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("th_greydragon", "root_delay", "15"));
+    $group->checkbox("hide_root_sidebar")
+      ->label(t("Hide Sidebar"))
+      ->checked(module::get_var("th_greydragon", "hide_root_sidebar"));
+    $group->textarea("root_description")
+      ->label(t("Alternative Description (optional)"))
+      ->value(module::get_var("th_greydragon", "root_description"));
+
+    /* Sidebar Options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_side")->label(t("Sidebar Options"));
+    $group->checkbox("hide_blockheader")
+      ->label(t("Hide Block Header"))
+      ->checked(module::get_var("th_greydragon", "hide_blockheader"));
+    $group->checkbox("sidebar_albumonly")
+      ->label(t("Show Sidebar for Albums Only"))
+      ->checked(module::get_var("th_greydragon", "sidebar_albumonly"));
+    $group->checkbox("sidebar_hideguest")
+      ->label(t("Show Sidebar for Guest Users"))
+      ->checked(!module::get_var("th_greydragon", "sidebar_hideguest"));
+    $group->dropdown("sidebar_allowed")
+      ->label(t("Allowed Sidebar Positions"))
+      ->options(array("any" => t("Any"), "left" => t("Left"), "right" => t("Right"), "bottom" => t("Bottom"), "top" => t("Top"), "default" => t("Default Only")))
+      ->selected($sidebar_allowed);
+    $group->dropdown("sidebar_visible")
+      ->label(t("Default Sidebar Position"))
+      ->options(array("right" => t("Right"), "left" => t("Left"), "bottom" => t("Bottom"), "top" => t("Top"), "none" => t("No sidebar")))
+      ->selected($sidebar_visible);
+
+    /* Maintenance ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("maintenance")->label(t("Maintenance"));
+    $group->checkbox("build_thumbs")->label(t("Mark all Thumbnails for Rebuild"))->checked(false);
+    $group->checkbox("build_resize")->label(t("Mark all Image Resizes for Rebuild"))->checked(false);
+    $group->checkbox("build_exif")->label(t("Mark Exif Info data for reload"))->checked(false);
+    $group->checkbox("purge_cache")->label(t("Purge cache data"))->checked(false);
+    $group->checkbox("reset_theme")->label(t("Reset Theme to a Default State"))->checked(false);
+
+    module::event("theme_edit_form", $form);
+
+    $form->submit("g-theme-options-save")->value(t("Save Changes"));
+    
+    return $form;
+  }
+
+  protected function get_edit_form_help() {
+    $help = '<fieldset>';
+    $help .= '<legend>' . t("Help") . '</legend><ul>';
+    $help .= '<li><h3>' . t("Prerequisites") . '</h3>
+      <p><b>' . t("REQUIREMENTS NEED TO BE MET FOR THE THEME TO FUNCTION PROPERLY.") . '</b><br />
+        ' . t("Please refer to the section on the left.") . '
+      </li>';
+
+    $help .= '<li><h3>' . t("General Settings") . '</h3>
+      ' . t("<p>Theme is designed to display thumbnails as a table.
+        You can choose different number of <b>Rows/Columns per Album Page</b> or can use <b>Flexible Columns</b>.
+      <p>Default G3 logo can be replaced with your own by providing <b>Alternate Logo Image</b>. Recommended logo size
+        is within 300x80px. If you need bigger space for your logo, CSS would have to be adjusted. Otherwise, Logo could be
+        suppressed altogether by providing <b>Header Text</b> to replace it. <b>Footer Text</b> would be simply placed next
+        to Site's credits.
+      <p><b>Copyright Message</b> can be placed in the right top corner of the footer.
+      <p>Important feature of the theme is a support for Color Packs which is managed by <b>Selected Color Pack</b> Option.
+      <b>Color Pack</b> allows changing colors, styles, theme for the pages. By default 6 color packs are included,
+        but it could be easily extended. Visit Theme's Download page for additional information.
+      <b>Frame Pack</b> allows change Frames used for Thumbs in album pages.") . '
+      </li>';
+
+    $help .= '<li><h3>' . t("Advanced Options - General") . '</h3>
+      ' . t("<p>In order to allow easier integration of Gallery 3 within other site infrastructure, Theme supports Special <b>View Mode</b>
+        - when <i>Mini Mode</i> is selected, attempt would be made to minimize space associated with Header/Footer by trimming of
+        the some information. Use with caution. Theme supports CMD parameter to override this selection - add 
+        \"?viewmode=default|full|mini\" to site URL in order to trigger a switch for specific browser session. When browser session
+        is restarted, view mode would revert back to default set in Admin Panel.
+      <p>Show your appreciation for our hard work by allowing <b>Show Site Credits</b> or contributing to our Coffee Fund.
+      <p>If main menu has functionality intended for guest users you can use <b>Show Main Menu for Guest Users</b> to keep it
+        visible.
+      <br />You can go even further and move main menu to the top of the header with breadcrumbs taking it place by selecting
+        <b>Alternate Header Layout</b>. <br />Then if you prefer breadcrumbs not being used, simply hide it with <b>Hide
+        Breadcrumbs</b> option.
+      <br />Then you can decide if you want to <b>Show Breadcrumbs</b> in the root album/root page.
+      <p>If you like to add some cool effects while navigating between pages,
+        enable <b>Blend Page Transition</b>.
+      <p><b>Paginator Position</b> could be changed to display it above and/or below the main content. 
+      <p>You can further fine tune theme using custom CSS file by providing file name (file need to be located in <b>themes/custom</b>
+        folder) or more specific location in form of <b>your_path/your_file_name.css</b> if different.
+      <p>Block web crawlers from indexing your Gallery with <b>Disallow Search Engine Indexing</b> Option.") . '
+      </li>';
+    $help .= '<li><h3>' . t("Advanced Options - Album page - Thumbs") . '</h3>
+      ' . t("<p>Options in this section adjust how Photo's Thumb images are displayed.
+      <p><b>Aspect Ratio</b> specifies layout/size of the thumb. Setting should be used with understanding that some
+        information may be out of visible area (crop). When switching to/from <b>Actual Size</b>, it is recommended to rebuild
+        thumbs so that proper settings are used for thumb resize logic (see Maintenance section below). Combined with
+        <b>Expanded Aspect Ratio (300px wide)</b> you can switch between 200px and 300px wide thumb images.
+      <p><b>Title Display Mode</b> and <b>Meta Data Display Mode</b> allows changing how Item's caption and Meta Data is
+        displayed. And selecting <b>Merge with Title</b> would place meta data with the Title.
+      <p>Randomize your thumbs by enabling <b>Randomize Thumb Image</b> (Please use with caution as it does introduce extra
+        load for database.).") . '
+      </li>';
+    $help .= '<li><h3>' . t("Advanced Options - Photo Page") . '</h3>
+      ' . t("<p>Options in this section adjust how individual Photo are presented to the viewer.
+      <p>With <b>ShadowBox Mode</b>, theme's logic could be adjusted in how Slideshow module is integrated.
+      <br />As with Title in Photo Thumbs, <b>Description Display Mode</b> changes how Photo Description is displayed.
+      <br />You can choose to <b>Keep Thumb Nav Block on the side</b> of the Photo when Page is displayed with bottom aligned
+        or hidden Sidebar.
+      <br />And if metadata (owner/clicks/etc.) is unnecessary, it could be removed with <b>Hide Item Meta Data</b>.
+      <p>Theme allows use of BBCode/HTML in item's descriptions, to enable it select <b>Allow BBCode/HTML in Descriptions</b>.") . '
+      </li>';
+    $help .= '<li><h3>' . t("Advanced Options - Root Page") . '</h3>
+      ' . t("<p>Special option which allows adding special root/landing page with slideshow utilizing specified <b>Slideshow RSS Feed
+        URL</b> (Default: /gallery3/index.php/rss/feed/gallery/latest).
+      <p>To enable it, select <b>Allow root page</b>.
+      <p>Add small description on the side of the slideshow with <b>Show Gallery Description</b>.
+      <br />Adjust rotation delay with <b>Slideshow Delay</b>.
+      <br />If Sidebar is not desired in the Root Page it could be hidden with <b>Hide Sidebar</b> option.
+      <br />By default, description content is populated from description of the root album, but by providing <b>Alternative
+        Description</b> you can overwrite it.") . '
+      </li>';
+    $help .= '<li><h3>' . t("Sidebar Options") . '</h3>
+      ' . t("<p>If Block's header is not desired, it could be removed using <b>Hide Block Header</b>.
+      <p>Sidebar visibility could be limited to individual Photo pages with
+      <b>Show Sidebar for Albums Only</b>.
+      <p>When sidebar is visible it can be placed on the left or right of the 
+        screen or removed altogether using <b>Allowed Sidebar Positions</b>.
+        If more than one position is allowed, <b>Default Sidebar Position</b>
+        would indicate default state, but visitor would able change it later.") . '
+      </li>';
+    $help .= '<li><h3>' . t("Maintenance") . '</h3>
+      ' . t("<p>Without changing image size, you can <b>Mark all Resizes for Rebuild</b>.
+      Then you need to visit Admin\Maintenance to initiate the process.
+      <p>Same can be done for image thumbs with <b>Mark all Thumbnails for Rebuild</b>.
+      <p><b>Mark Exif/IPTC Info for reload</b> would mark all Exif or IPTC records as \"Dirty\" allowing it to be repopulated.
+      <p>And just in case you think that something is not right, you can always <b>Reset Theme to a Default State</b>.") . '
+      </li>';
+    $help .= '</ul></fieldset>';
+    return $help;
+  }
+
+  private function save_item_state($statename, $state, $value) {
+    if ($state):
+      module::set_var("th_greydragon", $statename, $value);
+    else:
+      module::clear_var("th_greydragon", $statename);
+    endif;
+  }
+
+  protected function legacy() {
+    module::clear_var("th_greydragon", "photonav_top");
+    module::clear_var("th_greydragon", "photonav_bottom");
+    module::clear_var("th_greydragon", "hide_sidebar_photo");
+    module::clear_var("th_greydragon", "hide_thumbdesc");
+    module::clear_var("th_greydragon", "use_detailview");
+    module::clear_var("th_greydragon", "horizontal_crop");
+    module::clear_var("th_greydragon", "photo_shadowbox");
+    module::clear_var("th_greydragon", "root_text");
+    module::clear_var("th_greydragon", "enable_pagecache");
+
+    module::clear_var("th_greydragon", "navigator_album");
+    module::clear_var("th_greydragon", "navigator_photo");
+
+    module::clear_var("th_greydragon", "blendpagetrans");
+    module::clear_var("th_greydragon", "last_update");
+    module::clear_var("th_greydragon", "thumb_quality");
+  }
+
+  protected function reset_theme() {
+    // Default core theme settings
+    module::set_var("gallery", "page_size", 9);
+    module::set_var("gallery", "resize_size", 640);
+    module::set_var("gallery", "thumb_size", 200);
+    module::set_var("gallery", "header_text", "");
+    module::set_var("gallery", "footer_text", "");
+    module::set_var("gallery", "show_credits", FALSE);
+
+    module::clear_all_vars("th_greydragon");
+  }
+
+  public function save() {
+    site_status::clear("gd_init_configuration");
+    access::verify_csrf();
+
+    $form = self::get_edit_form_admin();
+
+    if ($form->validate()):
+      $this->legacy();
+
+      if ($form->maintenance->reset_theme->value):
+        $this->reset_theme();
+        module::event("theme_edit_form_completed", $form);
+        message::success(t("Theme details are reset"));
+      else:
+        // * General Settings ****************************************************
+
+        $resize_size  = $form->edit_theme->resize_size->value;
+
+        $build_resize = $form->maintenance->build_resize->value;
+        $build_thumbs = $form->maintenance->build_thumbs->value;
+        $build_exif   = $form->maintenance->build_exif->value;
+        if (module::is_active("iptc") and module::info("iptc")):
+          $build_iptc   = $form->maintenance->build_iptc->value;
+        else:
+          $build_iptc = FALSE;
+        endif;
+        $purge_cache  = $form->maintenance->purge_cache->value;
+
+        $color_pack = $form->edit_theme->colorpack->value;
+        $frame_pack = $form->edit_theme->framepack->value;
+        $thumb_imgalign = $form->edit_theme_adv_thumb->thumb_imgalign->value;
+        $thumb_descmode_a = $form->edit_theme_adv_thumb->thumb_descmode_a->value;
+        $thumb_descmode = $form->edit_theme_adv_thumb->thumb_descmode->value;
+        $thumb_metamode = $form->edit_theme_adv_thumb->thumb_metamode->value;
+        $photo_descmode = $form->edit_theme_adv_photo->photo_descmode->value;
+        $photo_popupbox = $form->edit_theme_adv_photo->photo_popupbox->value;
+        $resize_quality = $form->edit_theme_adv_main->resize_quality->value;
+
+        if ($build_resize):
+          graphics::remove_rule("gallery", "resize", "gallery_graphics::resize");
+          graphics::add_rule("gallery", "resize", "gallery_graphics::resize",
+            array("width" => $resize_size, "height" => $resize_size, "master" => Image::AUTO), 100);
+        endif;
+
+        if (module::get_var("gallery", "image_quality") != $resize_quality):
+          module::set_var("gallery", "image_quality", $resize_quality);
+        endif;
+
+        if (module::get_var("gallery", "resize_size") != $resize_size):
+          module::set_var("gallery", "resize_size", $resize_size);
+        endif;
+
+        $_priorratio = module::get_var("th_greydragon", "thumb_ratio", "photo");
+        $thumb_ratio = $form->edit_theme_adv_thumb->thumb_ratio->value;
+        $thumb_ratio_ex = $form->edit_theme_adv_thumb->thumb_ratio_ex->value;
+        if ($thumb_ratio_ex):
+          $thumb_ratio .= "_ex";
+        endif;
+
+        if ($thumb_ratio_ex):
+          $thumb_size   = 300;  
+        else:
+          $thumb_size   = 200;
+        endif;
+
+        if ($thumb_ratio == "photo"):
+          $rule = Image::AUTO;
+        else:
+          $rule = Image::WIDTH;
+        endif;
+
+        if ($build_thumbs):
+          graphics::remove_rule("gallery", "thumb", "gallery_graphics::resize");
+          graphics::add_rule("gallery", "thumb", "gallery_graphics::resize",
+            array("width" => $thumb_size, "height" => $thumb_size, "master" => $rule), 100);
+        endif;
+
+        if (module::get_var("gallery", "thumb_size") != $thumb_size):
+          module::set_var("gallery", "thumb_size", $thumb_size);
+        endif;
+
+        $row_count    = $form->edit_theme->row_count->value;
+        $column_count = $form->edit_theme->column_count->value;
+        $this->save_item_state("row_count", 3, $row_count);
+        $this->save_item_state("column_count", 3, $column_count);
+        if ($column_count == -1):
+          $column_count = 3;
+        endif;
+        module::set_var("gallery", "page_size", $row_count * $column_count);
+        module::set_var("gallery", "header_text", $form->edit_theme->header_text->value);
+        module::set_var("gallery", "footer_text", $form->edit_theme->footer_text->value);
+        module::set_var("gallery", "favicon_url", $form->edit_theme->favicon->value);
+        module::set_var("gallery", "apple_touch_icon_url", $form->edit_theme->appletouchicon->value);
+
+        $this->save_item_state("copyright", $form->edit_theme->copyright->value, $form->edit_theme->copyright->value);
+        $this->save_item_state("logo_path", $form->edit_theme->logo_path->value, $form->edit_theme->logo_path->value);
+        $this->save_item_state("color_pack", (($color_pack) and ($color_pack != "greydragon")), $color_pack);
+        $this->save_item_state("frame_pack", (($frame_pack) and ($frame_pack != "greydragon")), $frame_pack);
+
+        $auto_delay = $form->edit_theme->g_auto_delay->value;
+        $this->save_item_state("auto_delay", $auto_delay != 30, $auto_delay);
+
+        // * Advanced Options - General ******************************************
+
+        $this->save_item_state("viewmode",              $form->edit_theme_adv_main->viewmode->value != "default", $form->edit_theme_adv_main->viewmode->value);
+        $this->save_item_state("toolbar_large",         $form->edit_theme_adv_main->toolbar_large->value, TRUE);
+        module::set_var("gallery", "show_credits",      $form->edit_theme_adv_main->show_credits->value);
+        $this->save_item_state("show_guest_menu",       $form->edit_theme_adv_main->show_guest_menu->value, TRUE);
+        $this->save_item_state("loginmenu_position",    $form->edit_theme_adv_main->loginmenu_position->value != "default", $form->edit_theme_adv_main->loginmenu_position->value);
+        $this->save_item_state("mainmenu_position",     $form->edit_theme_adv_main->mainmenu_position->value != "default", $form->edit_theme_adv_main->mainmenu_position->value);
+        $this->save_item_state("breadcrumbs_position",  $form->edit_theme_adv_main->breadcrumbs_position->value != "default", $form->edit_theme_adv_main->breadcrumbs_position->value);
+        $this->save_item_state("breadcrumbs_showinroot",$form->edit_theme_adv_main->breadcrumbs_showinroot->value, TRUE);
+        $this->save_item_state("custom_css_path",       $form->edit_theme_adv_main->custom_css_path->value != "", $form->edit_theme_adv_main->custom_css_path->value);
+        $this->save_item_state("disable_seosupport",    $form->edit_theme_adv_main->disable_seosupport->value, TRUE);
+        $this->save_item_state("desc_allowbbcode",      $form->edit_theme_adv_main->desc_allowbbcode->value, TRUE);
+        module::set_var("gallery", "visible_title_length", $form->edit_theme_adv_main->visible_title_length->value);
+        $this->save_item_state("title_source",          $form->edit_theme_adv_main->title_source->value != "default", $form->edit_theme_adv_main->title_source->value);
+        $this->save_item_state("use_permalinks",        $form->edit_theme_adv_main->use_permalinks->value, TRUE);
+
+        // * Advanced Options - Album page ***************************************
+
+        $this->save_item_state("album_descmode",    $form->edit_theme_adv_album->album_descmode->value != "hide", $form->edit_theme_adv_album->album_descmode->value);
+        $this->save_item_state("paginator_album",   $form->edit_theme_adv_album->paginator_album->value != "top", $form->edit_theme_adv_album->paginator_album->value);
+        $this->save_item_state("disablephotopage",  $form->edit_theme_adv_album->disablephotopage->value, TRUE);
+        $this->save_item_state("hidecontextmenu",   $form->edit_theme_adv_album->hidecontextmenu->value, TRUE);
+
+        // * Advanced Options - Album page - Thumbs ******************************
+
+        $this->save_item_state("thumb_ratio",       $thumb_ratio != "photo", $thumb_ratio);
+        $this->save_item_state("thumb_imgalign",    $thumb_imgalign != "top", $thumb_imgalign);
+        $this->save_item_state("thumb_descmode_a",  $thumb_descmode_a != "overlay", $thumb_descmode_a);
+        $this->save_item_state("thumb_descmode",    $thumb_descmode != "overlay", $thumb_descmode);
+        $this->save_item_state("thumb_metamode",    $thumb_metamode != "default", $thumb_metamode);
+        $this->save_item_state("thumb_random",      $form->edit_theme_adv_thumb->thumb_random->value, TRUE);
+
+        // * Advanced Options - Photo page ***************************************
+
+        $this->save_item_state("paginator_photo",  $form->edit_theme_adv_photo->paginator_photo->value != "top", $form->edit_theme_adv_photo->paginator_photo->value);
+        $this->save_item_state("photo_descmode",   $photo_descmode != "overlay_top", $photo_descmode);
+        $this->save_item_state("photo_popupbox",   $photo_popupbox != "default", $photo_popupbox);
+        $this->save_item_state("thumb_inpage",     $form->edit_theme_adv_photo->thumb_inpage->value, TRUE);
+        $this->save_item_state("hide_photometa",   !$form->edit_theme_adv_photo->hide_photometa->value, FALSE);
+
+        // * Advanced Options - Root page ****************************************
+
+        $rssmodulecheck = module::is_active("rss") and module::info("rss");
+
+        $root_feed = $form->edit_theme_adv_root->root_feed->value;
+        $root_cyclemode = $form->edit_theme_adv_root->root_cyclemode->value;
+        $root_delay = $form->edit_theme_adv_root->root_delay->value;
+        $root_description = $form->edit_theme_adv_root->root_description->value;
+
+        $this->save_item_state("allow_root_page", $form->edit_theme_adv_root->allow_root_page->value, TRUE);
+        $this->save_item_state("hide_root_desc",  !$form->edit_theme_adv_root->show_root_desc->value, TRUE);
+        $this->save_item_state("root_feed", $root_feed != "gallery/latest", $root_feed);
+        $this->save_item_state("root_cyclemode", $root_cyclemode != "fade", $root_cyclemode);
+        $this->save_item_state("root_delay", $root_delay != "15", $root_delay);
+        $this->save_item_state("hide_root_sidebar", $form->edit_theme_adv_root->hide_root_sidebar->value, TRUE);
+        $this->save_item_state("root_description", $root_description, $root_description);
+
+        // * Sidebar Options *****************************************************
+
+        $sidebar_allowed = $form->edit_theme_side->sidebar_allowed->value;
+        $sidebar_visible = $form->edit_theme_side->sidebar_visible->value;    
+
+        if ($sidebar_allowed == "right"):
+          $sidebar_visible = "right";
+        endif;
+        if ($sidebar_allowed == "left"):
+          $sidebar_visible = "left";
+        endif;
+
+        $this->save_item_state("hide_blockheader",  $form->edit_theme_side->hide_blockheader->value, TRUE);
+        $this->save_item_state("sidebar_albumonly", $form->edit_theme_side->sidebar_albumonly->value, TRUE);
+        $this->save_item_state("sidebar_hideguest", !$form->edit_theme_side->sidebar_hideguest->value, TRUE);
+        $this->save_item_state("sidebar_allowed",   $sidebar_allowed != "any",   $sidebar_allowed);
+        $this->save_item_state("sidebar_visible",   $sidebar_visible != "right", $sidebar_visible);
+
+        $this->save_item_state("last_update",       TRUE, time());
+
+        module::event("theme_edit_form_completed", $form);
+
+        if ($_priorratio != $thumb_ratio):
+          message::warning(t("Thumb aspect ratio has been changed. Consider rebuilding thumbs if needed."));
+        endif;
+
+        message::success(t("Updated theme details"));
+
+        if ($build_exif):
+          db::update('exif_records')
+            ->set(array('dirty'=>'1'))
+            ->execute();
+        endif;
+
+        if ($build_iptc):
+          db::update('iptc_records')
+            ->set(array('dirty'=>'1'))
+            ->execute();
+        endif;
+
+        if ($purge_cache):
+          db::build()
+            ->delete("caches")
+            ->execute();
+        endif;
+      endif;
+      url::redirect("admin/theme_options");
+    else:
+      print $this->get_admin_view();
+    endif;
+  }
+
+  protected function get_admin_view() {
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Grey Dragon Theme");
+    $view->content = new View("admin_theme_options.html");
+    $view->content->name = self::get_theme_name();
+    $view->content->version = self::get_theme_version();
+    $view->content->form = self::get_edit_form_admin();
+    $view->content->help = self::get_edit_form_help();
+    return $view;
+  }
+
+  public function index() {
+    site_status::clear("gd_init_configuration");
+    print $this->get_admin_view();
+  }
+}
+?>
\ No newline at end of file
diff --git a/themes/greydragon/admin/views/admin_theme_options.html.php b/themes/greydragon/admin/views/admin_theme_options.html.php
new file mode 100644
index 0000000..0e9f404
--- /dev/null
+++ b/themes/greydragon/admin/views/admin_theme_options.html.php
@@ -0,0 +1,38 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+  $gd_shared_installed = (module::is_active("greydragon") && module::info("greydragon"));
+  if ($gd_shared_installed):
+    $view = new View("gd_admin_include.html");
+    $view->is_module = FALSE;
+    $view->downloadid = 1;
+    $view->name = "greydragon";
+    $view->form = $form;
+    $view->help = $help;
+  else:
+    $view  = '<div id="g-greydragon-admin" class="g-block">';
+    $view .= "<h1>" . t("Prerequisite") . "</h1><hr>";
+    $view .= "<p>" . t("This theme requires GreyDragon shared module to be installed and actived first.") . "</p>";
+    $view .= "<p>" . t("Please download it") . ' <a href="http://codex.gallery2.org/Gallery3:Modules:greydragon" target="_blank">' . t("here") . "</a> " . t("and install. Make sure it is activated.") . "</p>";
+    $view .= "</div>";
+  endif;
+
+  print $view;
+?>   
+
diff --git a/themes/greydragon/changelog.txt b/themes/greydragon/changelog.txt
new file mode 100644
index 0000000..04ca0d4
--- /dev/null
+++ b/themes/greydragon/changelog.txt
@@ -0,0 +1,641 @@
+=== Grey Dragon Theme ===
+Grey Dragon Theme - a custom theme for Gallery 3
+
+This theme was designed and built by Serguei Dosyukov, whose blog you will find
+at http://blog.dragonsoft.us/
+Copyright (C) 2009-2012 Serguei Dosyukov
+
+Tested up to: G3 3.0.3 build 55
+Minimum requirement: G3 3.0.2 build 49
+
+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 for more
+details. You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street Fifth Floor, Boston, MA  02110-1301, USA.
+
+=== Open issues ===
+- RTL layout support
+                            
+=== Changelog ===
+version 4.0.2
+- Incompatability fix for PHP5.4 and below causing crash and blank page. http://galleryproject.org/forum_theme_greydragon?page=48#comment-408923
+- Fix to allow thumbnail rotation update when operation is performed. http://galleryproject.org/forum_theme_greydragon?page=48#comment-408993
+- Cycle JS: Added fadeout support. Fixed issue in root page when "Click to Enter" link would disappear with some effects
+
+version 4.0.1
+- Code converted to use latest jQuery library
+- Added support for RWInfo meta data injection
+- CSS: Fixes a phenomenon where dialog content not setting proper width in FF/Ch
+- CSS: Fixes a phenomenon where context menu shows empty space above first item
+- Added support for g-movie class in thumbs
+- Admin: Better help translation
+- Logic to load frame template optimized to prevent exception
+- thumb_top()/thumb_botom() call moved inside div.g-thumbslide per Dave's request
+- Markup cleanup for W3C validation
+- CSS: small layout size adjustments in Simple Frame Pack
+- Photo Page: fixed issue with image preload logic when one of the items is an album
+- Added code protection to paginator when item is not well defined - missing ->url() method
+- Breadcrumbs to take advantage of new logic introduced in latest G3 core for tags and search
+- Added support for tag_albums module for pagination
+- FP: Fix for Book frame pack - missing frame for movie thumbs
+- Photo pages in Tag based collections do not support full item list. As result First/Last page paginator buttons and page list need to be disabled.
+- Updated jQuery Cycle plug-in to latest version
+- CSS: fixes for movie thumbnail in greydragon framepack
+
+version 3.2.2
+- CSS: Fixes a phenomenon where dialog content not aligning properly under some conditions
+- CSS: Fixes a phenomenon where login dialog for error/login and reauthenticate pages were not in sync
+- Movie thumb and Photo IDs are adjusted to comply with 3.0.3 notation
+- Photo page image precache javascript moved into .ready to speed up the page load
+- CP: Roundrobin styles improvements - top login positioning adjusted, removed padding for root page when sidebar is used
+- ADMIN: Added prerequisite check for CURL support in PHP
+
+version 3.2.1
+- Logic to process command line parameters changed to prevent unhandled exception on some LAMP instances
+
+version 3.2.0
+- Theme is now HTML 5 
+- CSS: Dropped support for IE 6
+- IMPORTANT: .g-extended class moved from .g-item level into a <body> to allow layout manipulation based on thumb formats. Styles are affected.
+- Added class marker to page's <body> element to indicate current sidebar mode - g-sidebar-xxxxxxxx
+- CSS: Min width of the gallery is now enforced based on number of columns and sidebar visibility - extended thumbs 3/4 columns
+- CSS:   Decrease size of the column for 3 column layout to 31% to prevent wrapping in some browser modes
+- ADMIN: Logic added to inform site owner about new versions of the theme
+- ADMIN: Admin page layout is now based on shared GreyDragon module which is now required 
+- ADMIN: "Visible Title Length" option - access to G3 title length setting. 
+- ADMIN: Use Permalinks for navigation - allows /root, /enter be used for root page access. 
+  Requires the following rules added in .htaccess <mod_rewrite.c> section
+
+  ########## Enable /root url ################
+  #
+  RewriteRule ^root ?root=yes [NC]
+  RewriteRule ^enter ?root=no [NC]
+  #
+  ############################################
+
+- Visible Title Length is now taken in consideration when displaying Photo Titles in thumbs, breadcrumbs, etc.
+- Improved file name detection for Title Source
+- CP: new color pack - Round Robin     \
+- FP: new frame pack - Round Corners   / combined would give look of Clean Canvas theme
+- FP: Book frame pack : removed right padding to prevent wrapping on smaller resolutions
+- FP: Wall frame pack : min width decreased to all proper alignment of tiles
+- jquery.cycle.js updated to v.2.9999.4
+- Synchronize Calendar page with page.html.php
+- CSS: forms.css - fixed two misspelled rules
+- Added code protection from Camel case in CMD parameters
+- Fixed issue with missing status icons for some colorpacks in Upload dialog
+- Added code protection in Root page to detect situation when roller is empty and then do not initialize the cycle plugin
+- Added translation support for default thumb caption (Photo #, Movie #, etc)
+                                                                                                       
+version 3.1.4
+- ADMIN: Option to specify image quality level for Photo resizes and Thumbs
+- ADMIN: Additional Description Display Mode for Photo page : Overlay Top (Static), Overlay Bottom (Static)
+- ADMIN: Title Source - manage what thumb/image title is based on : Title | Title/Suppress Filename | Description
+- Added support for normalize.css - see http://necolas.github.com/normalize.css/ for more details
+- Added rel=nofollow for sidebar mode switch links to prevent indexing
+- Fix: module check failing in admin section when none of colorbox, shadowbox or fancybox is intalled
+- Fix: CSS: Added missing rule for size of the thumb in Wall frame pack for "Actual" aspect ratio
+- Fix: CSS: Fixed "Forgot password" misalignment in Login dialog
+- G3 version requirement increased to 3.0.2
+
+version 3.1.3
+- Removed validation for ImageBlockEx preventing use of RootPage option
+- Removed JS code - attempt to have fadeIn effect
+ 
+version 3.1.2
+- CSS: Fixed issue with breadcrumbs divider in colorpacks
+- CSS: Fixed issue with thumb description positioning
+
+version 3.1.1
+- Removed some redundant code in page.html.php
+- Fixed issue with fixed Columns style not being applied
+- Added code protection for situation when $position is not defined in paginator.html.php
+- CSS: Fixed issues with popup menu positioning
+
+version 3.1.0
+- CSS: !!! Folder Structure Change !!! colors.css and frame.css added to aggregated CSS.
+- ADMIN: Root Page is now iPad/Mac compatible - Flash player has been replaced with jquery.cycle - option added to manage
+  rotation mode. ImageBlockEx module is no longer required. For hosts where there is a block accessing local RSS feed, 
+  rootpage.html.php_fix can be used (old style) by renaming it and placing into /themes/custom/views folder
+- ADMIN: New option - Hide Context Menu for thumbs
+- ADMIN: New option - Disable photo page - open FancyBox style slideshow directly from album page
+- ADMIN: New option - Show Sidebar for Guest Users
+- ADMIN: Option for Thumb alignment extended to Top/Center/Bottom/Fit
+- ADMIN: Option's order change in Advanced Options - General
+- ADMIN: Large toolbar buttons
+- ADMIN: "Blend Page Transitions" is replaced with JS version
+- ADMIN: Corrected setting for Apple Touch Fav Icon to use G3 default setting
+- ADMIN: "Login Menu Position" expanded to allow login to be hidden. Admin can access Admin area using http://site_url/admin URL
+- CP: New color pack - White Hawk
+- FP: New frame pack - Wall
+- FP: Support for custom frame content added - frame.html.php
+- Core: Current framepack is now referenced by the page
+- Core: Body class logic moved into theme's library class
+- Core: "Up" navigation button now would take you to item's associated page rather then to first page of the album
+- Core: Fixed issue of Sidebar position setting not being picked up under some conditions
+- Core: Improved detection for root page - if root album id <> 1
+- Core: Framepack and viewmode URL parameter value is now retained for duration of the session
+- Core: In "Disable photo page" mode, if EXIF module is disabled, thumb would include clickable reference to EXIF dialog
+- Core: Breadcrumbs are now using :: as divider instead of image
+- CSS: Column/Colorpack classes (ex: g-column-3, g-wall) moved one level up from ul#g-album-grid to div.g-album-grid-container
+- CSS: Fixed issue with meta data alignment in Simple frame pack
+- CSS: Fixed issue with permission dialog's breadcrumbs alignment
+- CSS: removed left padding for navigator thumbs which was causing image "jumps"
+- CSS: Some images were changed
+- JS: Shadowbox settings moved out of the theme into module itself.
+
+version 3.0.8
+- Fixed issue with allowed sidebar position not properly recognized when used as Default 
+- Fix issue with missing quotes in Admin module
+- Fixed issue with uninitialized variable in admin page
+- Fixed background for view-calendar.png for some color packs
+- CSS: Center content of ThumbNav module. If non default thumb size is used for module, setting may need to be adjusted.
+- CSS: Added new style sheet for iPad support
+
+version 3.0.7
+- ADMIN: Added support for View Mode - Full/Mini (ex: ?viewmode=mini | ?viewmode=full | ?viewmode=default )
+- ADMIN: Paginator position now can be set independently for Album and Photo pages
+- ADMIN: Added Colorbox slideshow detection
+- Theme.info adjusted to match new guidelines
+- CSS: GreyDragon Color Pack - fixed thumb background color issue with GreyDragon Frame Pack
+- CSS: changes to improve Basket Module integration
+- CSS: #g-album-grid element now references framepack used for better interaction between frame and color packs (ex: class="g-slateblue")
+- Fix issue with sidebar not properly displayed in Root Page
+- Fix issue with missing thumb image not being aligned properly in "Actual Aspect Ratio" mode
+
+version 3.0.6
+- Fix: Using Top aligned sidebar causes problem
+
+version 3.0.5
+- ADMIN: Allow hiding sidebar for root pages -> Advanced Options\Root Page\Hide Sidebar
+- ADMIN: Allow breadcrumbs in root page/root album -> Advanced Options\General\Show Breadcrumbs in top album/root page
+- Fixed issue with Calendar not displayed properly when no items are returned
+- CSS: Increased padding for in-page description block
+
+version 3.0.4
+- FP: New framepack - book
+  Please note that if bottom aligned description is used, it need to be the same for both album and photo thumbs.
+- CSS: #g-album-grid-container renamed to .g-album-grid-container
+- CSS: Fixed slight misalignment of 3 level main menu items
+- ADMIN: New position for main menu - Top Bar - top aligned/fixed positioned menu. Useful for admin mode menu
+- ADMIN: Added support for separate option for description position in album thumbs
+
+version 3.0.3
+- ADMIN: Added option for Root Page slideshow delay
+- ADMIN: Added option for Alternative Description for Root Page which overwrites Description from Root album
+- CSS: Fix issue with context menu hotspot z-index in thumbs
+- CSS: Fixed margin in Uploadify dialog to prevent overlap
+- ADMIN: Page cache option has been deprecated. It can be achieved via .htaccess instead
+
+version 3.0.2
+- Wind Color Pack: Fixed issue with missing background image for dialog header
+- CSS: Wind Color Pack: Set dialog background to white
+- ADMIN: Fixed issue of Maintenance group label not being translated
+- Fixed issue with float division for photo page
+- Fixed issue with BBCode in info block not being converted (regression error)
+- Fixed small misalignment of the image with the "Actual" Aspect Ratio Thumb
+- Added CSS class marker for portrait thumb images
+- IE9: Added support for Pinned Site mode and Jump List menu
+
+version 3.0.1
+- ADMIN: Page Header and Footer Text allows BBCode
+- ADMIN: Added support for apple-touch-icon - icon similar to favicon to be used on iPad/iPhone/iPod devices
+- ADMIN: New option - Album Description Display Mode - allowing placement of the description in the album pages
+- ADMIN: Main menu could be now positioned as Top-Left/Bottom-Left aligned
+- ADMIN: Bradcrumbs could be now positioned as Top-Left/Bottom-Left/Bottom-Right or Hidden
+- Added <span> wrappers for Header and Footer texts allowing further CSS manipulation
+- Added support for custom header/footer inclusion - simply drop header.html.php and/or footer.html.php in the views folder and content would be added in the header/footer section
+- Info sidebar block logic synchronized to match default but still allow BBCode
+
+version 3.0.0
+- Due to extensive changes to CSS it is now a major release
+- Rules from screen.css moved into base.css. Screen.css used as loader file only.
+- Introduced better support for RTL
+- Some of the icons moved into ui-icons.png for optimization. Color adjustments for visibility.
+- Added support for frame packs. Included: greydragon (default), simple, android, iphone, iphoto, darkglass
+- Fixed issue with regular wide thumb format not being set/displayed properly
+- Breadcrumb logic extended to take in consideration [visible_title_length] variable value introduced in G3
+- Reordered JS registration to comply with default G3 3.0.1 logic
+- Added some missing translation hooks in Admin area
+- Some Page load optimization
+- Added logic to take in consideration date display format for info module
+- Performed validation and necessary adjustments for IE 9/IE 9 compatibility mode
+- IE Fix CSS is only applied for IE 6. Older versions are no longer supported
+
+version 2.7.9
+- Optimized session handling for colorpack cmd param
+- Removed validation for colorpack presence
+
+version 2.7.8
+- Fixed issue with colorpack detection. Reenabled
+- Fixed issue with sidebar position could be "stuck" when switching from Grey Dragon Wind Theme
+- Fixed introduced error with missing forms.css reference
+- Theme's CSS/JS is combined into session based G3 files
+
+version 2.7.7
+- Adjusted for 3.0.1 release of G3
+- New color pack: blackhawk
+- ADMIN: New sidebar position supported - top (new rules added to colorpacks)
+- CSS: Some clean up for included colorpacks - CSS/image resources, sprite image optimization for sidebar position buttons
+- Added session persistence for colorpack url parameter for demo purposes
+- ADMIN: Prerequisites module check extended to make it more relevant when Root Page is allowed
+- CSS: Sync positions of main menu and breadcrumbs when in alternative header layout format
+- colorpack location validation has been disabled for now until issue is resolved
+
+version 2.7.6
+- ADMIN: "Large" Thumb sizes are removed from Aspect dropdown and managed via "Expanded Aspect Ratio (300px wide)" option
+- ADMIN: New Thumb aspect ratio - Wide/HDTV (16:9), "Actual" aspect is supported in Expanded mode
+- ADMIN: Root Page - new option "Show Gallery Description"
+- Added check if Shadowbox is loaded so that theme's initialization JS does not produce hidden exception
+- Added pointer cursor for clickable overlay area in Root Page until Minislideshow is loaded
+
+version 2.7.5
+- ADMIN: Full Slideshow RSS feed url now being used. This solves some issues with Flash loader and allows creation of custom playlists to be used in the root page
+- Root Page: Fixed issue with Flash Slideshow not being loaded properly
+
+version 2.7.4
+- Root Page: Added "Click to Enter" to indicate clickable state
+- Root Page: Quote is now taken from root album description field. If description is empty, slideshow content is centered.
+- Added branding icons for "gallery 3" and theme/color packs.
+- Fixed issue with page layout for calendar module.
+- Fixed issue with URL parameters not being recognized in some server configurations
+- CSS: Fixed aspect ratio for thumbs. Some css alignments optimization
+- CSS: Turned back on borders for blocks in bottom aligned sidebar
+- ADMIN: New option for Photo Description Display Mode - Overlay Bottom. !!!! Color pack's CSS rules affected.
+- ADMIN: Maintenance section: Added "Reset IPIC Info" (if module is active) and "Purge cache data", some tweaks for "Reset EXIF Info"
+
+version 2.7.3
+- ADMIN: New option - Randomize Thumb Image
+- Missing markup in rootpage.html.php
+- Root Page - set size of the slideshow to auto so it can be managed via CSS
+- Sync page.html.php structure with latest git changes
+- CSS: Fixed styles for progress dialog when invoked from non-admin area
+
+version 2.7.2
+- CSS: Restored visible state of rotation operations for photos
+- JS: To resolve issue with Opera OS, background image need to be set for #g-rootpage-link instead of roller object. Finalization JS for root page slideshow extended to clear background for overlay.
+- Reenabled support for site status messages
+
+version 2.7.1
+- Root Page layout/css extended to allow click on the image while slideshow is still loading
+- ADMIN: Some changes in setting's titles and help
+- Fixed issue with meta data overlay not being shown for some title/meta combinations
+
+version 2.7.0
+- DEV: new url parameter support added - colorpack. Ex: <gallery_url>?colorpack=<name> 
+- ADMIN: 2 to 5 columns layout is now supported. Flex column option moved into column selector. 
+- ADMIN: Added new mode for Description overlay in Album - Overlay Bottom (Static) - places description on the bottom of the thumb as static overlay. Metadata would not be shown. 
+- ADMIN: Metadata Display Mode for Thumbs introduced. [Hide metadata] merged into it. Metadata can now be merged with description. 
+- W3C: resolved some validation errors in album page 
+- CSS: !!! Colorpack !!! - adjusted to reflect changes to thumb description structure 
+- CSS: Changes for columns CSS (.g-column-3/.g-column-4) - moved to list level - several php files also affected 
+- CSS: Fixed issue with re-authenticate dialog layout 
+- CSS: Fixed issue search button in IE7 Compatibility mode for wind color pack 
+- ShadowBox module config settings changed to prevent flickering - enabled dialog animation. Slideshow timeout increased to 7 sec. Updated version of ShadowBox module is available. 
+- CSS: Deprecated styles for ShadowBox Ajax dialogs as they are not supported by the library in Core and color pack references 
+
+version 2.6.3
+- ADMIN: New "Title Display Mode" added - Overlay (Static)
+- CSS: syncronization between colorpacks. Some simplification
+
+version 2.6.2
+- Added support for initial background in the Root Page to be removed as soon as slideshow starts (requires imageblockex 2.1)
+- ADMIN: Added option allowing feed selection for Root Page, Quote text
+- Small changes in color pack and layout for Upload dialog
+- Fixed logic in roopage.html.php to properly construct the link for navigation
+
+version 2.6.0
+- Support for root page added
+- Added borders for main wrapper in Slate Blue color pack to accommodate centered layout
+- Added JS to preload next/prior images in photo pages
+- Added content wrapper for album grid to allow external CSS application - ex: center grid content
+- ALERT! Improved rendering of admin panel. This would break admin panels for any modules which uses the same file by inheritance. Please download updated module distros.
+- Fixed wrong reference to layout_non_ie.css file - not used
+- Removed restrictions for displaying sidebar in satellite pages
+- Fixed status message alignment in Upload dialog
+- Fixed W3C validation error in Photo page markup
+- "controllers" folder deprecated
+                                                 
+version 2.5.1
+- Fixed issue with relative path not being used when changing sidebar display mode
+- ADMIN: Added support for Blend effect for page transitions
+- ADMIN: Added check to identify module collision between FancyBox and ShadowBox
+- ADMIN: New option "Keep Thumb Nav Block on the side" for Photo Pages
+- CSS: small css changes for bottom aligned sidebar positioning
+- CSS: Fix for dialog overlay div to properly position itself and prevent scrollbars to appear without reason
+- CSS: slateblue color pack - make regular text grey
+- CSS: set min height for bottom aligned sidebar
+- CSS: Fixed issue with font size for dialogs in IE8 Compatability mode 
+- Custom layout for tag_block.html.php is depricated
+- Some W3C Validation clean-up
+
+version 2.5.0
+- New colorpack - SlateBlue
+- Added support for bottom aligned Sidebar
+- CSS: opacity in .ui-widget-overlay (forms.css) set to 70
+- CSS: Fixed issue with misallignment of sidebar toolbar area and page header info
+- CSS: Removed left pagging for g-photo element to properly align in the div
+- CSS: Added thumb size restrictions for Image Block module
+- Removed logic to use Shadowbox when showing Exif data
+
+version 2.4.9
+- ADMIN: Top Align Thumb Image option added - do not center thumb image in the view window. Useful for portrait oriented photos.
+- ADMIN: Added a new Advanced option - Relative path to custom.css, if used - allowing inclusion of custom css override
+- Ignore albums when building item list for Fancybox/Shadowbox Slideshow in Photo page. Fix issue with extra item added when start with first item.
+- Fixed issue with not properly sanitized titles for links for Fancybox/Shadowbox Slideshow in Photo page
+- Small adjustment to FancyBox slideshow navigation arrows
+- Force min height requirement for H1/H2 elements
+- Fixed spelling for g-thumlink -> g-thumblink
+- Force size of the thumb link to fill crop area - situation when thumb image is smaller then view area
+- Removed custom layout for User Profile page
+
+version 2.4.8
+- Fixed inverted state of "Disallow Search Engine Indexing (No Bots)
+- Fixed JS syntax incompatibility in IE7/IE8 compatibility mode
+- Fixed display of thumb title and photo description on hover in IE7/IE8 compatibility mode
+- Fixed issue with Dialogs not skinned properly in Carbon/Wind themes
+- Fixed issue with metadata for photo thumbs when Aspect Ratio: Actual Size and Title Display Mode: Bottom
+
+version 2.4.7
+- Fixed issue with some .g-block structures.
+  Fixed issue with avatar not properly aligned in comment section.
+
+version 2.4.6
+- Fixed some issues when strict error reporting is enabled for PHP
+- Fixed background color for description for bottom Display Title Mode (greydragon colorpack)
+- Added support for two new Thumb Sizes - Digital Ex and Film Ex - 300px wide thumbs
+- Fixed issue with buttons in the block "jumping" out
+- Added check in block view to verify that theme is defined
+
+version 2.4.5
+- Min G3 core requirement is set to v.41
+- Fixed issue with Exif dialog data integration
+- Fixed issue with permission dialog
+- CSS: Changes form style management. Fixed issue with breadcrumbs display in dialogs.
+- CSS: Important! Colorpack files are affected
+- Removed no longer required custom Login dialog logic
+- JS cleanup
+
+version 2.4.4
+
+Please drop GD themes folder before uploading a new version
+
+- CSS: screen.css - fixed layout naming change preventing proper display of authentification form when accessing protected areas
+- CSS: Removed some temp files not required by the theme.
+- Support for Fancybox added as alternative to Shadowbox
+- Added support for CalendarView module
+
+version 2.4.3
+- Fixed issue with sidebar mode switch link being incorrect
+- CSS: small style adjustment to neutralize default style effect for the search entry box
+
+version 2.4.2
+- Fixed issue some modules requiring scrollTo() function.
+- Shadowbox is now optional. Special logic added to allow/disallow SB slideshow mode. If disabled, theme would not support full view for images to be in the popup window, new window will be used instead.
+- CSS: Minor improvements for thumb layout in Overlay and Bottom Title Display mode
+- ADMIN: Support for flex column layout added
+- ADMIN Help: Small improvements
+
+version 2.4.1
+- Organize module support reenabled
+- Register module support reenabled
+- Partial support for Shopping Basket module
+- CSS clean-up after dialog engine conversion - round #1
+- Fixed issue with Exif dialog not properly rendered
+
+version 2.4.0
+- Apply g-button style only to forms
+- Fix to properly display videos
+- Fix to account for changes in Comments module
+- Favicon removed from theme's package
+- Fixed uninitialized state warnings of the variables in PHP protected mode
+- Album thumbs now have "lighter" background
+- First draft to change how dialogs are handled - switched to standard code
+- ADMIN: G3 Core version requirement is set to 32
+- ADMIN: Added missing settings initializations
+- ADMIN: Fixed issue with Navigator position setting not being persisted
+- ADMIN: Abstract admin form styles for reuse from regular module admin panels
+- ADMIN: Added option to specify favicon location. If not specified default G3 icon is used.
+
+version 2.3.1
+- Hide Rotate operations for pictures since they are not supported by the theme
+- Added use of common gallery.ajax.js. Fix issue with some Ajax based links.
+- Layout fixes for Translation form overlay
+- Changed CSS styling for buttons to provide unified coverage for buttons and links exposed as buttons.
+- ADMIN: Fixed options group styles in Theme's Admin panel
+- ADMIN: Advanced Settings for Thumbs and Individual Photo are moved into separate sections.
+- ADMIN: New option - display meta data in Photo description section
+- ADMIN: New option/fix - SEO indexing is now allowed by default. In order to prevent your site from being indexed, you can now use "Disallow Search Engine Indexing" option
+
+version 2.3.0
+- Adopted for Gallery 3.0RC2 changes (minor template adjustments, css class name changes, etc.)
+
+version 2.2.1
+- Redesigned Ready event handler for the theme to ensure proper ShadowBox initialization
+- Added support for gallery_dialog() function call used by some 3rd party modules - some sync issues are solved by imposed delay of 1 second
+- GPS module - better action list alignment in the sidebar
+
+version 2.2.0
+- Added support for slideshow mode in Photo Preview
+- Fixed issue with Info side block - missing markup
+- Fixed issue with Upload dialog layout with some resolutions/fonts
+- ADMIN: Added option to hide breadcrumbs
+- ADMIN: Added prerequisite check for Info module - required for Thumb meta data display
+
+version 2.1.7
+- Added support for missing images in the thumbs to allow proper operations with empty albums or albums with broken thumbs
+- Some color optimizations
+- Color improvements for "Add Image" dialog
+- Better support for Basket module
+
+version 2.1.6
+- Wind colorpack adjusted to closer match default Wind theme
+
+version 2.1.5
+- Minor changes in ADMIN infrastructure
+- ADMIN: added check for Kbd Navigation module
+- ADMIN: New color pack - carbon
+
+version 2.1.4
+- Minor refactoring in paginator
+- Added support for keyboard navigation module (http://codex.gallery2.org/Gallery3:Modules:kbd_nav)
+
+version 2.1.3
+- Sidebar restricted to item related pages (album, photo, movie, etc)
+- Fixed issue with bottom border not applied to all instances of H1 tag
+- Min footer size set to 4em
+- ADMIN: "Photo: Description Display Mode" option added
+- ADMIN: Added new maintenance operation - "Reset Exif Info"
+
+version 2.1.2
+- Fixed issue with Album thumbs - empty space under
+- Thumb Item's Title Display Mode expanded to be applied to Item's description in Photo page
+- More documentations in CSS files, some movements
+- Some cleanup for Wind color pack
+- Fixed font name typo in screen.css
+- Fixed "Waiting" roller for Wind theme to match background
+- Added "up" button in navigation
+
+version 2.1.1
+- Increased size of Add photo dialog for better display on some lower resolutions.
+- ADMIN: New option: "Thumb: Item's Title Display Mode" - specifies how to display item's title in thumbs : Overlay Bottom Hide 
+
+version 2.1.0
+- Custom Info Block to include item's description
+- Image is centered when "Actual Size" aspect is used for thumbs
+- Added support for color packs - included: greydragon, wind
+- ADMIN: Improved error handling
+- ADMIN: Disable submit button on click to prevent Dbl-click
+- ADMIN: New option: Enable page cache - adds header marker for page to be cached for 60 seconds
+
+version 2.0.1
+- Enable BBCode/HTML support in individual photo descriptions
+- Fixed main menu overlay issue when in top position
+- Theme's credits moved into dedicated method
+- CSS clean up
+- Comments module layout enhancements
+
+version 2.0.0
+- Major redesign of the gallery flow.
+    - Added caption and metadata (Admin/optional) overlay for thumbs.
+    - Added description overlay in individual Photo view (look for "Learn More" marker).
+    - Based on Admin setting, thumbs are adjusted to fit Digital/Film/Actual size.
+- Attempt to fix issue with JS load latency to prevent unhandled AJAX calls
+- Added code protection for theme initialization procedure
+- ADMIN: Thumb Aspect Ratio option. See help section for more info.
+
+version 1.8.2
+- Increased based font size
+- Layout adjusted to match new settings
+- ADMIN: New option - Place Login Link in the Header 
+
+version 1.8.1
+- ADMIN: small adjustments in layout and help info
+- 3rd party module's related CSS moved into contrib.css
+- Adjust user profile screen to match new layout
+- initial design for calendar module
+
+version 1.8.0
+- ADMIN: Major redesign of the layout. Help section added.
+- ADMIN: New option - Show main menu for guest user
+- Minimum required Gallery version set to 30
+- When configured not to use sidebar, theme is switched into 4 columns layout
+
+version 1.7.6
+- Organize module: CSS improvements
+- Fixed issue with Chrome browser
+
+version 1.7.5
+- ADMIN: Added option to reset theme to default state
+- CSS: some size adjustments for dialogs. Added minimum height for overlay to keep dialogs from shrinking.
+
+version 1.7.4
+- ADMIN: Theme Gallery 3 core requirement changed to v.26
+- ADMIN: Most of theme's settings are documented using element's title attribute - hover over to see a description
+- Edit Permissions form redesigned and enlarged to fit more information
+
+version 1.7.3
+- ADMIN: Default states for the theme options are no longer being stored. Please save theme settings at least once to take advantage of a new functionality.
+- Photo Navigator default position is set to Top Only
+
+version 1.7.2
+- Fix in Uploader dialog to keep items inside respected boxes
+- Organize module support has been abandoned. Please use GWT Organize module instead. Added item in Prerequisites Checklist.
+
+version 1.7.1
+- CSS: Fixed visibility of the "Select Photo" button in "Add photo" dialog
+- CSS: Fixed "ghost" line for navigation buttons when zoomed-in in IE
+- Admin: fixed issue with prerequisite check not detecting deleted modules
+- <theme>/views/support folder deprecated. Logic moved into Theme_View extension class for Theme_View_Core
+- Theme Options Page management, generic Page code and BBCode processor moved into Theme_View class
+- HACK: Info block is not displayed if there is no description for the item
+
+version 1.6.4
+- Admin: Added "Show Sidebar for Albums only" option
+- Admin: added error visibility to the requirements validation list
+- Small CSS adjustments: Fixed footer min size issue when no site credit info is displayed; added space between Credits in the footer and Footer text area.
+- Few missing parts from last git sync
+
+version 1.6.3
+- Kohana 2.4 support
+- Support for Movie files view
+- Admin: Allow hide Sidebar Block header
+
+version 1.6.2
+- Admin: Page navigator option changed to use combobox
+- Admin: Added option to hide item description in albums
+
+version 1.6.2
+- Small CSS adjustments.
+- All operation dialogs should be visible now
+- Context menu: "Rotate 90..." items are removed due to an issue with image quality affected by the operation
+- Context menu: "Choose as the album cover" is now properly handled
+
+version 1.6.1
+- Admin: When allowed sidebar position is "Default Only", don't disregard selected Default position
+- Adjust item's toolbar buttons to align properly when side bar position is fixed
+- BBCode parser improved to support stripping of BBCode for Page title and breadcrumbs
+- Fixed issue with main menu missing class declaration not allowing open dialogs
+- Adjust context dialogs to properly show caption info
+- Caption added to Full size Preview
+- "New Comment" form styled
+- Admin: Option to align main menu to the top and Breadcrumbs to the left
+
+version 1.6.0
+- Admin: Fixed issue with "Rebuild thumbs" option in theme admin
+- Admin: Fixed issue with Item's toolbar not properly aligned in Quirks Mode
+- Exif data dialog Layout changes
+- Item context menu improvements:
+    - Fixed issue with submit logic
+    - Layout fixes for context menu dialogs 
+
+version 1.5.8
+- Admin: First release of the Theme admin option. After theme installation, visit Appearance/Theme
+  Options to configure the theme. If you had older version of the theme, initial setup is also required.
+  The following settings are available:
+    - Rows per album page - theme uses 3 columns layout for pictures, therefore default page_size is computed in x3 increments
+    - Thumb size is restricted to 200 and therefore not available for administration
+    - Mark to build resizes/thumbs - allows force rebuilding of images
+    - Show/Hide top/bottom photo navigators
+    - Specify allowed and default sidebar position
+    - Administrator can now specify Copyright message to display in the footer
+    - Site logo is now default to Gallery 3 logo, but admin can provide a path to custom logo.
+    - Admin module validates Theme's requirements (Shadowbox module need to be installed/active)
+- Sidebar session cookie is set to expire in 365 days
+
+version 1.5.7
+- Status message has been moved into header as popup to prevent obstruction of the main view.
+  jQuery is used to fade it out in 10 sec.
+- Improved logic for dialogs on submit
+- Theme related JS has been moved out of the page.html.php
+
+version 1.5.6
+- Fixed issue with tollbar buttons not properly aligned/shown when page is resized.
+- Copyright info moved into DB. To change default settings add [th_greydragon/copyright] into VARS table.
+
+version 1.5.5
+- CSS fixes.
+- Theme adjusted to be compatible with latest Git.
+- Login links are moved into footer.
+- Pagination module redesigned to support new structure of paging data.
+
+version 1.5.4
+- CSS fixes.
+- Added support for Comments block.
+- Improved support for Modal dialogs.
+
+version 1.5.3
+- Updated to match latest git.
+- Exif menu customization is now part of the theme.
+- Sidebar management button is disabled for current mode.
+
+version 1.5.2
+- Code, layout, css cleanup.
+- New thumbs for buttons.
+- First set of Ajax dialogs is ready and now operational: Login, user info, edit album, exit info.
+- Fixed some browser related issues.
\ No newline at end of file
diff --git a/themes/greydragon/controllers/greydragon.php b/themes/greydragon/controllers/greydragon.php
new file mode 100644
index 0000000..0ecfc4f
--- /dev/null
+++ b/themes/greydragon/controllers/greydragon.php
@@ -0,0 +1,14 @@
+<?
+
+class GreyDragon_Controller extends Controller {
+
+  public function custom_css() {
+
+    // Draw the page.
+//    $template = new Theme_View("gd_custom.css", "other", "Custom_CSS");
+
+    print $template;
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/themes/greydragon/css/base.css b/themes/greydragon/css/base.css
new file mode 100644
index 0000000..735a999
--- /dev/null
+++ b/themes/greydragon/css/base.css
@@ -0,0 +1,322 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules - Main CSS ruleset
+ *
+ * Color rules for font/background/lines can be found in dedicated colorpack files
+ */
+        
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* base.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+body { font-family: Arial, verdana, sans-serif; font-size: 0.9em; }
+
+a { text-decoration: none; outline: none; -moz-outline-style: none; }
+a:focus, a:active, a:hover { text-decoration: none; outline: none; }
+img { border: none; }
+p { text-indent: 0;  }
+ul { list-style: none none; padding-left: 0; }
+
+h1 { font-weight: bold; font-size: 1.1em; padding-bottom: 1px; min-height: 1.1em; }
+h2 { font-weight: bold; font-size: 1.1em; min-height: 1.1em; }
+h3 { font-weight: bold; }
+h4 { font-weight: bold; }
+h5 { font-weight: bold; }
+
+.txtright { text-align: right; }
+.g-metadata { overflow: hidden; }
+.g-avatar { float: right; }
+.g-hide { display: none; }
+
+.ui-icon { display: inline-block; zoom: 1; width: 16px; height: 15px; }
+.ui-icon-first { background-position: -162px -178px; }
+.ui-icon-first-d { background-position: -162px -162px; }
+.ui-icon-prev { background-position: -178px -178px; }
+.ui-icon-prev-d { background-position: -178px -162px; }
+.ui-icon-parent { background-position: -226px -178px; }
+.ui-icon-parent-d { background-position: -226px -162px; }
+.ui-icon-next { background-position: -194px -178px; }
+.ui-icon-next-d { background-position: -194px -162px; }
+.ui-icon-last { background-position: -210px -178px; }
+.ui-icon-last-d { background-position: -210px -162px; }
+.ui-icon-signal-diag { background-position: -16px  -178px; }
+.ui-icon-info { background-position: -16px  -144px; }
+.ui-icon-plus { background-position: -14px  -129px; }
+.ui-icon-minus { background-position: -46px  -129px; }
+.ui-icon-note { background-position: -66px  -98px;  }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-left .ui-icon { float: left; margin-right: .2em; }
+.ui-icon-right .ui-icon { float: right; margin-left: .2em; }
+
+/* base.css - Inline layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-inline li { float: left; }
+
+/* base.css - Header ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-header { height: 90px; padding: 0; font-size: 0.9em; }
+#g-logo { position: absolute; top: 8px; left: 16px; }
+
+.g-breadcrumbs { position: absolute; background-color: transparent; }
+.g-breadcrumbs.g-default     { bottom: 4px; right: 14px; }
+.g-breadcrumbs.g-bottom-left { bottom: 4px; left: 21.4em; }
+.g-breadcrumbs.g-top-right   { top: 4px; right: 14px; }
+.g-breadcrumbs.g-top-left    { top: 4px; left: 21.4em; }
+
+.g-breadcrumbs li { display: inline; } 
+.g-breadcrumbs li.g-first { background-image: none; padding-left: 0; }
+.rtl .g-breadcrumbs .g-first { background-image: none; padding-left: 0; }
+.g-breadcrumbs li.g-active { padding-right: 0; }
+
+#g-header .g-message-block { position: absolute; z-index: 10; min-width: 30em; padding: 0; right: 20em; top: 34px; overflow: hidden; font: bold 9pt Arial, verdana, sans-serif; text-align: center; }
+#g-header #g-login-menu { position: absolute; top: 0.2em; right: 1em; background-color: transparent; display: none; }
+#g-site-status li { padding: .3em .3em .3em 30px; }
+
+/* base.css - Main ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-main { display: block; margin: 0; }
+#g-main-in { display: block; position: relative; }
+
+#g-column-center, #g-column-centerleft { padding: 6px 6px 6px 10px; }
+#g-column-centerfull { padding: 6px 12px 6px 10px; }
+#g-column-centerright { padding: 6px 10px 6px 6px; }
+#g-column-left { padding: 6px 4px 6px 10px; }
+#g-column-right { padding: 6px 10px 6px 4px; }
+
+/* base.css - Footer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-footer { padding: 6px 0 6px 0; zoom: 1; font-size: 0.9em; }
+#g-footer ul { float: left; padding: 0; text-align: left; }
+#g-footer li { padding: 0 0 2px 0; }
+
+#g-footer #g-login-menu { position: absolute; bottom: 0.5em; right: 1em; background-color: transparent; display: none; }
+
+#g-login-menu li { display: inline; padding-left: 1.2em; }
+#g-logout-link { float: none; margin-right: 0; } 
+
+#g-copyright { font-size: x-small; }
+#g-footer #g-footer-rightside { float: right; text-align: right; margin-right: 1em; }
+#g-credits { margin-left: 14px; margin-right: 14px; }
+#g-credits li.g-branding a { float: left; }
+#g-credits .g-first { display: none; }
+#g-gallery-logo { display: block; width: 70px; height: 18px; background: transparent url('../images/gallery.png') no-repeat; }
+#g-theme-logo { display: block; width: 70px; height: 18px; }
+
+/* base.css - Mini Mode ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.viewmode-mini #g-header { height: 2.3em; }
+.viewmode-mini #g-footer { display: none; }
+
+/* base.css - Pagination ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-paginator { display: inline-block; width: 100%; padding: 4px 0 0 0; zoom: 1; }
+.g-paginator li { display: inline; float: left; margin-left: 0; zoom: 1; }
+.g-paginator a { padding: 0; }
+
+.g-paginator .g-pagination { width: 80%; font-size: 0.8em; }
+.g-paginator .g-navigation { text-align: right; width: 20%; }
+
+/* base.css - Album grid ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-album-grid { padding: 6px 0 0 0; width: 100%; display: inline-block; margin: 0px auto; }
+#g-album-grid .g-item { position: relative; float: left; margin: 4px 2px 4px 0; min-width: 212px; zoom: 1; }
+.g-extended #g-album-grid .g-item { min-width: 314px; }
+.g-column-2 #g-album-grid .g-item { width: 48%; margin-right: 0; }
+.g-column-3 #g-album-grid .g-item { width: 30%; margin-right: 0; }
+.g-column-4 #g-album-grid .g-item { width: 23%; margin-right: 0; }
+.g-column-5 #g-album-grid .g-item { width: 18%; margin-right: 0; }
+#g-album-grid .g-item p { text-align: center; }
+#g-album-grid h2 { position: absolute; top: 164px; left: 12px; width: 150px; font: 100%/100% Arial, Helvetica, sans-serif; }
+#g-album-grid h2 a { display: block; margin-top: 4px; font: bold 0.8em Arial, Helvetica, Verdana, Sans-Serif; letter-spacing: 0.1em; text-transform: uppercase; min-height: 2em; }
+
+/* base.css - Thumbs : Common ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-thumbslide { font-size: 0.9em; width: 208px; min-height: 139px; padding-top: 6px; padding-left: 6px; overflow: hidden; text-align: left; }
+.g-thumbtype-sqr .g-thumbslide { height: 208px; }                                                                           
+.g-thumbtype-flm .g-thumbslide { height: 141px; }
+.g-thumbtype-dgt .g-thumbslide { height: 158px; }
+.g-thumbtype-wd  .g-thumbslide  { height: 120px; }
+
+.g-extended .g-thumbslide { width: 308px; }
+.g-extended .g-thumbtype-sqr .g-thumbslide { height: 308px; }
+.g-extended .g-thumbtype-flm .g-thumbslide { height: 207px; }
+.g-extended .g-thumbtype-dgt .g-thumbslide { height: 233px; }
+.g-extended .g-thumbtype-wd  .g-thumbslide { height: 176px; }
+
+.g-thumbcrop { overflow: hidden; position: relative; width: 200px; min-height: 112px; }
+.g-thumbtype-sqr .g-thumbcrop { height: 200px; }
+.g-thumbtype-flm .g-thumbcrop { height: 133px; }
+.g-thumbtype-dgt .g-thumbcrop { height: 150px; }
+.g-thumbtype-wd  .g-thumbcrop { height: 112px; }
+
+.g-extended .g-thumbcrop { width: 300px; }
+.g-extended .g-thumbtype-sqr .g-thumbcrop { height: 300px; }
+.g-extended .g-thumbtype-flm .g-thumbcrop { height: 199px; }
+.g-extended .g-thumbtype-dgt .g-thumbcrop { height: 225px; }
+.g-extended .g-thumbtype-wd  .g-thumbcrop { height: 168px; }
+
+.g-album .g-description strong { padding-left: 16px; }
+
+/* Force size of the link to fill thumbcrop */
+
+.g-thumbcrop a.g-thumblink { display: block; position: relative; min-width: 200px; }
+.g-thumbtype-sqr a.g-thumblink { min-height: 200px; }
+.g-thumbtype-flm a.g-thumblink { min-height: 133px; }
+.g-thumbtype-dgt a.g-thumblink { min-height: 150px; }
+.g-thumbtype-wd  a.g-thumblink { min-height: 112px; }
+
+.g-extended .g-thumbcrop a.g-thumblink { min-width: 300px; }
+.g-extended .g-thumbtype-sqr a.g-thumblink { min-height: 300px; }
+.g-extended .g-thumbtype-flm a.g-thumblink { min-height: 200px; }
+.g-extended .g-thumbtype-dgt a.g-thumblink { min-height: 225px; }
+.g-extended .g-thumbtype-wd  a.g-thumblink { min-height: 168px; }
+
+/* base.css - Thumbs : Overlay ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-thumbslide .g-description { display: none; position: absolute; left: 6px; top: 6px; min-height: 24px; width: 184px; overflow: hidden; z-index: 3; text-align: left; padding: 2px 8px; font-size: 0.85em; margin: 10px 0 1px 11px; }
+.g-extended .g-thumbslide .g-description { width: 284px; }
+.g-thumbslide:hover .g-description { display: block; }
+.g-thumbslide .g-description li { display: inline; padding-right: 0.8em; }
+.g-thumbslide .g-description .g-title { display: block; font-weight: bold; font-size: 1.1em; letter-spacing: 0.1em; text-transform: uppercase; padding-top: 3px; }  
+.g-album .g-thumbslide .g-description .g-title { padding-left: 24px; }
+
+.g-thumbslide .g-description.g-overlay-top    { display: block; }
+.g-thumbslide .g-description.g-overlay-bottom { display: block; top: auto; bottom: 6px; margin-bottom: 10px; }
+
+.g-thumbslide .g-metadata    { display: none; position: absolute; left: 6px; bottom: 6px; padding: 2px 4px 2px 10px; width: 186px; margin: 10px 0 11px 11px; }
+.g-thumbslide .g-metadata li { padding: 0; margin: 0; font-size: 0.9em; }
+.g-extended .g-thumbslide .g-metadata { width: 286px; }
+.g-thumbslide:hover .g-metadata { display: block; }
+
+/* base.css - Thumbs : Expanded View mode ~~~~~~~~~~~~~~*/
+
+.g-expanded .g-thumbslide { font-size: 0.9em; width: 208px; min-height: 139px; padding-top: 6px; padding-left: 6px; line-height: 1.2em; overflow: hidden; }
+.g-thumbtype-sqr.g-expanded .g-thumbslide { height: 238px; }
+.g-thumbtype-flm.g-expanded .g-thumbslide { height: 171px; }
+.g-thumbtype-dgt.g-expanded .g-thumbslide { height: 188px; }
+.g-thumbtype-wd.g-expanded  .g-thumbslide { height: 150px; }
+
+.g-extended .g-expanded .g-thumbslide                { width: 308px; }
+.g-extended .g-thumbtype-sqr.g-expanded .g-thumbslide { height: 346px; }
+.g-extended .g-thumbtype-flm.g-expanded .g-thumbslide { height: 244px; }
+.g-extended .g-thumbtype-dgt.g-expanded .g-thumbslide { height: 270px; }
+.g-extended .g-thumbtype-wd.g-expanded  .g-thumbslide { height: 214px; }
+
+.g-expanded .g-thumbslide .g-description { position: static; display: block; }
+.g-expanded .g-thumbslide .g-description li { display: inline; padding-right: 0.8em; }
+.g-expanded .g-thumbslide .g-description .g-title { display: block; font-weight: bold; font-size: 1.1em; letter-spacing: 0.1em; text-transform: uppercase; }  
+.g-album.g-expanded .g-thumbslide .g-description .g-title { padding-left: 24px; }
+
+.g-expanded .g-thumbslide .g-description.g-overlay-bottom { width: 192px; }
+.g-expanded .g-thumbslide .g-metadata { bottom: 10px; }
+.g-expanded .g-thumbslide .g-metadata li { padding: 0; margin: 0; font-size: 0.9em; }
+.g-expanded .g-thumbslide:hover .g-metadata { display: block; bottom: 40px; }
+ 
+/* base.css - Photo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-item { float: left; height: 100%; width: 100%; }
+#g-photo { padding: 6px 0 6px 0; text-align: center; float: left; height: 100%; width: 100%; }
+div.g-resize { position: relative; left: 50%; float: left; padding: 5px; font-size: 0.9em; }
+div.g-resize>a { float: left; overflow: hidden; }
+div.g-resize>a img { float: left; }
+
+div.g-resize .g-description { display: none; position: absolute; left: 5px; text-align: left; padding: 10px; }
+div.g-resize .g-description strong { display: block; margin-bottom: 5px; text-transform: uppercase; }
+div.g-resize .g-description.g-align-top { top: 0px; margin-top: 5px; }
+div.g-resize .g-description.g-align-bottom { bottom: 4px; }
+div.g-resize .g-description.g-align-static { display: block; }
+div.g-resize:hover .g-description { display: block; }
+
+div.g-resize .g-more { display: block; position: absolute; right: 16px; padding: 4px 8px; }
+div.g-resize:hover .g-more { display: none; visibility: hidden; }
+div.g-resize .g-more.g-align-top { top: 16px; }
+div.g-resize .g-more.g-align-bottom { bottom: 20px; }
+
+.ul-table { text-align: center; margin: 0px auto; padding: 0; list-style-type: none; clear: both; }
+.ul-table li { float: left; text-align: center; } 
+
+#g-info { display: inline-block; width: 100%; }
+#g-info .g-description { margin-top: .4em; margin-bottom: .4em; padding: .5em 1em; }
+#g-movie { padding: 6px 0 6px 6px; position: relative; }
+
+#g-item a.g-movie { display: block; margin: 0 auto; }
+
+.g-description .g-metadata { padding: 0.4em 0 0 0; font-size: 0.8em; }
+.g-description .g-metadata li { display: inline; padding-right: 1em; }
+
+/* base.css - Sidebar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* base.css - Sidebar : Common ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-block { margin-bottom: 4px; padding-bottom: 4px; position: relative; clear: both; } 
+.g-block h2 { padding: 6px 4px 6px 8px; font-size: 1em; }
+.g-block-content { margin: 6px 6px 0 6px; display: block; zoom: 1; }
+
+#g-column-top .g-block, #g-column-bottom .g-block { float: left; clear: none; width: 240px; margin-left: 10px; }
+#g-column-top .g-toolbar, #g-column-bottom .g-toolbar { margin-bottom: 0.5em; }
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { display: none; }
+
+/* base.css - Sidebar : Buttons ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-viewformat { z-index: 5; position: absolute; padding: 0; top: 6px; right: 10px; }
+#g-viewformat li { float: left; margin-right: 2px; }
+#g-viewformat span { display: block; width: 17px; height: 15px; line-height: 1px; text-indent: -900em; background-repeat: no-repeat; }
+#g-viewformat .g-sidebar-left   { background-position: -128px -210px; }
+#g-viewformat .g-sidebar-top    { background-position: -148px -210px; }
+#g-viewformat .g-sidebar-full   { background-position: -168px -210px; }
+#g-viewformat .g-sidebar-right  { background-position: -188px -210px; }
+#g-viewformat .g-sidebar-bottom { background-position: -208px -210px; }
+#g-viewformat .g-sidebar-left:hover,  #g-viewformat .g-sidebar-left.g-current  { background-position: -128px -225px; }
+#g-viewformat .g-sidebar-top:hover,   #g-viewformat .g-sidebar-top.g-current   { background-position: -148px -225px; }
+#g-viewformat .g-sidebar-full:hover,  #g-viewformat .g-sidebar-full.g-current  { background-position: -168px -225px; }
+#g-viewformat .g-sidebar-right:hover, #g-viewformat .g-sidebar-right.g-current { background-position: -188px -225px; }
+#g-viewformat .g-sidebar-bottom:hover,#g-viewformat .g-sidebar-bottom.g-current{ background-position: -208px -225px; }
+
+#g-view-menu { position: absolute; top: 6px; right: 106px; height: 16px; z-index: 5; zoom: 1; margin: 0 0 6px 0; padding: 0 0 4px 0; }
+#g-view-menu.g-buttonset-shift { right: 6px; }
+.g-toolbar { margin: 0 0 4px 0; } 
+.g-menu { margin: 0; padding: 0; text-align: left; }
+.g-menu li { display: inline; }
+
+.g-menu-element,
+.g-menu-link { display: inline; float: left; margin-right: 4px; background-repeat: no-repeat; background-position: center top; }
+
+.g-buttonset .g-menu-link { text-indent: -99999px; width: 22px; height: 15px; overflow: hidden; }
+
+#g-slideshow-link { background-position: -103px -210px; } 
+#g-slideshow-link:hover { background-position: -103px -225px; }
+
+.g-fullsize-link:hover, #g-exifdata-link:hover { background-position: left bottom; }
+
+/* base.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-quote { float: left; width: 300px; padding-top: 6px; font-size: 110%; }
+#g-rootpage-roll  { float: right; text-align: center; z-index: 1; position: relative; width: 800px; height: 540px; overflow: hidden; }
+#g-rootpage-link  { z-index: 10; position: absolute; height: 540px; width: 800px; top: 0; left: 0; cursor: pointer; }
+#g-rootpage-roll span { z-index: 50; display: block; position: absolute; right: 16px; padding: 4px 8px; top: 20px; cursor: pointer; font-size: 0.9em; }
+#g-rootpage-roll.g-full { margin-left: auto; margin-right: auto; float: none; }
+#g-rootpage-slideshow div img { border: 0; }
+
+/* base.css - Large toolbar icons support ~~~~~~~~~~~~~~*/
+
+.g-toolbar-large .g-buttonset .g-menu-link { width: 26px; height: 22px; }
+.g-toolbar-large h1 { line-height: 24px; height: 24px; }
+.g-toolbar-large #g-calendarview-link:hover { background-position: top center; }
+.g-toolbar-large #g-viewformat { top: 9px; }
+
+.g-toolbar-large .g-navigation .ui-icon { width: 23px; height: 22px; }
+.g-toolbar-large .ui-icon-first    { background-position: 0px -240px; }
+.g-toolbar-large .ui-icon-first-d  { background-position: 0px -263px; }
+.g-toolbar-large .ui-icon-prev     { background-position: -23px -240px; }
+.g-toolbar-large .ui-icon-prev-d   { background-position: -23px -263px; }
+.g-toolbar-large .ui-icon-parent   { background-position: -47px -240px; }
+.g-toolbar-large .ui-icon-parent-d { background-position: -47px -263px; }
+.g-toolbar-large .ui-icon-next     { background-position: -70px -240px; }
+.g-toolbar-large .ui-icon-next-d   { background-position: -70px -263px; }
+.g-toolbar-large .ui-icon-last     { background-position: -93px -240px; }
+.g-toolbar-large .ui-icon-last-d   { background-position: -93px -263px; }
+
+/* base.css - Upload dialog ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-status li.g-success { background: url('../images/ico-success.png') transparent no-repeat .4em 50%; }
+#g-add-photos-status li.g-error   { background: url('../images/ico-error.png') transparent no-repeat .4em 50%; color: #f00; }
diff --git a/themes/greydragon/css/colorpacks/blackhawk/css/colors.css b/themes/greydragon/css/colorpacks/blackhawk/css/colors.css
new file mode 100644
index 0000000..5ab71d0
--- /dev/null
+++ b/themes/greydragon/css/colorpacks/blackhawk/css/colors.css
@@ -0,0 +1,169 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: SlateBlue
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #101010; }
+body { color: #8C8C8C; background: #101010; }
+
+h1 { border-bottom: #424242 1px solid; }
+a { color: #6392CF !important; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png') no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-header { border: #424242 1px solid; }
+#g-header .g-message-block { border: 1px #888 solid; background-color: #AAA; color: #000; }
+#g-main { border-left: #424242 1px solid; border-right: #424242 1px solid; }
+.viewmode-mini #g-main { border-bottom: #424242 1px solid; }
+
+#g-footer { font-size: 10px; border: #424242 1px solid; }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top, #g-column-bottom { border-left: #424242 1px solid; border-right: #424242 1px solid; }
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info .g-description { border: #424242 1px solid; }
+
+.g-thumbcrop { border-color: #424142; }
+.g-thumbslide, .g-album .g-thumbslide { background: #212021; border-color: #424142 #000 #000 #424142; }
+.g-thumbslide .g-description { color: #fff; border-top: 1px solid #424142; border-bottom: 1px solid #424142; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-album.g-expanded .g-thumbslide .g-description { background: transparent url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-album .g-thumbslide .g-description { background: #1E1E1E url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-thumbslide .g-metadata { border-top: 1px solid #424142; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-expanded .g-thumbslide .g-metadata { border-top: 1px solid #424142; background: #1E1E1E; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { background: #212021; border-top: 1px solid #424142; border-left: 1px solid #424142; border-right: 1px solid #000; border-bottom: 1px solid #000; }
+div.g-resize .g-description { color: #fff; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #999; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #999; }
+div.g-resize .g-more { border: 1px solid #999; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div#g-movie .g-movie { border: 1px solid #888; padding: 5px; background: #555; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block h2 { border-top: 1px solid #424142; border-left: 1px solid #424142; border-right: 1px solid #000; border-bottom: 1px solid #000; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #424142; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #101415; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #101415 url('../images/section.png') repeat-x; }
+#sb-counter a { color: #fff !important; font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #101010; border: #303030 1px solid; }
+#g-add-photos-status { background-color: #101010; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #888 1px solid; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile .g-avatar { border: 1px solid #888; background: #555; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li a:hover { color: #000000; background-color: #303030; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #303030; border-bottom: #000000 1px solid; }
+#g-site-menu li ul { border: #000000 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #212121; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #303030; }
+
+#g-site-menu.g-bar { border: #000000 1px solid; background-color: #212121; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #181818 none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #303030; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #303030 1px solid; }
+#g-exif-data .g-even { background-color: #404040; }
+#g-exif-data .g-odd { background-color: #303030; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #424242; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #888; background: #555; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #424242; color: #8C8C8C; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #424242; }
+#g-comment-form { border: 1px dotted #424242; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #8C8C8C; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #424242; color: #8C8C8C; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background: url(../images/section.png) repeat-x; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #424242; }
+.ui-widget-content { border: 1px solid #303030; background-color: #101010; color: #8C8C8C; }
+.ui-progressbar .ui-progressbar-value { background: #424242; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/ajax-loading.gif b/themes/greydragon/css/colorpacks/blackhawk/images/ajax-loading.gif
new file mode 100644
index 0000000..0996045
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/ajax-loading.gif differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/colorpack.png b/themes/greydragon/css/colorpacks/blackhawk/images/colorpack.png
new file mode 100644
index 0000000..96f5372
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/colorpack.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/ico-album.png b/themes/greydragon/css/colorpacks/blackhawk/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/ico-album.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/ico-error.png b/themes/greydragon/css/colorpacks/blackhawk/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/ico-error.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/ico-help.png b/themes/greydragon/css/colorpacks/blackhawk/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/ico-help.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/ico-info.png b/themes/greydragon/css/colorpacks/blackhawk/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/ico-info.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/ico-warning.png b/themes/greydragon/css/colorpacks/blackhawk/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/ico-warning.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/loading-large.gif b/themes/greydragon/css/colorpacks/blackhawk/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/loading-large.gif differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/loading-small.gif b/themes/greydragon/css/colorpacks/blackhawk/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/loading-small.gif differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/search.png b/themes/greydragon/css/colorpacks/blackhawk/images/search.png
new file mode 100644
index 0000000..1bfa411
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/search.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/ui-icons.png b/themes/greydragon/css/colorpacks/blackhawk/images/ui-icons.png
new file mode 100644
index 0000000..a71d438
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/ui-icons.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/view-calendar-b.png b/themes/greydragon/css/colorpacks/blackhawk/images/view-calendar-b.png
new file mode 100644
index 0000000..c5a1248
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/view-calendar-b.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/view-calendar.png b/themes/greydragon/css/colorpacks/blackhawk/images/view-calendar.png
new file mode 100644
index 0000000..bd1d03c
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/view-calendar.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/view-comments-b.png b/themes/greydragon/css/colorpacks/blackhawk/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/view-comments-b.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/view-comments.png b/themes/greydragon/css/colorpacks/blackhawk/images/view-comments.png
new file mode 100644
index 0000000..293c587
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/view-comments.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/view-fullsize-b.png b/themes/greydragon/css/colorpacks/blackhawk/images/view-fullsize-b.png
new file mode 100644
index 0000000..f659d79
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/view-fullsize-b.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/view-fullsize.png b/themes/greydragon/css/colorpacks/blackhawk/images/view-fullsize.png
new file mode 100644
index 0000000..ed76257
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/view-fullsize.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/view-info-b.png b/themes/greydragon/css/colorpacks/blackhawk/images/view-info-b.png
new file mode 100644
index 0000000..880d3e8
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/view-info-b.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/view-info-o.png b/themes/greydragon/css/colorpacks/blackhawk/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/view-info-o.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/view-info.png b/themes/greydragon/css/colorpacks/blackhawk/images/view-info.png
new file mode 100644
index 0000000..521439c
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/view-info.png differ
diff --git a/themes/greydragon/css/colorpacks/blackhawk/images/view-slideshow-b.png b/themes/greydragon/css/colorpacks/blackhawk/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon/css/colorpacks/blackhawk/images/view-slideshow-b.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/css/colors.css b/themes/greydragon/css/colorpacks/carbon/css/colors.css
new file mode 100644
index 0000000..618a105
--- /dev/null
+++ b/themes/greydragon/css/colorpacks/carbon/css/colors.css
@@ -0,0 +1,188 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: Carbon
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #333; }
+body { color: #999; background-color: #333; }
+
+h1 { border-bottom: #6f6f6f 1px solid; }
+a { color: #999 !important; font-weight: bold; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png') no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-header .g-message-block { border: 1px #888 solid; background-color: #AAA; color: #000; }
+#g-main { background-color: #3f3f3f; margin-left: 10px; margin-right: 10px; }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top { border-top: #737373 1px solid; }
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info .g-description { border: #6f6f6f 1px solid; }
+
+.g-thumbslide { background: #555; border-color: #303E43; }
+.g-album .g-thumbslide { border-color: #6f6f6f; }
+.g-thumbcrop  { border-color: #303E43; }
+
+.g-thumbslide .g-description { color: #fff; border-top: 1px solid #303e43; border-bottom: 1px solid #303e43; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-album.g-expanded .g-thumbslide .g-description { background: transparent url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-album .g-thumbslide .g-description { background: #3f3f3f url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-thumbslide .g-metadata { border-top: 1px solid #303e43; background: #3f3f3f; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; color: #FFF; }
+.g-expanded .g-thumbslide .g-metadata { border-top: 1px solid #303e43; background: #3f3f3f; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: 1px solid #888; background: #555; }
+div.g-resize .g-description { color: #fff; background: #3f3f3f; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #999; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #999; }
+div.g-resize .g-more { border: 1px solid #999; background: #3f3f3f; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div#g-movie .g-movie { border: 1px solid #888; padding: 5px; background: #555; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block { border: 1px solid #6f6f6f; } 
+
+.g-block h2 { background-color: rgb(51, 51, 51); }
+#g-column-bottom .g-block h2 { background-color: rgb(41, 41, 41); }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #999; background: #3f3f3f; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li a:hover { color: #000000; background-color: #333; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #333; border-bottom: #000000 1px solid; }
+#g-site-menu li ul { border: #000000 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #333; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #ddf2ff; }
+
+#g-site-menu.g-bar { border: #000000 1px solid; background-color: #333; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #333 none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #ddf2ff; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #101415; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background-color: #333; }
+#sb-counter a { color: #fff !important; font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #101010; border: #303030 1px solid; }
+#g-add-photos-button { border: #303030 1px solid; color: #bbb; }
+#g-add-photos-status { background-color: #101010; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile .g-avatar { border: 1px solid #888; background: #555; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li a:hover { color: #000000; background-color: #303030; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #303030; border-bottom: #000000 1px solid; }
+#g-site-menu li ul { border: #000000 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #212121; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #303030; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #181818 none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #303030; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #303030 1px solid; }
+#g-exif-data .g-even { background-color: #404040; }
+#g-exif-data .g-odd { background-color: #303030; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #737373; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #888; background: #555; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #737373; }
+#g-comment-form { border: 1px dotted #737373; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #737373; color: #BBB; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background: url(../images/section.png) repeat-x; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #333 url('../images/section.png') repeat-x; }
+.ui-widget-content { border: 1px solid #303030; background-color: #333; color: #bbb; }
+.ui-progressbar .ui-progressbar-value { background: #737373; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #737373 1px solid; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon/css/colorpacks/carbon/images/ajax-loading.gif b/themes/greydragon/css/colorpacks/carbon/images/ajax-loading.gif
new file mode 100644
index 0000000..0996045
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/ajax-loading.gif differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/colorpack.png b/themes/greydragon/css/colorpacks/carbon/images/colorpack.png
new file mode 100644
index 0000000..bc51d4f
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/colorpack.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/ico-album.png b/themes/greydragon/css/colorpacks/carbon/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/ico-album.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/ico-error.png b/themes/greydragon/css/colorpacks/carbon/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/ico-error.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/ico-help.png b/themes/greydragon/css/colorpacks/carbon/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/ico-help.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/ico-info.png b/themes/greydragon/css/colorpacks/carbon/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/ico-info.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/ico-warning.png b/themes/greydragon/css/colorpacks/carbon/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/ico-warning.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/loading-large.gif b/themes/greydragon/css/colorpacks/carbon/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/loading-large.gif differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/loading-small.gif b/themes/greydragon/css/colorpacks/carbon/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/loading-small.gif differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/search.png b/themes/greydragon/css/colorpacks/carbon/images/search.png
new file mode 100644
index 0000000..1bfa411
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/search.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/section.png b/themes/greydragon/css/colorpacks/carbon/images/section.png
new file mode 100644
index 0000000..8180ecb
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/section.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/ui-icons.png b/themes/greydragon/css/colorpacks/carbon/images/ui-icons.png
new file mode 100644
index 0000000..ef92612
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/ui-icons.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/view-calendar-b.png b/themes/greydragon/css/colorpacks/carbon/images/view-calendar-b.png
new file mode 100644
index 0000000..c5a1248
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/view-calendar-b.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/view-calendar.png b/themes/greydragon/css/colorpacks/carbon/images/view-calendar.png
new file mode 100644
index 0000000..bd1d03c
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/view-calendar.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/view-comments-b.png b/themes/greydragon/css/colorpacks/carbon/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/view-comments-b.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/view-comments.png b/themes/greydragon/css/colorpacks/carbon/images/view-comments.png
new file mode 100644
index 0000000..293c587
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/view-comments.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/view-fullsize-b.png b/themes/greydragon/css/colorpacks/carbon/images/view-fullsize-b.png
new file mode 100644
index 0000000..f659d79
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/view-fullsize-b.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/view-fullsize.png b/themes/greydragon/css/colorpacks/carbon/images/view-fullsize.png
new file mode 100644
index 0000000..ed76257
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/view-fullsize.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/view-info-b.png b/themes/greydragon/css/colorpacks/carbon/images/view-info-b.png
new file mode 100644
index 0000000..880d3e8
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/view-info-b.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/view-info-o.png b/themes/greydragon/css/colorpacks/carbon/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/view-info-o.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/view-info.png b/themes/greydragon/css/colorpacks/carbon/images/view-info.png
new file mode 100644
index 0000000..521439c
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/view-info.png differ
diff --git a/themes/greydragon/css/colorpacks/carbon/images/view-slideshow-b.png b/themes/greydragon/css/colorpacks/carbon/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon/css/colorpacks/carbon/images/view-slideshow-b.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/css/colors.css b/themes/greydragon/css/colorpacks/greydragon/css/colors.css
new file mode 100644
index 0000000..23fb5eb
--- /dev/null
+++ b/themes/greydragon/css/colorpacks/greydragon/css/colors.css
@@ -0,0 +1,173 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: GreyDragon - Default color pack
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #1A2022; }
+body { color: #BBB; background: #1A2022; }
+
+h1 { border-bottom: #737373 1px solid; }
+a { color: #6392CF !important; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png')  no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-header { border-left: #10151c 1px solid; border-right: #10151c 1px solid; background: url(../images/background-top.gif) #1A2022 repeat-x; }
+#g-header .g-message-block { border: 1px #888 solid; background-color: #AAA; color: #000; }
+#g-main { border-left: #10151c 1px solid; border-right: #10151c 1px solid; background: url(../images/background-bottom.gif) #1A2022 repeat-x; }
+.viewmode-mini #g-main { border-bottom: #10151c 1px solid; }
+#g-footer { background: url(../images/footer.png) #1A2022 repeat-x top !important; }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top { background: url(../images/background-bottom.gif) #1A2022 repeat-x; border: #10151C 1px solid; }
+#g-column-bottom { background-color: #1a2022; border: #10151C 1px solid; }
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info .g-description { border: #737373 1px solid; }
+
+.g-thumbslide { background: #1E1E1E url('../images/image-thumb.gif') repeat-x; border-color: #303E43; }
+.g-album .g-thumbslide { border-color: #43565B; }
+.g-thumbcrop  { border-color: #303E43; }
+.g-thumbslide .g-description { color: #fff; border-top: 1px solid #303e43; border-bottom: 1px solid #303e43; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-album.g-expanded .g-thumbslide .g-description { background: transparent url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-album .g-thumbslide .g-description { background: #1E1E1E url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-thumbslide .g-metadata { border-top: 1px solid #303e43; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-expanded .g-thumbslide .g-metadata { border-top: 1px solid #303e43; background: #1E1E1E; }
+.g-album .g-thumbslide, .g-photo .g-thumbslide { background-color: #1E1E1E; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: 1px solid #888; background: #555; }
+div.g-resize .g-description { color: #fff; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #999; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #999; }
+div.g-resize .g-more { border: 1px solid #999; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div#g-movie .g-movie { border: 1px solid #888; padding: 5px; background: #555; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block { border: 1px solid #737373; background-color: #101415; } 
+.g-block h2 { background: url(../images/section.png) repeat-x; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #999; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background: #101415 url('../images/ajax-loading.gif') no-repeat center center; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #101415 url('../images/section.png') repeat-x; }
+#sb-counter a { color: #fff !important; font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #101010; border: #303030 1px solid; }
+#ag-add-photos-button { border: #303030 1px solid; color: #bbb; }
+#g-add-photos-status { background-color: #101010; border: #303030 1px solid; }
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile .g-avatar { border: 1px solid #888; background: #555; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li a:hover { color: #000000; background-color: #303030; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #303030; border-bottom: #000000 1px solid; }
+#g-site-menu li ul { border: #000000 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #212121; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #303030; }
+
+#g-site-menu.g-bar { border: #000000 1px solid; background-color: #212121; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #181818 none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #303030; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #303030 1px solid; }
+#g-exif-data .g-even { background-color: #404040; }
+#g-exif-data .g-odd { background-color: #303030; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #737373; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #888; background: #555; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #737373; }
+#g-comment-form { border: 1px dotted #737373; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #737373; color: #BBB; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background: url(../images/section.png) repeat-x; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #101415 url('../images/section.png') repeat-x; }
+.ui-widget-content { border: 1px solid #303030; background-color: #1a2022; color: #bbb; }
+.ui-progressbar .ui-progressbar-value { background: #737373; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #888 1px solid; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/ajax-loading.gif b/themes/greydragon/css/colorpacks/greydragon/images/ajax-loading.gif
new file mode 100644
index 0000000..0996045
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/ajax-loading.gif differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/background-bottom.gif b/themes/greydragon/css/colorpacks/greydragon/images/background-bottom.gif
new file mode 100644
index 0000000..1f675f3
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/background-bottom.gif differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/background-top.gif b/themes/greydragon/css/colorpacks/greydragon/images/background-top.gif
new file mode 100644
index 0000000..ec70a64
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/background-top.gif differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/background.gif b/themes/greydragon/css/colorpacks/greydragon/images/background.gif
new file mode 100644
index 0000000..b808356
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/background.gif differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/colorpack.png b/themes/greydragon/css/colorpacks/greydragon/images/colorpack.png
new file mode 100644
index 0000000..b4bd4ca
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/colorpack.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/footer.png b/themes/greydragon/css/colorpacks/greydragon/images/footer.png
new file mode 100644
index 0000000..04d5ee5
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/footer.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/ico-album.png b/themes/greydragon/css/colorpacks/greydragon/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/ico-album.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/ico-error.png b/themes/greydragon/css/colorpacks/greydragon/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/ico-error.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/ico-help.png b/themes/greydragon/css/colorpacks/greydragon/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/ico-help.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/ico-info.png b/themes/greydragon/css/colorpacks/greydragon/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/ico-info.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/ico-warning.png b/themes/greydragon/css/colorpacks/greydragon/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/ico-warning.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/image-thumb.gif b/themes/greydragon/css/colorpacks/greydragon/images/image-thumb.gif
new file mode 100644
index 0000000..bc3a192
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/image-thumb.gif differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/loading-large.gif b/themes/greydragon/css/colorpacks/greydragon/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/loading-large.gif differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/loading-small.gif b/themes/greydragon/css/colorpacks/greydragon/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/loading-small.gif differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/search.png b/themes/greydragon/css/colorpacks/greydragon/images/search.png
new file mode 100644
index 0000000..1bfa411
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/search.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/section.png b/themes/greydragon/css/colorpacks/greydragon/images/section.png
new file mode 100644
index 0000000..8180ecb
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/section.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/ui-icons.png b/themes/greydragon/css/colorpacks/greydragon/images/ui-icons.png
new file mode 100644
index 0000000..41ce8ff
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/ui-icons.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/view-calendar-b.png b/themes/greydragon/css/colorpacks/greydragon/images/view-calendar-b.png
new file mode 100644
index 0000000..c5a1248
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/view-calendar-b.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/view-calendar.png b/themes/greydragon/css/colorpacks/greydragon/images/view-calendar.png
new file mode 100644
index 0000000..bd1d03c
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/view-calendar.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/view-comments-b.png b/themes/greydragon/css/colorpacks/greydragon/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/view-comments-b.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/view-comments.png b/themes/greydragon/css/colorpacks/greydragon/images/view-comments.png
new file mode 100644
index 0000000..293c587
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/view-comments.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/view-fullsize-b.png b/themes/greydragon/css/colorpacks/greydragon/images/view-fullsize-b.png
new file mode 100644
index 0000000..f659d79
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/view-fullsize-b.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/view-fullsize.png b/themes/greydragon/css/colorpacks/greydragon/images/view-fullsize.png
new file mode 100644
index 0000000..ed76257
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/view-fullsize.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/view-info-b.png b/themes/greydragon/css/colorpacks/greydragon/images/view-info-b.png
new file mode 100644
index 0000000..880d3e8
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/view-info-b.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/view-info-o.png b/themes/greydragon/css/colorpacks/greydragon/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/view-info-o.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/view-info.png b/themes/greydragon/css/colorpacks/greydragon/images/view-info.png
new file mode 100644
index 0000000..521439c
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/view-info.png differ
diff --git a/themes/greydragon/css/colorpacks/greydragon/images/view-slideshow-b.png b/themes/greydragon/css/colorpacks/greydragon/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon/css/colorpacks/greydragon/images/view-slideshow-b.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/css/colors.css b/themes/greydragon/css/colorpacks/roundrobin/css/colors.css
new file mode 100644
index 0000000..6878554
--- /dev/null
+++ b/themes/greydragon/css/colorpacks/roundrobin/css/colors.css
@@ -0,0 +1,192 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: Wind - White Hawk color pack
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #FFFFFF; }
+body { color: #555; margin-top: 1em; padding-left: 0px; padding-right: 0px; background: transparent url(../images/bg-body.jpg) top left; border-radius: 10px; box-shadow: 4px 4px 12px #333; }
+                                                                               
+a { color: #555 !important }
+a:hover { text-decoration: underline; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png') no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-main-in { overflow: visible; }
+#g-header { border-bottom: #050505 1px solid; background: transparent url(../images/bg-header.jpg) repeat-x top left; border-top-left-radius: 10px; border-top-right-radius: 10px; }
+#g-header .g-message-block { border: 1px #ccc solid; color: #000; }
+#g-footer { border-top: #050505 1px solid; background: transparent url(../images/bg-header.jpg) repeat-x top left; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; }
+
+#g-column-left  { position: relative; float: left; right: 40px; top: 16px; background: transparent url(../images/bg-header.jpg) top left; border-radius: 6px; padding-top: 4px; box-shadow: 4px 4px 12px #333; }
+#g-column-right { position: relative; float: right; left: 40px; top: 16px; background: transparent url(../images/bg-header.jpg) top left; border-radius: 6px; padding-top: 4px; box-shadow: 4px 4px 12px #333; }
+
+.g-sidebar-left #g-column-centerright { position: relative; left: -16px; }
+.g-sidebar-left #g-view-menu { right: 120px; }
+.g-sidebar-left #g-viewformat { right: 24px; }
+
+.g-sidebar-right #g-column-centerleft { position: relative; left: 16px; }
+.g-sidebar-right #g-view-menu { top: 22px; }
+.g-sidebar-right #g-viewformat { top: 22px; }
+.g-toolbar-large.g-sidebar-right #g-viewformat { top: 26px; }
+
+#g-gallery-logo { background-image: url('../images/gallery.png'); }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+#g-rootpage.g-sidebar-left #g-column-centerright,
+#g-rootpage.g-sidebar-right #g-column-centerleft { left: 0px; padding-left: 26px; }
+#g-header #g-login-menu { top: 0.6em; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info h1, #g-album-header h1 { border-bottom: #ccc 1px solid; }
+#g-info .g-description { border: #ccc 1px solid; }
+
+.g-thumbslide { border-color: #ccc; }
+.g-album .g-thumbslide { border-color: #ccc; }
+.g-thumbcrop  { border-color: #ccc; }
+                                                                                                                 
+.g-default  .g-thumbslide .g-description { color: #000; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-expanded .g-thumbslide .g-description { color: #fff; background: transparent; border: none; }
+.g-album    .g-thumbslide .g-description { background-image: url(../images/ico-album.png); background-repeat: no-repeat; background-position: 8px 4px; }
+.g-thumbslide .g-metadata { border-top: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: 1px solid #ccc; }
+div.g-resize .g-description { color: #000; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #ccc; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #ccc; }
+div.g-resize .g-more { border: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div#g-movie .g-movie { border: 1px solid #ccc; padding: 5px; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block {  } 
+.g-block h2 { border-bottom: 1px solid #ccc; background: rgba(255, 255, 255, 0.5); border-radius: 5px; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #fff; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #e8e8e8; color: #000; }
+#sb-title-inner { color: #000; }
+#sb-counter a { font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #fff; border: #303030 1px solid; }
+#g-add-photos-button { border: #303030 1px solid; }
+#g-add-photos-status { background-color: #fff; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile h1 { border-bottom: #ccc 1px solid; }
+#g-user-profile .g-avatar { border: 1px solid #ccc; background: #fff; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; color: #000; }
+#g-site-menu li { background-color: #ccc; }
+#g-site-menu li ul { border: #ccc 1px solid; }
+#g-site-menu li ul li { border: #ccc 0px solid; background-color: #ccc; }
+
+#g-site-menu>ul>li { background-color: transparent; }
+
+#g-site-menu.g-bar { border: #ccc 1px solid; background-color: #ccc; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #e8e8e8 none; border: 1px #ccc solid; }
+.g-item .g-context-menu li li a:hover { background-color: #e8e8e8; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #ccc 1px solid; }
+#g-exif-data .g-even { background-color: #e8e8e8; }
+#g-exif-data .g-odd { background-color: #FFFFFF; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #ccc; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #ccc; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #ccc; }
+#g-comment-form { border: 1px dotted #ccc; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form.g-short-form li { margin-left: -2px !important; }
+#g-quick-search-form input[type="text"]   { background-color: #FFF; border: 1px solid #ccc; color: #666;  border-top-left-radius: 4px; border-bottom-left-radius: 4px; }
+#ag-quick-search-form input[type="submit"] { border: #c5dbec 1px solid; text-indent: 0; width: auto; height: auto; font: 80% arial, helvetica, clean, sans-serif; font-weight: bold; padding-top: 3px; padding-bottom: 3px; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+#g-search-results h1 { border-bottom: #ccc 1px solid; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background-color: #e8e8e8; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #e8e8e8; color: #666666; }
+.ui-widget-content { border: 1px solid #303030; background-color: #fff; color: #000; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; background: #303030; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #ccc 1px solid; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/ajax-loading.gif b/themes/greydragon/css/colorpacks/roundrobin/images/ajax-loading.gif
new file mode 100644
index 0000000..53dd589
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/ajax-loading.gif differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/bg-body.jpg b/themes/greydragon/css/colorpacks/roundrobin/images/bg-body.jpg
new file mode 100644
index 0000000..08f519b
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/bg-body.jpg differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/bg-header.jpg b/themes/greydragon/css/colorpacks/roundrobin/images/bg-header.jpg
new file mode 100644
index 0000000..f33f0c6
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/bg-header.jpg differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/colorpack.png b/themes/greydragon/css/colorpacks/roundrobin/images/colorpack.png
new file mode 100644
index 0000000..12fea30
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/colorpack.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/gallery.png b/themes/greydragon/css/colorpacks/roundrobin/images/gallery.png
new file mode 100644
index 0000000..9ee765c
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/gallery.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/ico-album.png b/themes/greydragon/css/colorpacks/roundrobin/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/ico-album.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/ico-error.png b/themes/greydragon/css/colorpacks/roundrobin/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/ico-error.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/ico-help.png b/themes/greydragon/css/colorpacks/roundrobin/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/ico-help.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/ico-info.png b/themes/greydragon/css/colorpacks/roundrobin/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/ico-info.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/ico-warning.png b/themes/greydragon/css/colorpacks/roundrobin/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/ico-warning.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/loading-large.gif b/themes/greydragon/css/colorpacks/roundrobin/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/loading-large.gif differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/loading-small.gif b/themes/greydragon/css/colorpacks/roundrobin/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/loading-small.gif differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/search.png b/themes/greydragon/css/colorpacks/roundrobin/images/search.png
new file mode 100644
index 0000000..d9592d8
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/search.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/ui-icons.png b/themes/greydragon/css/colorpacks/roundrobin/images/ui-icons.png
new file mode 100644
index 0000000..4082a0e
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/ui-icons.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/view-calendar-b.png b/themes/greydragon/css/colorpacks/roundrobin/images/view-calendar-b.png
new file mode 100644
index 0000000..f3ab6aa
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/view-calendar-b.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/view-calendar.png b/themes/greydragon/css/colorpacks/roundrobin/images/view-calendar.png
new file mode 100644
index 0000000..a4d038a
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/view-calendar.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/view-comments-b.png b/themes/greydragon/css/colorpacks/roundrobin/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/view-comments-b.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/view-comments.png b/themes/greydragon/css/colorpacks/roundrobin/images/view-comments.png
new file mode 100644
index 0000000..5aca071
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/view-comments.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/view-fullsize-b.png b/themes/greydragon/css/colorpacks/roundrobin/images/view-fullsize-b.png
new file mode 100644
index 0000000..fad5e53
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/view-fullsize-b.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/view-fullsize.png b/themes/greydragon/css/colorpacks/roundrobin/images/view-fullsize.png
new file mode 100644
index 0000000..cc4fbba
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/view-fullsize.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/view-info-b.png b/themes/greydragon/css/colorpacks/roundrobin/images/view-info-b.png
new file mode 100644
index 0000000..90f1bb4
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/view-info-b.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/view-info-o.png b/themes/greydragon/css/colorpacks/roundrobin/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/view-info-o.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/view-info.png b/themes/greydragon/css/colorpacks/roundrobin/images/view-info.png
new file mode 100644
index 0000000..4bdb724
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/view-info.png differ
diff --git a/themes/greydragon/css/colorpacks/roundrobin/images/view-slideshow-b.png b/themes/greydragon/css/colorpacks/roundrobin/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon/css/colorpacks/roundrobin/images/view-slideshow-b.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/css/colors.css b/themes/greydragon/css/colorpacks/slateblue/css/colors.css
new file mode 100644
index 0000000..c684319
--- /dev/null
+++ b/themes/greydragon/css/colorpacks/slateblue/css/colors.css
@@ -0,0 +1,176 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: SlateBlue
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #1c242e; }
+body { color: #BBB; background: #1c242e; }
+
+h1 { border-bottom: #737373 1px solid; }
+a { color: #6392CF !important; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png')  no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-header { border-left: #10151c 1px solid; border-right: #10151c 1px solid; background: url(../images/background.jpg) #1c242e repeat-x; }
+.viewmode-mini #g-header { border-bottom: #10151c 1px solid; }
+#g-header .g-message-block { border: 1px #888 solid; background-color: #AAA; color: #000; }
+#g-main { border-left: #10151c 1px solid; border-right: #10151c 1px solid; }
+.viewmode-mini #g-main { border-bottom: #10151c 1px solid; }
+#g-footer { background: #000; font-size: 10px; }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top, #g-column-bottom { background-color: #1a1e27; border: #10151C 1px solid; border-top: none;}
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info .g-description { border: #10151c 1px solid; background-color: #1a1e27; }
+
+.g-thumbslide { border-color: #303E43; }
+.g-album .g-thumbslide { border-color: #43565B; }
+.g-thumbcrop  { border-color: #303E43; }
+
+.g-default  .g-thumbslide .g-description { color: #fff; background: #1E1E1E; border-top: 1px solid #303e43; border-bottom: 1px solid #303e43; opacity:.85; -ms-filter: "alpha (opacity=85)"; filter: alpha (opacity=85);  }
+.g-expanded .g-thumbslide .g-description { color: #fff; background: transparent; border: none; }
+.g-album .g-thumbslide .g-description { background-image: url(../images/ico-album.png); background-repeat: no-repeat; background-position: 8px 4px; }
+
+.g-thumbslide .g-metadata { border-top: 1px solid #303e43; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+#g-album-grid.g-panel .g-album .g-thumbslide, #g-album-grid.g-panel .g-thumbslide { border-width: 1px; border-style: solid; border-left-color: #666; border-top-color: #666; border-right-color: #10151C; border-bottom-color: #10151C; }
+// #g-album-grid.g-panel .g-album .g-thumbslide, #g-album-grid.g-panel .g-thumbslide { border-width: 1px; border-style: solid; border-left-color: #666; border-top-color: #666; border-right-color: #202020; border-bottom-color: #202020; }
+
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: #10151c 1px solid; background: #4a4e67; }
+div.g-resize .g-description { color: #fff; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #999; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #999; }
+div.g-resize .g-more { border: 1px solid #999; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div#g-movie .g-movie { border: 1px solid #888; padding: 5px; background: #555; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block { border-width: 1px; border-style: solid; border-left-color: #303e43; border-top-color: #303e43; border-right-color: #10151C; border-bottom-color: #10151C; background-color: #1a1e27; } 
+.g-block h2 { background: #1c242e; border-bottom: #273444 1px solid; border-top: #273444 1px solid; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #999; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #101415; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #101415 url('../images/section.png') repeat-x; }
+#sb-counter a { color: #fff !important; font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #101010; border: #303030 1px solid; }
+#g-add-photos-status { background-color: #101010; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #888 1px solid; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile .g-avatar { border: 1px solid #888; background: #555; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li a:hover { color: #000000; background-color: #303030; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #303030; border-bottom: #000000 1px solid; }
+#g-site-menu li ul { border: #000000 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #212121; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #303030; }
+
+#g-site-menu.g-bar { border: #000000 1px solid; background-color: #212121; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #181818 none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #303030; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #303030 1px solid; }
+#g-exif-data .g-even { background-color: #404040; }
+#g-exif-data .g-odd { background-color: #303030; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #737373; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #888; background: #555; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #737373; }
+#g-comment-form { border: 1px dotted #737373; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #737373; color: #BBB; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background: url(../images/section.png) repeat-x; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #101415 url('../images/section.png') repeat-x; }
+.ui-widget-content { border: 1px solid #303030; background-color: #1a2022; color: #bbb; }
+.ui-progressbar .ui-progressbar-value { background: #737373; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/ajax-loading.gif b/themes/greydragon/css/colorpacks/slateblue/images/ajax-loading.gif
new file mode 100644
index 0000000..0996045
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/ajax-loading.gif differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/background.jpg b/themes/greydragon/css/colorpacks/slateblue/images/background.jpg
new file mode 100644
index 0000000..7ec958a
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/background.jpg differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/colorpack.png b/themes/greydragon/css/colorpacks/slateblue/images/colorpack.png
new file mode 100644
index 0000000..d3fd993
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/colorpack.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/footer.png b/themes/greydragon/css/colorpacks/slateblue/images/footer.png
new file mode 100644
index 0000000..04d5ee5
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/footer.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/ico-album.png b/themes/greydragon/css/colorpacks/slateblue/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/ico-album.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/ico-error.png b/themes/greydragon/css/colorpacks/slateblue/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/ico-error.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/ico-help.png b/themes/greydragon/css/colorpacks/slateblue/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/ico-help.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/ico-info.png b/themes/greydragon/css/colorpacks/slateblue/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/ico-info.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/ico-warning.png b/themes/greydragon/css/colorpacks/slateblue/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/ico-warning.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/loading-large.gif b/themes/greydragon/css/colorpacks/slateblue/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/loading-large.gif differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/loading-small.gif b/themes/greydragon/css/colorpacks/slateblue/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/loading-small.gif differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/search.png b/themes/greydragon/css/colorpacks/slateblue/images/search.png
new file mode 100644
index 0000000..1bfa411
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/search.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/section.png b/themes/greydragon/css/colorpacks/slateblue/images/section.png
new file mode 100644
index 0000000..8180ecb
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/section.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/ui-icons.png b/themes/greydragon/css/colorpacks/slateblue/images/ui-icons.png
new file mode 100644
index 0000000..41ce8ff
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/ui-icons.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/view-calendar-b.png b/themes/greydragon/css/colorpacks/slateblue/images/view-calendar-b.png
new file mode 100644
index 0000000..c5a1248
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/view-calendar-b.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/view-calendar.png b/themes/greydragon/css/colorpacks/slateblue/images/view-calendar.png
new file mode 100644
index 0000000..bd1d03c
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/view-calendar.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/view-comments-b.png b/themes/greydragon/css/colorpacks/slateblue/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/view-comments-b.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/view-comments.png b/themes/greydragon/css/colorpacks/slateblue/images/view-comments.png
new file mode 100644
index 0000000..293c587
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/view-comments.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/view-fullsize-b.png b/themes/greydragon/css/colorpacks/slateblue/images/view-fullsize-b.png
new file mode 100644
index 0000000..f659d79
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/view-fullsize-b.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/view-fullsize.png b/themes/greydragon/css/colorpacks/slateblue/images/view-fullsize.png
new file mode 100644
index 0000000..ed76257
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/view-fullsize.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/view-info-b.png b/themes/greydragon/css/colorpacks/slateblue/images/view-info-b.png
new file mode 100644
index 0000000..880d3e8
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/view-info-b.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/view-info-o.png b/themes/greydragon/css/colorpacks/slateblue/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/view-info-o.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/view-info.png b/themes/greydragon/css/colorpacks/slateblue/images/view-info.png
new file mode 100644
index 0000000..521439c
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/view-info.png differ
diff --git a/themes/greydragon/css/colorpacks/slateblue/images/view-slideshow-b.png b/themes/greydragon/css/colorpacks/slateblue/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon/css/colorpacks/slateblue/images/view-slideshow-b.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/css/colors.css b/themes/greydragon/css/colorpacks/whitehawk/css/colors.css
new file mode 100644
index 0000000..cd02f40
--- /dev/null
+++ b/themes/greydragon/css/colorpacks/whitehawk/css/colors.css
@@ -0,0 +1,172 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: Wind - White Hawk color pack
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #FFFFFF; }
+body { color: #666666; padding-left: 10px; padding-right: 10px; }
+                                                                               
+a { color: #666666 !important }
+a:hover { text-decoration: underline; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png') no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-header { border-bottom: #ccc 1px solid; }
+#g-header .g-message-block { border: 1px #ccc solid; color: #000; }
+#g-footer { border-top: #ccc 1px solid; }
+
+#g-gallery-logo { background-image: url('../images/gallery.png'); }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info h1, #g-album-header h1 { border-bottom: #ccc 1px solid; }
+#g-info .g-description { border: #ccc 1px solid; }
+
+.g-thumbslide { border-color: #ccc; }
+.g-album .g-thumbslide { border-color: #ccc; }
+.g-thumbcrop  { border-color: #ccc; }
+                                                                                                                 
+.g-default  .g-thumbslide .g-description { color: #000; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-expanded .g-thumbslide .g-description { color: #fff; background: transparent; border: none; }
+.g-album    .g-thumbslide .g-description { background-image: url(../images/ico-album.png); background-repeat: no-repeat; background-position: 8px 4px; }
+.g-thumbslide .g-metadata { border-top: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: 1px solid #ccc; }
+div.g-resize .g-description { color: #000; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #ccc; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #ccc; }
+div.g-resize .g-more { border: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div#g-movie .g-movie { border: 1px solid #ccc; padding: 5px; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block { border: 1px solid #ccc; } 
+.g-block h2 { border-bottom: 1px solid #ccc; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #fff; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #e8e8e8; color: #000; }
+#sb-title-inner { color: #000; }
+#sb-counter a { font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #fff; border: #303030 1px solid; }
+#g-add-photos-button { border: #303030 1px solid; }
+#g-add-photos-status { background-color: #fff; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile h1 { border-bottom: #ccc 1px solid; }
+#g-user-profile .g-avatar { border: 1px solid #ccc; background: #fff; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li { background-color: #FFFFFF; }
+#g-site-menu li ul { border: #ccc 1px solid; }
+#g-site-menu li ul li { border: #ccc 0px solid; background-color: #FFFFFF; }
+
+#g-site-menu.g-bar { border: #ccc 1px solid; background-color: #FFFFFF; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #e8e8e8 none; border: 1px #ccc solid; }
+.g-item .g-context-menu li li a:hover { background-color: #e8e8e8; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #ccc 1px solid; }
+#g-exif-data .g-even { background-color: #e8e8e8; }
+#g-exif-data .g-odd { background-color: #FFFFFF; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #ccc; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #ccc; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #ccc; }
+#g-comment-form { border: 1px dotted #ccc; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #ccc; color: #666;  }
+#ag-quick-search-form input[type="submit"] { border: #c5dbec 1px solid; text-indent: 0; width: auto; height: auto; font: 80% arial, helvetica, clean, sans-serif; font-weight: bold; padding-top: 3px; padding-bottom: 3px; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+#g-search-results h1 { border-bottom: #ccc 1px solid; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background-color: #e8e8e8; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #e8e8e8; color: #666666; }
+.ui-widget-content { border: 1px solid #303030; background-color: #fff; color: #000; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; background: #303030; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #ccc 1px solid; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/ajax-loading.gif b/themes/greydragon/css/colorpacks/whitehawk/images/ajax-loading.gif
new file mode 100644
index 0000000..53dd589
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/ajax-loading.gif differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/colorpack.png b/themes/greydragon/css/colorpacks/whitehawk/images/colorpack.png
new file mode 100644
index 0000000..3b7afef
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/colorpack.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/gallery.png b/themes/greydragon/css/colorpacks/whitehawk/images/gallery.png
new file mode 100644
index 0000000..3ba425d
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/gallery.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/ico-album.png b/themes/greydragon/css/colorpacks/whitehawk/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/ico-album.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/ico-error.png b/themes/greydragon/css/colorpacks/whitehawk/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/ico-error.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/ico-help.png b/themes/greydragon/css/colorpacks/whitehawk/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/ico-help.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/ico-info.png b/themes/greydragon/css/colorpacks/whitehawk/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/ico-info.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/ico-warning.png b/themes/greydragon/css/colorpacks/whitehawk/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/ico-warning.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/loading-large.gif b/themes/greydragon/css/colorpacks/whitehawk/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/loading-large.gif differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/loading-small.gif b/themes/greydragon/css/colorpacks/whitehawk/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/loading-small.gif differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/search.png b/themes/greydragon/css/colorpacks/whitehawk/images/search.png
new file mode 100644
index 0000000..bb323e5
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/search.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/ui-icons.png b/themes/greydragon/css/colorpacks/whitehawk/images/ui-icons.png
new file mode 100644
index 0000000..db1ec71
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/ui-icons.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/view-calendar-b.png b/themes/greydragon/css/colorpacks/whitehawk/images/view-calendar-b.png
new file mode 100644
index 0000000..f3ab6aa
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/view-calendar-b.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/view-calendar.png b/themes/greydragon/css/colorpacks/whitehawk/images/view-calendar.png
new file mode 100644
index 0000000..a4d038a
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/view-calendar.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/view-comments-b.png b/themes/greydragon/css/colorpacks/whitehawk/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/view-comments-b.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/view-comments.png b/themes/greydragon/css/colorpacks/whitehawk/images/view-comments.png
new file mode 100644
index 0000000..5aca071
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/view-comments.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/view-fullsize-b.png b/themes/greydragon/css/colorpacks/whitehawk/images/view-fullsize-b.png
new file mode 100644
index 0000000..fad5e53
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/view-fullsize-b.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/view-fullsize.png b/themes/greydragon/css/colorpacks/whitehawk/images/view-fullsize.png
new file mode 100644
index 0000000..cc4fbba
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/view-fullsize.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/view-info-b.png b/themes/greydragon/css/colorpacks/whitehawk/images/view-info-b.png
new file mode 100644
index 0000000..90f1bb4
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/view-info-b.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/view-info-o.png b/themes/greydragon/css/colorpacks/whitehawk/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/view-info-o.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/view-info.png b/themes/greydragon/css/colorpacks/whitehawk/images/view-info.png
new file mode 100644
index 0000000..4bdb724
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/view-info.png differ
diff --git a/themes/greydragon/css/colorpacks/whitehawk/images/view-slideshow-b.png b/themes/greydragon/css/colorpacks/whitehawk/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon/css/colorpacks/whitehawk/images/view-slideshow-b.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/css/colors.css b/themes/greydragon/css/colorpacks/wind/css/colors.css
new file mode 100644
index 0000000..2e53eb1
--- /dev/null
+++ b/themes/greydragon/css/colorpacks/wind/css/colors.css
@@ -0,0 +1,175 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: Wind - Wind theme-like color pack
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #ccc; }
+body { color: #000; background-color: #ccc; padding-left: 10px; padding-right: 10px; }
+                                                                               
+a { color: #33629f !important }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png') no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-header { background-color: #e8e8e8; border-bottom: #ccc 1px solid; }
+#g-header .g-message-block { border: 1px #888 solid; background-color: #aaa; color: #000; }
+#g-main { background-color: #fff; }
+#g-footer { background-color: #e8e8e8; border-top: #ccc 1px solid; }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top, #g-column-bottom { background-color: #e8e8e8; }
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info h1, #g-album-header h1 { border-bottom: #ccc 1px solid; }
+#g-info .g-description { border: #888 1px solid; }
+
+.g-thumbslide { background: #e8e8e8; border-color: #707E83; }
+.g-album .g-thumbslide { border-color: #707E83; }
+.g-thumbcrop  { border-color: #707E83; }
+                                                                                                                 
+.g-default  .g-thumbslide .g-description { color: #000; border-top: 1px solid #707E83; border-bottom: 1px solid #707E83; background: #e8e8e8; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-expanded .g-thumbslide .g-description { color: #fff; background: transparent; border: none; }
+.g-album    .g-thumbslide .g-description { background-image: url(../images/ico-album.png); background-repeat: no-repeat; background-position: 8px 4px; }
+
+.g-thumbslide .g-metadata { border-top: 1px solid #707E83; background: #e8e8e8; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: 1px solid #888; background: #e8e8e8; }
+div.g-resize .g-description { color: #000; background: #e8e8e8; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #999; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #999; }
+div.g-resize .g-more { border: 1px solid #999; background: #e8e8e8; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div#g-movie .g-movie { border: 1px solid #888; padding: 5px; background: #e8e8e8; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block { border: 1px solid #ccc; } 
+.g-block h2 { background-color: #e8e8e8; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #999; background: #e8e8e8; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #fff; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #e8e8e8; color: #000; }
+#sb-title-inner { color: #000; }
+#sb-counter a { font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #fff; border: #303030 1px solid; }
+#g-add-photos-button { border: #303030 1px solid; }
+#g-add-photos-status { background-color: #fff; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile h1 { border-bottom: #ccc 1px solid; }
+#g-user-profile .g-avatar { border: 1px solid #888; background: #fff; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li { background-color: #bdd2ff; }
+#g-site-menu li a:hover { color: #000000; background-color: #cfdeff; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #cfdeff; border-bottom: #cfdeff 1px solid; }
+#g-site-menu li ul { border: #cfdeff 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #bdd2ff; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #ddf2ff; }
+
+#g-site-menu.g-bar { border: #cfdeff 1px solid; background-color: #bdd2ff; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #bdd2ff none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #ddf2ff; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #303030 1px solid; }
+#g-exif-data .g-even { background-color: #A0A0A0; }
+#g-exif-data .g-odd { background-color: #C0C0C0; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #ccc; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #888; background: #555; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #ccc; }
+#g-comment-form { border: 1px dotted #ccc; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #ccc; color: #666;  }
+#g-quick-search-form input[type="submit"] { border: #c5dbec 1px solid; text-indent: 0; width: auto; height: auto; font: 80% arial, helvetica, clean, sans-serif; font-weight: bold; padding-top: 3px; padding-bottom: 3px; }
+#g-search-results h1 { border-bottom: #ccc 1px solid; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background-color: #e8e8e8; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #ccc url('../images/section.png') repeat-x; }
+.ui-widget-content { border: 1px solid #303030; background-color: #fff; color: #000; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; background: #303030; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #888 1px solid; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../../../../../../modules/calendarview/images/ico-view-calendarview.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/ico-view-fullsize.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon/css/colorpacks/wind/images/ajax-loading.gif b/themes/greydragon/css/colorpacks/wind/images/ajax-loading.gif
new file mode 100644
index 0000000..53dd589
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/ajax-loading.gif differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/colorpack.png b/themes/greydragon/css/colorpacks/wind/images/colorpack.png
new file mode 100644
index 0000000..d217920
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/colorpack.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/ico-album.png b/themes/greydragon/css/colorpacks/wind/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/ico-album.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/ico-error.png b/themes/greydragon/css/colorpacks/wind/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/ico-error.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/ico-help.png b/themes/greydragon/css/colorpacks/wind/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/ico-help.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/ico-info.png b/themes/greydragon/css/colorpacks/wind/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/ico-info.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/ico-view-fullsize.png b/themes/greydragon/css/colorpacks/wind/images/ico-view-fullsize.png
new file mode 100644
index 0000000..740183a
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/ico-view-fullsize.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/ico-view-slideshow-rtl.png b/themes/greydragon/css/colorpacks/wind/images/ico-view-slideshow-rtl.png
new file mode 100644
index 0000000..9552d30
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/ico-view-slideshow-rtl.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/ico-view-slideshow.png b/themes/greydragon/css/colorpacks/wind/images/ico-view-slideshow.png
new file mode 100644
index 0000000..d43a560
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/ico-view-slideshow.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/ico-warning.png b/themes/greydragon/css/colorpacks/wind/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/ico-warning.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/loading-large.gif b/themes/greydragon/css/colorpacks/wind/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/loading-large.gif differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/loading-small.gif b/themes/greydragon/css/colorpacks/wind/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/loading-small.gif differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/section.png b/themes/greydragon/css/colorpacks/wind/images/section.png
new file mode 100644
index 0000000..33fc350
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/section.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/ui-icons.png b/themes/greydragon/css/colorpacks/wind/images/ui-icons.png
new file mode 100644
index 0000000..7dc8ab9
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/ui-icons.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/view-calendar.png b/themes/greydragon/css/colorpacks/wind/images/view-calendar.png
new file mode 100644
index 0000000..13e0e8f
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/view-calendar.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/view-comments-b.png b/themes/greydragon/css/colorpacks/wind/images/view-comments-b.png
new file mode 100644
index 0000000..64f8c50
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/view-comments-b.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/view-comments.png b/themes/greydragon/css/colorpacks/wind/images/view-comments.png
new file mode 100644
index 0000000..f33bdf1
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/view-comments.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/view-fullsize.png b/themes/greydragon/css/colorpacks/wind/images/view-fullsize.png
new file mode 100644
index 0000000..58b3e0b
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/view-fullsize.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/view-info-b.png b/themes/greydragon/css/colorpacks/wind/images/view-info-b.png
new file mode 100644
index 0000000..90f1bb4
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/view-info-b.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/view-info-o.png b/themes/greydragon/css/colorpacks/wind/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/view-info-o.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/view-info.png b/themes/greydragon/css/colorpacks/wind/images/view-info.png
new file mode 100644
index 0000000..2cc7a68
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/view-info.png differ
diff --git a/themes/greydragon/css/colorpacks/wind/images/view-slideshow-b.png b/themes/greydragon/css/colorpacks/wind/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon/css/colorpacks/wind/images/view-slideshow-b.png differ
diff --git a/themes/greydragon/css/custom.css b/themes/greydragon/css/custom.css
new file mode 100644
index 0000000..d9b3582
--- /dev/null
+++ b/themes/greydragon/css/custom.css
@@ -0,0 +1,61 @@
+#fam-login {
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  width: 700px;
+  height: 300px;
+  margin-top: -150px;
+  margin-left: -350px;
+  background-color: #F1F1F1;
+  border: 2px solid #DDD;
+}
+
+#fam-login #g-login-form {
+  margin: 60px auto 0px;
+  width: 400px;
+  color: #555;
+  font-size: 14px;
+  letter-spacing: 1px;
+}
+
+#fam-login input[type="text"], #fam-login input[type="password"] {
+  width: 392px;
+  color: #555;
+  font-size: 20px;
+  margin-top: 3px;
+  background-color: #DDD;
+  border: 2px solid #CCC;
+  padding: 2px;
+}
+
+#fam-login input[type="text"]:focus, #fam-login input[type="password"]:focus {
+  border: 2px solid #ff8000;
+  background-color: #fff;
+}
+
+#fam-login input[type="submit"] {
+  position: absolute;
+  left: 50%;
+  margin-left: -100px;
+  margin-top: 2em;
+  width: 200px;
+  font-size: 14px;
+  letter-spacing: 2px;
+  background-color: #666;
+  color: #FFF;
+  padding: 5px;
+}
+
+#fam-login-header {
+  height: 48px;
+  background-repeat: no-repeat;
+  width: 400px;
+  position: absolute;
+  left: 50%;
+  margin-left: -200px;
+}
+
+#fam-login #g-login-form fieldset {
+  border: none;
+  padding: 0;
+}
diff --git a/themes/greydragon/css/forms.css b/themes/greydragon/css/forms.css
new file mode 100644
index 0000000..8375de2
--- /dev/null
+++ b/themes/greydragon/css/forms.css
@@ -0,0 +1,120 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules related to forms/dialogs
+ */
+
+.ui-widget-overlay { position: absolute; top:0; left:0; bottom: 0; right: 0; position: fixed; width:100%; filter: alpha(opacity=70); -moz-opacity: 0.7; -khtml-opacity: 0.7; opacity: 0.7; background-color: #111; zoom: 1; }
+.ui-widget-overlay { height: expression(document.documentElement.clientHeight + 'px'); }
+.ui-widget-overlay { height: 100%; }
+
+/* Dialog ----------------------------------*/
+
+.ui-dialog { position: relative; width: 300px; display: inline-block; z-index: 100; }
+.ui-dialog .ui-dialog-titlebar { height: 1em; padding: .5em .3em .3em 1em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; } 
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; text-indent: -900em; }
+.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; display: block; clear:both; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-dialog ul { padding: 0; }
+.ui-dialog .ui-dialog-content .g-right { margin-right: 20px; }
+
+/* forms.css - Component containers ~~~~~~~~~~~~~~~~~~*/
+.ui-widget-header { color: #ffffff; font-weight: bold; }
+.ui-widget-header a { color: #ffffff; }
+.ui-widget-content a { color: #222222; }
+
+/* forms.css - Forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+form        { margin: 0; }
+form p.g-error { color: red; }
+fieldset    { border: 1px solid #ccc; margin-left: 0; margin-right: 0; padding: 0 1em .8em 1em; }
+legend      { display: none; }
+input.textbox, input[type="text"], input[type="password"], textarea { border: 1px solid #e8e8e8; border-top-color: #ccc; border-left-color: #ccc; clear: both; color: #333; width: 50%; }
+textarea    { height: 12em; width: 97%; }
+input:focus, input.textbox:focus, input[type=text]:focus, textarea:focus, option:focus { background-color: #ffc; color: #000; }
+input.checkbox, input[type=checkbox], input.radio, input[type=radio] { float: left; margin-right: .4em; }
+
+/* forms.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+form li { margin: 0; padding: 0 0 .2em 0; }
+form ul { margin-top: 0; }
+form ul ul { clear: both; }
+form ul ul li { float: left; margin-right: 0.6em; }
+input, select, textarea { display: block; clear: both; }
+input[type="submit"], input[type="reset"] { display: inline; }
+input[type="submit"], .g-button, button { display: inline-block; padding: 2px 10px 2px; font-size: 0.8em; color: #333 !important; font-weight: normal; line-height: 1.4em; text-align: center; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); background-color: #fafafa; background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-repeat: no-repeat; filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); border: 1px solid #ccc; border-bottom-color: #bbb; cursor: pointer; cursor: hand; *margin-left: .3em; }
+
+.ui-dialog .g-cancel { display: none; }
+
+.g-button { margin: 0 0.4em 0.4em 0; }
+.g-right { float: right; }
+
+/* forms.css - Forms in dialogs and panels ~~~~~~~~~~~*/
+
+#g-dialog ul li { padding-bottom: 0.4em; }
+#g-dialog fieldset, #g-panel fieldset { border: none; padding: 0; }
+#g-panel legend { display: none; }
+input[readonly] { background-color: #F4F4FC; }
+#g-dialog input.textbox, #g-dialog input[type=text], #g-dialog input[type=password], #g-dialog textarea { width: 97%; }
+
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
+.g-progress-bar { height: 1em; width: 100%; margin-top: .5em; display: inline-block; }
+#g-progress #g-status { padding: 0.5em 0; }
+
+/* forms.css - Short forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-short-form legend, .g-short-form label { display: none; }
+.g-short-form fieldset { border: none; padding: 0; }
+.g-short-form li { float: left; margin: 0 !important; padding: .4em 0; }
+.g-short-form .textbox, .g-short-form input[type=text] { color: #666; padding: .3em .6em; width: 100%; }
+.g-short-form .textbox.g-error { border: 1px solid #f00; color: #f00; padding-left: 24px; }
+.g-short-form .g-cancel { display: block; margin: .3em .8em; }
+#g-sidebar .g-short-form li { padding-left: 0; padding-right: 0; }
+
+#g-quick-search-form input[type="submit"] { filter: none; margin-top: 0; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-login fieldset { border: none; }
+#g-login legend { display: none; }
+#g-login label { display: block; }
+
+#g-column-centerfull #g-error h2 { padding-top: 10px; }
+#g-column-centerfull #g-login { width: 270px; margin-top: 10px; padding-top: 10px; }
+#g-column-centerfull #g-login input[type='text'], #g-column-centerfull #g-login input[type='password'] { width: 100%; }
+#g-column-centerfull #g-login #g-password-reset { position: relative; bottom: 20px; right: 14px; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile { display: block; }
+#g-user-profile h1 { margin: 0 0 1em 0; }
+#g-user-profile .g-avatar { float: left; margin: .4em; }
+#g-user-profile .g-block { position: static; min-height: 5em; clear: none; margin-left: 4em; }
+#g-user-profile .g-block ul { padding: 0.6em 0; }
+#g-user-profile th { text-align: left; }
+
+#g-user-profile-operations { height: 1.5em; }
+#g-user-profile #g-rest-key .g-button { margin-left: 1em; }
+
+/* forms.css - Uploadify ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-album-form,
+#g-edit-album-form, #g-edit-photo-form { width: 500px; }
+
+#g-add-photos-form { width: 476px; }
+#g-add-photos-canvas { margin-top: 1.1em; }
+#g-add-photos-status #g-action-status li { padding-top: 0.3em; padding-bottom: 0.3em; padding-left: 2em; }
+.uploadifyQueueItem { padding-top: 6px; padding-bottom: 4ps; }
+
+/* forms.css - Permission ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-permissions { width: 480px; }
+#g-permissions .g-breadcrumbs { position: static; }
+#g-permissions th { padding-top: 4px; padding-right: 0.5em; }
+
+#g-confirm-delete { width: 340px; margin-top: 1em; }
diff --git a/themes/greydragon/css/framepacks/android/css/frame.css b/themes/greydragon/css/framepacks/android/css/frame.css
new file mode 100644
index 0000000..548b152
--- /dev/null
+++ b/themes/greydragon/css/framepacks/android/css/frame.css
@@ -0,0 +1,32 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Android
+ */
+
+#g-album-grid>li { padding: 10px 6px 10px 10px; }
+.g-thumbslide { background: transparent; }
+
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { border-color: #ADAEAD; }
+.g-thumbcrop { border-width: 1px; border-style: solid; border-color: #ADAEAD; }
+
+.g-thumbtype-sqr { background: url('../images/thumb-sqr.png') no-repeat top left; }
+.g-thumbtype-flm { background: url('../images/thumb-flm.png') no-repeat top left; }
+.g-thumbtype-dgt { background: url('../images/thumb-dgt.png') no-repeat top left; }
+.g-thumbtype-wd  { background: url('../images/thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-thumbtype-sqr { background-image: url('../images/thumb-sqr-ext.png'); }
+.g-extended .g-thumbtype-flm { background-image: url('../images/thumb-flm-ext.png'); }
+.g-extended .g-thumbtype-dgt { background-image: url('../images/thumb-dgt-ext.png'); }
+.g-extended .g-thumbtype-wd  { background-image: url('../images/thumb-wd-ext.png'); }
+
+.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-e.png'); }
+.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-e.png'); }
+.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-e.png'); }
+.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-e.png'); }
+
+.g-extended .g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-eext.png'); }
+.g-extended .g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-eext.png'); }
+.g-extended .g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-eext.png'); }
+.g-extended .g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-eext.png'); }
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-dgt-e.png b/themes/greydragon/css/framepacks/android/images/thumb-dgt-e.png
new file mode 100644
index 0000000..39a793a
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-dgt-e.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-dgt-eext.png b/themes/greydragon/css/framepacks/android/images/thumb-dgt-eext.png
new file mode 100644
index 0000000..df4aa49
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-dgt-eext.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-dgt-ext.png b/themes/greydragon/css/framepacks/android/images/thumb-dgt-ext.png
new file mode 100644
index 0000000..297a456
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-dgt-ext.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-dgt.png b/themes/greydragon/css/framepacks/android/images/thumb-dgt.png
new file mode 100644
index 0000000..b9cc40e
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-dgt.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-flm-e.png b/themes/greydragon/css/framepacks/android/images/thumb-flm-e.png
new file mode 100644
index 0000000..b97c8c1
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-flm-e.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-flm-eext.png b/themes/greydragon/css/framepacks/android/images/thumb-flm-eext.png
new file mode 100644
index 0000000..45c38dc
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-flm-eext.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-flm-ext.png b/themes/greydragon/css/framepacks/android/images/thumb-flm-ext.png
new file mode 100644
index 0000000..7361f20
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-flm-ext.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-flm.png b/themes/greydragon/css/framepacks/android/images/thumb-flm.png
new file mode 100644
index 0000000..a407409
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-flm.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-sqr-e.png b/themes/greydragon/css/framepacks/android/images/thumb-sqr-e.png
new file mode 100644
index 0000000..33bcd99
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-sqr-e.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-sqr-eext.png b/themes/greydragon/css/framepacks/android/images/thumb-sqr-eext.png
new file mode 100644
index 0000000..c924637
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-sqr-eext.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-sqr-ext.png b/themes/greydragon/css/framepacks/android/images/thumb-sqr-ext.png
new file mode 100644
index 0000000..3fdc3a3
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-sqr-ext.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-sqr.png b/themes/greydragon/css/framepacks/android/images/thumb-sqr.png
new file mode 100644
index 0000000..3a038b0
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-sqr.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-wd-e.png b/themes/greydragon/css/framepacks/android/images/thumb-wd-e.png
new file mode 100644
index 0000000..3e78ce8
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-wd-e.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-wd-eext.png b/themes/greydragon/css/framepacks/android/images/thumb-wd-eext.png
new file mode 100644
index 0000000..c51abf3
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-wd-eext.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-wd-ext.png b/themes/greydragon/css/framepacks/android/images/thumb-wd-ext.png
new file mode 100644
index 0000000..a5aa4b2
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-wd-ext.png differ
diff --git a/themes/greydragon/css/framepacks/android/images/thumb-wd.png b/themes/greydragon/css/framepacks/android/images/thumb-wd.png
new file mode 100644
index 0000000..36a6a4f
Binary files /dev/null and b/themes/greydragon/css/framepacks/android/images/thumb-wd.png differ
diff --git a/themes/greydragon/css/framepacks/book/css/frame.css b/themes/greydragon/css/framepacks/book/css/frame.css
new file mode 100644
index 0000000..73a0bbb
--- /dev/null
+++ b/themes/greydragon/css/framepacks/book/css/frame.css
@@ -0,0 +1,64 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Book
+ */
+
+#g-album-grid>li { padding: 10px 10px 10px 14px; }
+.g-thumbslide { background: transparent; }
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { background-color: #FFF; border-color: #ADAEAD; color: #111; margin-left: 15px; }
+.g-thumbcrop { border: #ADAEAD 1px solid; } 
+.g-album .g-thumbslide .g-description { background-image: none; }
+.g-album .g-thumbslide .g-description .g-title { padding-left: 0; }
+.g-expanded.g-album .g-thumbslide .g-description .g-title { padding-left: 0; }
+
+.g-item .g-context-menu { left: 200px; }
+.g-item .g-context-menu:hover { left: 20px; }
+.g-extended .g-item .g-context-menu { left: 304px; }
+.g-extended .g-item .g-context-menu:hover { left: 20px; }
+
+.g-album.g-thumbtype-sqr { background: url('../images/a-thumb-sqr.png') no-repeat top left; }
+.g-album.g-thumbtype-flm { background: url('../images/a-thumb-flm.png') no-repeat top left; }
+.g-album.g-thumbtype-dgt { background: url('../images/a-thumb-dgt.png') no-repeat top left; }
+.g-album.g-thumbtype-wd  { background: url('../images/a-thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-album.g-thumbtype-sqr { background-image: url('../images/a-thumb-sqr-ext.png'); }
+.g-extended .g-album.g-thumbtype-flm { background-image: url('../images/a-thumb-flm-ext.png'); }
+.g-extended .g-album.g-thumbtype-dgt { background-image: url('../images/a-thumb-dgt-ext.png'); }
+.g-extended .g-album.g-thumbtype-wd  { background-image: url('../images/a-thumb-wd-ext.png'); }
+
+.g-album.g-thumbtype-sqr.g-expanded { background-image: url('../images/a-thumb-sqr-e.png'); }
+.g-album.g-thumbtype-flm.g-expanded { background-image: url('../images/a-thumb-flm-e.png'); }
+.g-album.g-thumbtype-dgt.g-expanded { background-image: url('../images/a-thumb-dgt-e.png'); }
+.g-album.g-thumbtype-wd.g-expanded  { background-image: url('../images/a-thumb-wd-e.png'); }
+
+.g-extended .g-album.g-thumbtype-sqr.g-expanded { background-image: url('../images/a-thumb-sqr-eext.png'); }
+.g-extended .g-album.g-thumbtype-flm.g-expanded { background-image: url('../images/a-thumb-flm-eext.png'); }
+.g-extended .g-album.g-thumbtype-dgt.g-expanded { background-image: url('../images/a-thumb-dgt-eext.png'); }
+.g-extended .g-album.g-thumbtype-wd.g-expanded  { background-image: url('../images/a-thumb-wd-eext.png'); }
+
+.g-photo.g-thumbtype-sqr { background: url('../images/thumb-sqr.png') no-repeat top left; }
+.g-photo.g-thumbtype-flm { background: url('../images/thumb-flm.png') no-repeat top left; }
+.g-photo.g-thumbtype-dgt { background: url('../images/thumb-dgt.png') no-repeat top left; }
+.g-photo.g-thumbtype-wd  { background: url('../images/thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-photo.g-thumbtype-sqr { background-image: url('../images/thumb-sqr-ext.png'); }
+.g-extended .g-photo.g-thumbtype-flm { background-image: url('../images/thumb-flm-ext.png'); }
+.g-extended .g-photo.g-thumbtype-dgt { background-image: url('../images/thumb-dgt-ext.png'); }
+.g-extended .g-photo.g-thumbtype-wd  { background-image: url('../images/thumb-wd-ext.png'); }
+
+.g-photo.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-e.png'); }
+.g-photo.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-e.png'); }
+.g-photo.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-e.png'); }
+.g-photo.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-e.png'); }
+
+.g-extended .g-photo.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-eext.png'); }
+.g-extended .g-photo.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-eext.png'); }
+.g-extended .g-photo.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-eext.png'); }
+.g-extended .g-photo.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-eext.png'); }
+
+.g-movie.g-thumbtype-sqr { background: url('../images/thumb-sqr.png') no-repeat top left; }
+.g-movie.g-thumbtype-flm { background: url('../images/thumb-flm.png') no-repeat top left; }
+.g-movie.g-thumbtype-dgt { background: url('../images/thumb-dgt.png') no-repeat top left; }
+.g-movie.g-thumbtype-wd  { background: url('../images/thumb-wd.png') no-repeat top left; }
\ No newline at end of file
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-dgt-e.png b/themes/greydragon/css/framepacks/book/images/a-thumb-dgt-e.png
new file mode 100644
index 0000000..486f50b
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-dgt-e.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-dgt-eext.png b/themes/greydragon/css/framepacks/book/images/a-thumb-dgt-eext.png
new file mode 100644
index 0000000..64bd017
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-dgt-eext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-dgt-ext.png b/themes/greydragon/css/framepacks/book/images/a-thumb-dgt-ext.png
new file mode 100644
index 0000000..bb5089d
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-dgt-ext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-dgt.png b/themes/greydragon/css/framepacks/book/images/a-thumb-dgt.png
new file mode 100644
index 0000000..458cc15
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-dgt.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-flm-e.png b/themes/greydragon/css/framepacks/book/images/a-thumb-flm-e.png
new file mode 100644
index 0000000..7be7ffe
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-flm-e.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-flm-eext.png b/themes/greydragon/css/framepacks/book/images/a-thumb-flm-eext.png
new file mode 100644
index 0000000..0ec4d3c
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-flm-eext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-flm-ext.png b/themes/greydragon/css/framepacks/book/images/a-thumb-flm-ext.png
new file mode 100644
index 0000000..a06d963
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-flm-ext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-flm.png b/themes/greydragon/css/framepacks/book/images/a-thumb-flm.png
new file mode 100644
index 0000000..b1ec950
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-flm.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-sqr-e.png b/themes/greydragon/css/framepacks/book/images/a-thumb-sqr-e.png
new file mode 100644
index 0000000..bf972a3
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-sqr-e.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-sqr-eext.png b/themes/greydragon/css/framepacks/book/images/a-thumb-sqr-eext.png
new file mode 100644
index 0000000..c13dd02
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-sqr-eext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-sqr-ext.png b/themes/greydragon/css/framepacks/book/images/a-thumb-sqr-ext.png
new file mode 100644
index 0000000..f197016
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-sqr-ext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-sqr.png b/themes/greydragon/css/framepacks/book/images/a-thumb-sqr.png
new file mode 100644
index 0000000..6eb7f26
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-sqr.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-wd-e.png b/themes/greydragon/css/framepacks/book/images/a-thumb-wd-e.png
new file mode 100644
index 0000000..2699b36
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-wd-e.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-wd-eext.png b/themes/greydragon/css/framepacks/book/images/a-thumb-wd-eext.png
new file mode 100644
index 0000000..ff78ba5
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-wd-eext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-wd-ext.png b/themes/greydragon/css/framepacks/book/images/a-thumb-wd-ext.png
new file mode 100644
index 0000000..7501df7
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-wd-ext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/a-thumb-wd.png b/themes/greydragon/css/framepacks/book/images/a-thumb-wd.png
new file mode 100644
index 0000000..df1164b
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/a-thumb-wd.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-dgt-e.png b/themes/greydragon/css/framepacks/book/images/thumb-dgt-e.png
new file mode 100644
index 0000000..2b9dc15
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-dgt-e.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-dgt-eext.png b/themes/greydragon/css/framepacks/book/images/thumb-dgt-eext.png
new file mode 100644
index 0000000..9d5cbe1
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-dgt-eext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-dgt-ext.png b/themes/greydragon/css/framepacks/book/images/thumb-dgt-ext.png
new file mode 100644
index 0000000..a1afba6
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-dgt-ext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-dgt.png b/themes/greydragon/css/framepacks/book/images/thumb-dgt.png
new file mode 100644
index 0000000..020ed3b
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-dgt.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-flm-e.png b/themes/greydragon/css/framepacks/book/images/thumb-flm-e.png
new file mode 100644
index 0000000..89724e8
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-flm-e.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-flm-eext.png b/themes/greydragon/css/framepacks/book/images/thumb-flm-eext.png
new file mode 100644
index 0000000..1c84d91
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-flm-eext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-flm-ext.png b/themes/greydragon/css/framepacks/book/images/thumb-flm-ext.png
new file mode 100644
index 0000000..04bc46a
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-flm-ext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-flm.png b/themes/greydragon/css/framepacks/book/images/thumb-flm.png
new file mode 100644
index 0000000..1709bbe
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-flm.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-sqr-e.png b/themes/greydragon/css/framepacks/book/images/thumb-sqr-e.png
new file mode 100644
index 0000000..ede2e1b
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-sqr-e.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-sqr-eext.png b/themes/greydragon/css/framepacks/book/images/thumb-sqr-eext.png
new file mode 100644
index 0000000..48416c6
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-sqr-eext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-sqr-ext.png b/themes/greydragon/css/framepacks/book/images/thumb-sqr-ext.png
new file mode 100644
index 0000000..d7e2e53
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-sqr-ext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-sqr.png b/themes/greydragon/css/framepacks/book/images/thumb-sqr.png
new file mode 100644
index 0000000..95e5890
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-sqr.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-wd-e.png b/themes/greydragon/css/framepacks/book/images/thumb-wd-e.png
new file mode 100644
index 0000000..eae6d66
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-wd-e.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-wd-eext.png b/themes/greydragon/css/framepacks/book/images/thumb-wd-eext.png
new file mode 100644
index 0000000..ee89913
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-wd-eext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-wd-ext.png b/themes/greydragon/css/framepacks/book/images/thumb-wd-ext.png
new file mode 100644
index 0000000..d303a1d
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-wd-ext.png differ
diff --git a/themes/greydragon/css/framepacks/book/images/thumb-wd.png b/themes/greydragon/css/framepacks/book/images/thumb-wd.png
new file mode 100644
index 0000000..6d344c5
Binary files /dev/null and b/themes/greydragon/css/framepacks/book/images/thumb-wd.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/css/frame.css b/themes/greydragon/css/framepacks/darkglass/css/frame.css
new file mode 100644
index 0000000..30d5c9a
--- /dev/null
+++ b/themes/greydragon/css/framepacks/darkglass/css/frame.css
@@ -0,0 +1,32 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - DarkGlass
+ */
+
+#g-album-grid>li { padding: 10px 6px 10px 10px; }
+.g-thumbslide { background: transparent; }
+
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { border-color: #ADAEAD; }
+.g-thumbcrop { border-width: 1px; border-style: solid; border-color: #7F7F7F; }
+
+.g-thumbtype-sqr { background: url('../images/thumb-sqr.png') no-repeat top left; }
+.g-thumbtype-flm { background: url('../images/thumb-flm.png') no-repeat top left; }
+.g-thumbtype-dgt { background: url('../images/thumb-dgt.png') no-repeat top left; }
+.g-thumbtype-wd  { background: url('../images/thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-thumbtype-sqr { background-image: url('../images/thumb-sqr-ext.png'); }
+.g-extended .g-thumbtype-flm { background-image: url('../images/thumb-flm-ext.png'); }
+.g-extended .g-thumbtype-dgt { background-image: url('../images/thumb-dgt-ext.png'); }
+.g-extended .g-thumbtype-wd  { background-image: url('../images/thumb-wd-ext.png'); }
+
+.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-e.png'); }
+.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-e.png'); }
+.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-e.png'); }
+.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-e.png'); }
+
+.g-extended .g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-eext.png'); }
+.g-extended .g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-eext.png'); }
+.g-extended .g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-eext.png'); }
+.g-extended .g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-eext.png'); }
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-e.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-e.png
new file mode 100644
index 0000000..c96c40c
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-e.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-eext.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-eext.png
new file mode 100644
index 0000000..0f87149
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-eext.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-ext.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-ext.png
new file mode 100644
index 0000000..ed89c39
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt-ext.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt.png
new file mode 100644
index 0000000..ace3e98
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-dgt.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-flm-e.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-flm-e.png
new file mode 100644
index 0000000..f8e8841
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-flm-e.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-flm-eext.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-flm-eext.png
new file mode 100644
index 0000000..4e735c8
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-flm-eext.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-flm-ext.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-flm-ext.png
new file mode 100644
index 0000000..9c0bff5
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-flm-ext.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-flm.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-flm.png
new file mode 100644
index 0000000..460ee7c
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-flm.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-e.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-e.png
new file mode 100644
index 0000000..eb28835
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-e.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-eext.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-eext.png
new file mode 100644
index 0000000..3af47df
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-eext.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-ext.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-ext.png
new file mode 100644
index 0000000..d2e268e
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr-ext.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr.png
new file mode 100644
index 0000000..da45039
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-sqr.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-wd-e.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-wd-e.png
new file mode 100644
index 0000000..62f5f1e
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-wd-e.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-wd-eext.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-wd-eext.png
new file mode 100644
index 0000000..bf8b2e7
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-wd-eext.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-wd-ext.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-wd-ext.png
new file mode 100644
index 0000000..bc994bc
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-wd-ext.png differ
diff --git a/themes/greydragon/css/framepacks/darkglass/images/thumb-wd.png b/themes/greydragon/css/framepacks/darkglass/images/thumb-wd.png
new file mode 100644
index 0000000..62e7881
Binary files /dev/null and b/themes/greydragon/css/framepacks/darkglass/images/thumb-wd.png differ
diff --git a/themes/greydragon/css/framepacks/greydragon/css/frame.css b/themes/greydragon/css/framepacks/greydragon/css/frame.css
new file mode 100644
index 0000000..bee1a1b
--- /dev/null
+++ b/themes/greydragon/css/framepacks/greydragon/css/frame.css
@@ -0,0 +1,43 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - GreyDragon
+ */
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in,
+body.g-extended.g-column-4 #g-column-top,
+body.g-extended.g-column-4 #g-column-bottom { min-width: 1302px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in { min-width: 1546px; }
+
+.g-thumbslide { margin-right: 6px; }
+.g-thumbslide .g-description { margin: 1px 0 0 2px; }
+.g-thumbslide .g-metadata    { margin-bottom: 4px; margin-left: 2px; }
+
+.g-extended #g-album-grid .g-item { min-width: 320px; }
+
+.g-item .g-context-menu { left: 190px; top: 12px; }
+.g-item .g-context-menu:hover { left: 6px; top: 6px; }
+
+.g-extended .g-item .g-context-menu { left: 290px; top: 12px; }
+.g-extended .g-item .g-context-menu:hover { left: 8px; top: 8px; }
+
+.g-thumbslide, .g-thumbslide-ext, .g-thumbcrop { border-width: 1px; border-style: solid; background-color: inherit; }
+.g-album .g-thumbslide, .g-album .g-thumbslide-ext { border-right-width: 4px; border-right-style: double; border-bottom-width: 4px; border-bottom-style: double; }
+.g-photo .g-thumbslide, .g-photo .g-thumbslide-ext { margin-bottom: 4px; } /* Need to compensate for double border in album's thumbs */
+.g-movie .g-thumbslide, .g-movie .g-thumbslide-ext { margin-bottom: 4px; } /* Need to compensate for double border in album's thumbs */
+
diff --git a/themes/greydragon/css/framepacks/iphone/css/frame.css b/themes/greydragon/css/framepacks/iphone/css/frame.css
new file mode 100644
index 0000000..0d24188
--- /dev/null
+++ b/themes/greydragon/css/framepacks/iphone/css/frame.css
@@ -0,0 +1,31 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - iPhone
+ */
+
+#g-album-grid>li { padding: 10px 6px 10px 10px; }
+.g-thumbslide { background: transparent; }
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { border-color: #7D7E7D; }
+.g-thumbcrop { border-width: 1px; border-style: solid; border-color: #7D7E7D; } 
+
+.g-thumbtype-sqr { background: url('../images/thumb-sqr.png') no-repeat top left; }
+.g-thumbtype-flm { background: url('../images/thumb-flm.png') no-repeat top left; }
+.g-thumbtype-dgt { background: url('../images/thumb-dgt.png') no-repeat top left; }
+.g-thumbtype-wd  { background: url('../images/thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-thumbtype-sqr { background-image: url('../images/thumb-sqr-ext.png'); }
+.g-extended .g-thumbtype-flm { background-image: url('../images/thumb-flm-ext.png'); }
+.g-extended .g-thumbtype-dgt { background-image: url('../images/thumb-dgt-ext.png'); }
+.g-extended .g-thumbtype-wd  { background-image: url('../images/thumb-wd-ext.png'); }
+
+.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-e.png'); }
+.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-e.png'); }
+.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-e.png'); }
+.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-e.png'); }
+
+.g-extended .g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-eext.png'); }
+.g-extended .g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-eext.png'); }
+.g-extended .g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-eext.png'); }
+.g-extended .g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-eext.png'); }
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-dgt-e.png b/themes/greydragon/css/framepacks/iphone/images/thumb-dgt-e.png
new file mode 100644
index 0000000..daa2002
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-dgt-e.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-dgt-eext.png b/themes/greydragon/css/framepacks/iphone/images/thumb-dgt-eext.png
new file mode 100644
index 0000000..9362e8b
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-dgt-eext.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-dgt-ext.png b/themes/greydragon/css/framepacks/iphone/images/thumb-dgt-ext.png
new file mode 100644
index 0000000..e477616
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-dgt-ext.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-dgt.png b/themes/greydragon/css/framepacks/iphone/images/thumb-dgt.png
new file mode 100644
index 0000000..c514620
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-dgt.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-flm-e.png b/themes/greydragon/css/framepacks/iphone/images/thumb-flm-e.png
new file mode 100644
index 0000000..3d3ddaa
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-flm-e.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-flm-eext.png b/themes/greydragon/css/framepacks/iphone/images/thumb-flm-eext.png
new file mode 100644
index 0000000..aedd558
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-flm-eext.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-flm-ext.png b/themes/greydragon/css/framepacks/iphone/images/thumb-flm-ext.png
new file mode 100644
index 0000000..62e62a2
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-flm-ext.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-flm.png b/themes/greydragon/css/framepacks/iphone/images/thumb-flm.png
new file mode 100644
index 0000000..0094def
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-flm.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-sqr-e.png b/themes/greydragon/css/framepacks/iphone/images/thumb-sqr-e.png
new file mode 100644
index 0000000..1dc590c
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-sqr-e.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-sqr-eext.png b/themes/greydragon/css/framepacks/iphone/images/thumb-sqr-eext.png
new file mode 100644
index 0000000..9f6024b
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-sqr-eext.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-sqr-ext.png b/themes/greydragon/css/framepacks/iphone/images/thumb-sqr-ext.png
new file mode 100644
index 0000000..4233c84
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-sqr-ext.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-sqr.png b/themes/greydragon/css/framepacks/iphone/images/thumb-sqr.png
new file mode 100644
index 0000000..c9e5714
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-sqr.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-wd-e.png b/themes/greydragon/css/framepacks/iphone/images/thumb-wd-e.png
new file mode 100644
index 0000000..15a0c4c
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-wd-e.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-wd-eext.png b/themes/greydragon/css/framepacks/iphone/images/thumb-wd-eext.png
new file mode 100644
index 0000000..0867baa
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-wd-eext.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-wd-ext.png b/themes/greydragon/css/framepacks/iphone/images/thumb-wd-ext.png
new file mode 100644
index 0000000..213d494
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-wd-ext.png differ
diff --git a/themes/greydragon/css/framepacks/iphone/images/thumb-wd.png b/themes/greydragon/css/framepacks/iphone/images/thumb-wd.png
new file mode 100644
index 0000000..a25d477
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphone/images/thumb-wd.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/css/frame.css b/themes/greydragon/css/framepacks/iphoto/css/frame.css
new file mode 100644
index 0000000..0dba3e9
--- /dev/null
+++ b/themes/greydragon/css/framepacks/iphoto/css/frame.css
@@ -0,0 +1,31 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - iPhoto
+ */
+
+#g-album-grid>li { padding: 10px 6px 10px 10px; }
+.g-thumbslide { background: transparent; }
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { background-color: #FFF; border-color: #ADAEAD; color: #111; }
+.g-thumbcrop { border: #ADAEAD 1px solid; } 
+
+.g-thumbtype-sqr { background: url('../images/thumb-sqr.png') no-repeat top left; }
+.g-thumbtype-flm { background: url('../images/thumb-flm.png') no-repeat top left; }
+.g-thumbtype-dgt { background: url('../images/thumb-dgt.png') no-repeat top left; }
+.g-thumbtype-wd  { background: url('../images/thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-thumbtype-sqr { background-image: url('../images/thumb-sqr-ext.png'); }
+.g-extended .g-thumbtype-flm { background-image: url('../images/thumb-flm-ext.png'); }
+.g-extended .g-thumbtype-dgt { background-image: url('../images/thumb-dgt-ext.png'); }
+.g-extended .g-thumbtype-wd  { background-image: url('../images/thumb-wd-ext.png'); }
+
+.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-e.png'); }
+.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-e.png'); }
+.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-e.png'); }
+.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-e.png'); }
+
+.g-extended .g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-eext.png'); }
+.g-extended .g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-eext.png'); }
+.g-extended .g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-eext.png'); }
+.g-extended .g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-eext.png'); }
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-e.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-e.png
new file mode 100644
index 0000000..616d1d5
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-e.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-eext.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-eext.png
new file mode 100644
index 0000000..828528a
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-eext.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-ext.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-ext.png
new file mode 100644
index 0000000..c090406
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt-ext.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt.png
new file mode 100644
index 0000000..5190758
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-dgt.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-flm-e.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-flm-e.png
new file mode 100644
index 0000000..251216b
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-flm-e.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-flm-eext.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-flm-eext.png
new file mode 100644
index 0000000..c60ba42
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-flm-eext.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-flm-ext.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-flm-ext.png
new file mode 100644
index 0000000..b1f8675
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-flm-ext.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-flm.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-flm.png
new file mode 100644
index 0000000..44c67c3
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-flm.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-e.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-e.png
new file mode 100644
index 0000000..02ddcd2
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-e.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-eext.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-eext.png
new file mode 100644
index 0000000..a6f6946
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-eext.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-ext.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-ext.png
new file mode 100644
index 0000000..de2fae4
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr-ext.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr.png
new file mode 100644
index 0000000..57c192f
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-sqr.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-wd-e.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-wd-e.png
new file mode 100644
index 0000000..492432e
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-wd-e.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-wd-eext.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-wd-eext.png
new file mode 100644
index 0000000..901a13a
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-wd-eext.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-wd-ext.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-wd-ext.png
new file mode 100644
index 0000000..0efa766
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-wd-ext.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/images/thumb-wd.png b/themes/greydragon/css/framepacks/iphoto/images/thumb-wd.png
new file mode 100644
index 0000000..f6bb30f
Binary files /dev/null and b/themes/greydragon/css/framepacks/iphoto/images/thumb-wd.png differ
diff --git a/themes/greydragon/css/framepacks/iphoto/views/frame.html.php b/themes/greydragon/css/framepacks/iphoto/views/frame.html.php
new file mode 100644
index 0000000..87ed99b
--- /dev/null
+++ b/themes/greydragon/css/framepacks/iphoto/views/frame.html.php
@@ -0,0 +1,5 @@
+<div class="g-thumb-wrapper"><div class="g-thumb-content"><div class="g-thumb-topleft"></div>
+	<?= $thumb_content; ?>
+	</div>
+	<div class="g-thumb-bottom"><div></div></div>
+</div>
diff --git a/themes/greydragon/css/framepacks/panel/css/frame.css b/themes/greydragon/css/framepacks/panel/css/frame.css
new file mode 100644
index 0000000..07a3048
--- /dev/null
+++ b/themes/greydragon/css/framepacks/panel/css/frame.css
@@ -0,0 +1,37 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Panel
+ */
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in,
+body.g-extended.g-column-4 #g-column-top,
+body.g-extended.g-column-4 #g-column-bottom { min-width: 1302px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in { min-width: 1546px; }
+
+.g-album .g-thumbslide, .g-thumbslide { border-width: 1px; border-style: solid; }
+.g-thumbslide .g-description { margin: 0 0 0 1px; }
+.g-thumbslide .g-metadata    { margin-bottom: 3px; margin-left: 1px; }
+
+.g-extended #g-album-grid .g-item { min-width: 320px; }
+
+.g-item .g-context-menu { left: 188px; top: 12px; }
+.g-item .g-context-menu:hover { left: 6px; top: 6px; }
+.g-extended .g-item .g-context-menu { left: 288px; top: 12px; }
+.g-extended .g-item .g-context-menu:hover { left: 6px; top: 6px; }
+
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { border-color: #ADAEAD; }
diff --git a/themes/greydragon/css/framepacks/roundcorners/css/frame.css b/themes/greydragon/css/framepacks/roundcorners/css/frame.css
new file mode 100644
index 0000000..ffe7c13
--- /dev/null
+++ b/themes/greydragon/css/framepacks/roundcorners/css/frame.css
@@ -0,0 +1,44 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Round Corners
+ */
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in,
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-column-top,
+body.g-extended.g-column-4 #g-column-bottom { min-width: 1278px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in { min-width: 1520px; }
+
+.g-thumbslide .g-description { margin: 0 0 0 0px; border-top-left-radius: 10px; border-top-right-radius: 10px; }
+.g-thumbslide .g-description.g-overlay-bottom { border-top-left-radius: 0; border-top-right-radius: 0; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; bottom: -3px; }
+.g-thumbslide .g-metadata    { margin: 0 0 1px 0px; }
+
+.g-item .g-context-menu { left: 188px; top: 12px; }
+.g-item .g-context-menu:hover { left: 6px; top: 6px; }
+.g-extended .g-item .g-context-menu { left: 288px; top: 12px; }
+.g-extended .g-item .g-context-menu:hover { left: 6px; top: 6px; }
+
+.g-default .g-thumbslide .g-description, 
+.g-expanded .g-thumbslide .g-description { border-color: #ADAEAD; color: #3c5580; }
+.g-thumbslide .g-metadata { border-color: #ADAEAD; color: #3c5580; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; }
+.g-thumbcrop { border-radius: 10px; box-shadow: 3px 3px 8px #333; }
+.g-thumbslide { background-image: none; }
+.g-thumbslide:hover .g-thumbcrop { box-shadow: 4px 4px 8px #333; }
+
+#g-photo .g-resize { border: none; background: transparent; }
+#g-photo .g-resize a { border-radius: 10px; box-shadow: 3px 3px 8px #333; }
\ No newline at end of file
diff --git a/themes/greydragon/css/framepacks/simple/css/frame.css b/themes/greydragon/css/framepacks/simple/css/frame.css
new file mode 100644
index 0000000..3a0539c
--- /dev/null
+++ b/themes/greydragon/css/framepacks/simple/css/frame.css
@@ -0,0 +1,39 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Simple
+ */
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in,
+body.g-extended.g-column-4 #g-column-top,
+body.g-extended.g-column-4 #g-column-bottom { min-width: 1278px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-right #g-column-top,
+body.g-extended.g-column-4.g-sidebar-right #g-column-bottom,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-column-top,
+body.g-extended.g-column-4.g-sidebar-left #g-column-bottom { min-width: 1520px; }
+
+.g-thumbslide .g-description { margin: 0 0 0 1px; }
+.g-thumbslide .g-metadata    { margin: 0 0 1px 1px; }
+
+.g-item .g-context-menu { left: 188px; top: 12px; }
+.g-item .g-context-menu:hover { left: 6px; top: 6px; }
+.g-extended .g-item .g-context-menu { left: 288px; top: 12px; }
+.g-extended .g-item .g-context-menu:hover { left: 6px; top: 6px; }
+
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { border-color: #ADAEAD; }
+.g-thumbcrop { border-width: 1px; border-style: solid; border-color: #ADAEAD; }
diff --git a/themes/greydragon/css/framepacks/wall/css/frame.css b/themes/greydragon/css/framepacks/wall/css/frame.css
new file mode 100644
index 0000000..1a74654
--- /dev/null
+++ b/themes/greydragon/css/framepacks/wall/css/frame.css
@@ -0,0 +1,48 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Simple
+ */
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in,
+body.g-extended.g-column-4 #g-column-top,
+body.g-extended.g-column-4 #g-column-bottom { min-width: 1224px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in { min-width: 1470px; }
+
+
+.g-thumbslide { padding-top: 0; padding-left: 0; width: 200px; min-height: auto; }
+.g-extended .g-thumbslide { width: 300px; }
+
+.g-thumbtype-flm .g-thumbslide, .g-extended .g-thumbtype-flm .g-thumbslide,
+.g-thumbtype-dgt .g-thumbslide, .g-extended .g-thumbtype-dgt .g-thumbslide,
+.g-thumbtype-wd  .g-thumbslide, .g-extended .g-thumbtype-wd  .g-thumbslide,
+.g-thumbtype-sqr .g-thumbslide, .g-extended .g-thumbtype-sqr .g-thumbslide { height: auto; }
+
+.g-item .g-context-menu { left: 184px; top: 2px; }
+.g-extended .g-item .g-context-menu { left: 282px; top: 4px; }
+.g-item .g-context-menu:hover, .g-extended .g-item .g-context-menu:hover { left: 0px; top: 0; }
+
+#g-album-grid .g-item { margin: 0; min-width: 200px; }
+.g-extended #g-album-grid .g-item { min-width: 300px; }
+
+.g-album-grid-container .g-wall > li { width: auto; }
+
+.g-thumbslide .g-description { margin: 0 0 0 0; left: 0; top: 0; min-height: 2.4em; }
+.g-thumbslide .g-metadata    { margin: 0 0 0 0; left: 0; bottom: 0; min-height: 2.4em; }
+
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description { border-color: #ADAEAD; border-top: none; }
+.g-thumbcrop { border: none; }
diff --git a/themes/greydragon/css/ipad.css b/themes/greydragon/css/ipad.css
new file mode 100644
index 0000000..801356f
--- /dev/null
+++ b/themes/greydragon/css/ipad.css
@@ -0,0 +1,20 @@
+/* Start Apple Styles */
+/* These styles support Apple products display of CSS. NOTES (orientation:landscape), (orientation:portrait) can also be used to be more specific */
+/* iPad [portrait + landscape] */
+@media only screen and (min-device-width:768px) and (max-device-width:1024px)
+{
+	#cboxOverlay { height: 200%; width: 200%; }
+	.g-bar#g-site-menu { width: 200%; }
+}
+
+/* iPhone 4 [portrait + landscape] */
+@media only screen and (resolution:326dpi) { }
+
+/* screen and (resolution: 163dpi) */
+/* iPhone 3 [portrait + landscape] */
+@media only screen and (max-device-width:480px) { }
+
+/* iPod Touch and older [portrait + landscape] */
+@media only screen and (resolution:326dpi) { }
+
+/* End Apple Styles */
diff --git a/themes/greydragon/css/layout.css b/themes/greydragon/css/layout.css
new file mode 100644
index 0000000..97fe65c
--- /dev/null
+++ b/themes/greydragon/css/layout.css
@@ -0,0 +1,77 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules related to general layout
+ * Defined as 70em wide
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* layout.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { overflow: auto; overflow: -moz-scrollbars-vertical; overflow-y: scroll; }
+* { margin: 0px; }
+body { min-width: 1020px; padding: 0; }
+.g-hideitem { display: none; }
+
+/* layout.css - Header ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-header { position: relative; min-width: 1020px; z-index: 5; }
+
+/* layout.css - Main ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-main { min-width: 1020px; height: auto; bottom: auto; }
+#g-main-in { min-width: 1020px; height: 100%; aoverflow: auto; bottom: auto; }
+
+#g-column-left   { float: left;  width: 230px; min-height: 32em; overflow: hidden; height: 100%; }
+#g-column-right  { float: right; width: 230px; min-height: 32em; overflow: hidden; height: 100%; }
+#g-column-center { margin: 0 17em 0 17em; min-height: 32em; overflow: hidden; height: 100%; }
+#g-column-centerleft { min-height: 32em; overflow: hidden; height: 100%; }
+#g-column-centerright { min-height: 32em; overflow: hidden; height: 100%; } 
+#g-column-centerfull { position: relative; min-height: 31em; overflow: hidden; height: 100%; }
+#g-column-top { display: block; overflow: hidden; }
+#g-column-bottom { display: block; overflow: hidden; }
+
+/* layout.css - Footer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-footer { position: relative; height: auto; min-width: 1020px; min-height: 2.8em; clear: both; display: block; overflow: auto; }
+#g-footer-leftside { float: left; display: inline; }
+#g-footer-rightside { float: right; display: inline; }
+
+/* layout.css - Extended Layout ~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* layous.css - Extended Layout - 3 columns+sidebar ~~*/
+body.g-extended.g-column-3.g-sidebar-right #g-header,
+body.g-extended.g-column-3.g-sidebar-right #g-footer,
+body.g-extended.g-column-3.g-sidebar-right #g-main,
+body.g-extended.g-column-3.g-sidebar-right #g-main-in,
+body.g-extended.g-column-3.g-sidebar-right #g-column-top,
+body.g-extended.g-column-3.g-sidebar-right #g-column-bottom,
+body.g-extended.g-column-3.g-sidebar-left #g-header,
+body.g-extended.g-column-3.g-sidebar-left #g-footer,
+body.g-extended.g-column-3.g-sidebar-left #g-main,
+body.g-extended.g-column-3.g-sidebar-left #g-main-in,
+body.g-extended.g-column-3.g-sidebar-left #g-column-top,
+body.g-extended.g-column-3.g-sidebar-left #g-column-bottom { min-width: 1250px; }
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in,
+body.g-extended.g-column-4 #g-column-top,
+body.g-extended.g-column-4 #g-column-bottom { min-width: 1342px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-right #g-column-top,
+body.g-extended.g-column-4.g-sidebar-right #g-column-bottom,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-column-top,
+body.g-extended.g-column-4.g-sidebar-left #g-column-bottom { min-width: 1580px; }
diff --git a/themes/greydragon/css/menus.css b/themes/greydragon/css/menus.css
new file mode 100644
index 0000000..194e93c
--- /dev/null
+++ b/themes/greydragon/css/menus.css
@@ -0,0 +1,58 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules related to menus
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css - Main menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu { position: absolute; } 
+#g-site-menu.g-default { left: 21em; bottom: 0; }
+#g-site-menu.g-top { left: 21em; top: 2px; }
+#g-site-menu.g-bottom-right { bottom: 0; right: 2em; }
+#g-site-menu.g-bar { left: 0; top: 0; width: 100%; padding-left: .5em; position: fixed !important; z-index: 9999; font-size: 0.9em; }
+
+#g-site-menu ul { float: left; width: 100%; white-space: nowrap; z-index: 102; }
+#g-site-menu>ul>li>ul { margin-top: 1px; }
+
+#g-site-menu ul ul ul { padding-top: 0; }
+#g-site-menu a  { display: block; padding: 0.2em 0.4em; text-align: center; width: auto; letter-spacing: 0; cursor: pointer; z-index: 102; }
+#g-site-menu li { float: left; padding: 0; background-color: transparent; border: transparent 1px solid; z-index: 102; }
+#g-site-menu li ul a { text-align: left; padding: 0.3em 0; text-indent: 0.8em; letter-spacing: 0; }
+#g-site-menu li ul a:hover { background-image: none; }
+#g-site-menu li ul { position: absolute; margin: 0 0 0 -1px; width: 14em; height: auto; left: -999em; }
+
+#g-site-menu li li { width: 14em; padding-right: 0; }
+#g-site-menu li ul a { width: 14em; }
+#g-site-menu li ul ul { margin: -1.8em 0 0 14em; }
+#g-site-menu li:hover ul ul,
+#g-site-menu li:hover ul ul ul,
+#g-site-menu li.iemhover ul ul,
+#g-site-menu li.iemhover ul ul ul { left: -999em; }
+#g-site-menu li:hover ul,
+#g-site-menu li li:hover ul,
+#g-site-menu li li li:hover ul,
+#g-site-menu li.iemhover ul,
+#g-site-menu li li.iemhover ul,
+#g-site-menu li li li.iemhover ul { left: auto; }
+
+#g-site-menu>ul>li>ul { display: none; }
+
+/* menus.css - Context menu ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-item .g-context-menu { position: absolute; margin: 0; padding: 0; top: 20px; left: 198px; width: 14px; height: 14px; background-position: -178px -144px; z-index: 4; } 
+.g-item .g-context-menu li { width: 100%; padding: 0; margin: 0; text-indent: -9999px; }
+.g-item .g-context-menu>li>a { font-size: 0em; display: none; }
+.g-item .g-context-menu:hover { top: 4px; left: 16px; top: 16px; width: 200px; height: auto; z-index: 102; }
+
+.g-extended .g-item .g-context-menu { left: 300px; }
+.g-extended .g-item .g-context-menu:hover { width: 300px; left: 16px; }
+.g-item .g-context-menu ul { padding: 0; margin: 0; }
+.g-item .g-context-menu li li { display: none; }
+.g-item .g-context-menu li li a { display: block; padding: 4px 6px; }
+.g-item .g-context-menu:hover li li { display: block; text-indent: 0px; } 
+
+.g-item.g-detail .g-context-menu { left: auto; right: 6px; }
+.g-item.g-detail .g-context-menu:hover { left: auto; right: 6px; }
\ No newline at end of file
diff --git a/themes/greydragon/css/modules.css b/themes/greydragon/css/modules.css
new file mode 100644
index 0000000..ff155d2
--- /dev/null
+++ b/themes/greydragon/css/modules.css
@@ -0,0 +1,165 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules related to modules
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - ShadowBox Skin ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-title { overflow: hidden; }
+#sb-title-inner { font-size: 10pt; font-weight: bold; padding-left: 10px; }
+#sb-nav #sb-nav-close { background-image: url('../images/close.png'); width: 60px; }
+#sb-container > #sb-overlay { min-height: 530px; overflow: auto; }
+
+/* modules.css - FancyBox Skin ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#fancybox-outer { background: #555; }
+#fancybox-content { border-color: #555; }
+#fancybox-title-over { font-weight: bold; }
+.fancybox-title-inside { background: transparent; font-weight: bold; color: #FFF; text-align: left; }
+#fancybox-close { background: url(../images/close.png) 0 0 no-repeat; width: 60px; height: 16px; right: -6px; }
+#fancybox-left-ico { background: url(../images/arrows_left.png) no-repeat left center; width: 35px; height: 107px; top: 40%; }
+#fancybox-left:hover span { left: 10px; }
+#fancybox-right-ico { background: url(../images/arrows_right.png) no-repeat left center; width: 35px; height: 107px; top: 40%; }
+#fancybox-right:hover span { right: 10px; }
+
+/* modules.css - Exif Data ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data td { padding: 0.2em; }
+.g-thumbcrop a.g-meta-exif-link { position: absolute; left: 278px; bottom: 4px; z-index: 100; display: block; background: none center bottom no-repeat; width: 17px; height: 16px; }
+
+/* modules.css - Image Block ~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-image-block>div { margin-left: 1px; margin-right: 1px; }
+.g-image-block { text-align: center; }
+.g-image-block img { padding: 5px; max-width: 200px; height: auto; }
+
+/* modules.css - Image Block Ex ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage #g-column-bottom #g-image-block-ex { display: none; }
+
+/* modules.css - RSS Feeds ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ul#g-feeds { padding: 0; margin: 0; }
+
+/* modules.css - Tags ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-tag-cloud ul { padding: 0; font-size: 100%; }
+#g-tag-cloud ul li { line-height: 1.2em; }
+#g-tag-cloud ul li span { display: none; }
+
+#g-add-tag-form fieldset ul { float: left; display: inline-block; padding: 0; }
+#g-add-tag-form li { float: left; margin: 0; padding: 0; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments { margin-top: 2em; float: left; width: 100%; min-height: 2em; }
+#g-comments ul li { margin: 0.4em 0; }
+
+#g-comments .g-button { right: 0.4em; cursor: pointer; /* hand-shaped cursor */ cursor: hand; /* for IE 5.x */ font-size: 0.8em; color: #333 !important; padding: 2px 10px; margin-top: 0.4em; border: 1px solid; border-color: #999 #666 #666 #999; background-color: #ddd; font-weight: normal; }
+.ui-icon-comment { background-position: -210px -144px; }
+
+#g-comment-detail ul { padding: 0; }
+#g-comment-detail>ul>li { margin: 4px 0; padding: 6px; min-height: 40px; }
+#g-comment-detail div { margin-top: 6px; padding-bottom: 8px; }
+#g-comment-detail li.g-no-comments { display: none; }
+#g-comment-detail p.g-no-comments { padding-bottom: 4px; }
+
+#g-comment-form fieldset { border: none; }
+#g-comment-form legend { display: none; width: 100%; }
+#g-comment-form ul { padding: 0; }
+#g-comment-form>fieldset>ul { margin: 0px 10px; }
+#g-comment-form label { display: block; }
+#g-comment-form textarea { width: 99%; height: 140px; }
+#g-comment-form input[type="text"],
+#g-comment-form input[type="password"] { width: 99%; }
+
+#g-comments .g-author { height: 32px; line-height: 32px; }
+#g-comments .g-avatar { height: 32px; margin-right: .4em; width: 32px; }
+
+/* modules.css - Gallery Stats ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-gallerystats ul { padding: 0; font-size: x-small; }
+
+/* modules.css - Info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata ul { padding: 0; }
+#g-metadata .g-description { margin-top: 0.4em; padding: 0.4em 0; }
+#g-metadata strong.caption { display: none; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-calendarview-link:hover { background-position: left bottom; }
+
+#g-view-calendar-form fieldset { border: none; }
+#g-view-calendar-form ul { padding: 8px; }
+#g-view-calendar-form li { padding-top: 8px; display: inline; padding-left: 10px; }
+#g-view-calendar-form label { margin: 4px 0; }
+#g-view-calendar-form select { margin: 4px 10px; }
+
+table.calendar { border-spacing: 1px; }
+table.calendar td.title a { font-weight: bold; }
+
+/* modules.css - ClustrMaps ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-clustrmaps .g-block-content { text-align: center; }
+
+/* modules.css - GPS Info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-gps-maps ul { padding-left: 0; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form { position: absolute; top: 3em; right: 1em; background: none transparent; }
+.viewmode-mini #g-quick-search-form { top: auto; right: auto; left: 1em; bottom: 2px; }
+#g-quick-search-form label { display: none; }
+#g-quick-search-form li { display: inline; float: left; padding: 0px; }
+
+#g-quick-search-form input[type="text"] { width: 150px; padding-top: 0.1em; padding-bottom: 0.1em; }
+#g-quick-search-form input[type="submit"] { display: block; width: 23px; height: 23px; text-indent: -9999px; overflow: hidden; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-header #basket, #g-header a[href="/basket/view_Orders"] { display: none; }
+#g-view-basket span.ui-icon { float: none; }
+
+#g-view-basket .ui-icon-plusthick { background-position: -32px -128px; }
+#g-view-basket .ui-icon-clipboard { background-position: -160px -128px; }
+#g-view-basket .ui-icon-trash     { background-position: -176px -96px; }
+#g-view-basket .ui-icon-cart      { background-position: -48px -112px; }
+#g-view-basket a.g-button { line-height: 2.2em; }
+#g-column-centerfull>.g-block { margin-top: 3em; }
+#g-column-centerfull>div>.basketbuttons>a.g-button>span { display: none; }
+
+/* modules.css - Register ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-welcome-message p { padding-bottom: 6px; }
+#g-change-password-user-form { height: 100%; }
+
+/* modules.css - Localization ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#l10n-client .labels { border-top: white 1px solid; height: 1.7em; }
+#l10n-client h2      { padding-top: 0.4em; padding-bottom: 0.3em; }
+#l10n-client .label.translation { margin-top: -0.4em; height: 1.7em; }
+#l10n-client #l10n-client-toggler { line-height: 1.7em; height: 1.7em; }
+#l10n-client .string-list li { font-size: 0.8em; line-height: 1.1em; }
+#l10n-client #l10n-client-string-select { width: 24%; }
+#l10n-client #l10n-client-string-select .string-list { border: 1px #ccc solid; }
+#l10n-client #g-l10n-search-form ul { padding: 0; }
+#l10n-client #l10n-client-string-editor { margin-left: 1em; }
+#l10n-client-string-editor .source .source-text { margin: 0 0.4em 0 0; border: 1px #ccc solid; padding: 0.4em; line-height: 1em; }
+#l10n-client-string-editor .translation { height: 19em; }
+#l10n-client #l10n-edit-translation { width: 97%; height: 17em; border: 1px #ccc solid; font-family: monospace; padding: 0.4em; }
+
+/* modules.css - jcarousel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.jcarousel-skin-tango .jcarousel-container { padding-top: 0.5em; }
+
+/* modules.css - ThumbNav ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-thumbnav-block-inline { margin-top: 26px; }
+#g-thumbnav-block-inline h2 { display: none; }
+#g-thumbnav-block .g-block-content,
+#g-thumbnav-block-inline .g-block-content { width: 210px; margin-left: auto; margin-right: auto; }
diff --git a/themes/greydragon/css/normalize.css b/themes/greydragon/css/normalize.css
new file mode 100644
index 0000000..9776813
--- /dev/null
+++ b/themes/greydragon/css/normalize.css
@@ -0,0 +1,431 @@
+/*! normalize.css 2011-11-04T15:38 UTC - http://github.com/necolas/normalize.css */
+
+/* =============================================================================
+   HTML5 display definitions
+   ========================================================================== */
+
+/*
+ * Corrects block display not defined in IE6/7/8/9 & FF3
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+nav,
+section {
+    display: block;
+}
+
+/*
+ * Corrects inline-block display not defined in IE6/7/8/9 & FF3
+ */
+
+audio,
+canvas,
+video {
+    display: inline-block;
+    *display: inline;
+    *zoom: 1;
+}
+
+/*
+ * Prevents modern browsers from displaying 'audio' without controls
+ */
+
+audio:not([controls]) {
+    display: none;
+}
+
+/*
+ * Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4
+ * Known issue: no IE6 support
+ */
+
+[hidden] {
+    display: none;
+}
+
+
+/* =============================================================================
+   Base
+   ========================================================================== */
+
+/*
+ * 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units
+ *    http://clagnut.com/blog/348/#c790
+ * 2. Keeps page centred in all browsers regardless of content height
+ * 3. Prevents iOS text size adjust after orientation change, without disabling user zoom
+ *    www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/
+ */
+
+html {
+    font-size: 100%; /* 1 */
+    overflow-y: scroll; /* 2 */
+    -webkit-text-size-adjust: 100%; /* 3 */
+    -ms-text-size-adjust: 100%; /* 3 */
+}
+
+/*
+ * Addresses margins handled incorrectly in IE6/7
+ */
+
+body {
+    margin: 0;
+}
+
+/* 
+ * Addresses font-family inconsistency between 'textarea' and other form elements.
+ */
+
+body,
+button,
+input,
+select,
+textarea {
+    font-family: sans-serif;
+}
+
+
+/* =============================================================================
+   Links
+   ========================================================================== */
+
+/*
+ * Addresses outline displayed oddly in Chrome
+ */
+
+a:focus {
+    outline: thin dotted;
+}
+
+/*
+ * Improves readability when focused and also mouse hovered in all browsers
+ * people.opera.com/patrickl/experiments/keyboard/test
+ */
+
+a:hover,
+a:active {
+    outline: 0;
+}
+
+
+/* =============================================================================
+   Typography
+   ========================================================================== */
+
+/*
+ * Neutralise smaller font-size in 'section' and 'article' in FF4+, Chrome, S5
+ */
+
+h1 {
+    font-size: 2em;
+}
+
+/*
+ * Addresses styling not present in IE7/8/9, S5, Chrome
+ */
+
+abbr[title] {
+    border-bottom: 1px dotted;
+}
+
+/*
+ * Addresses style set to 'bolder' in FF3+, S4/5, Chrome
+*/
+
+b, 
+strong { 
+    font-weight: bold; 
+}
+
+blockquote {
+    margin: 1em 40px;
+}
+
+/*
+ * Addresses styling not present in S5, Chrome
+ */
+
+dfn {
+    font-style: italic;
+}
+
+/*
+ * Addresses styling not present in IE6/7/8/9
+ */
+
+mark {
+    background: #ff0;
+    color: #000;
+}
+
+/*
+ * Corrects font family set oddly in IE6, S4/5, Chrome
+ * en.wikipedia.org/wiki/User:Davidgothberg/Test59
+ */
+
+pre,
+code,
+kbd,
+samp {
+    font-family: monospace, serif;
+    _font-family: 'courier new', monospace;
+    font-size: 1em;
+}
+
+/*
+ * Improves readability of pre-formatted text in all browsers
+ */
+
+pre {
+    white-space: pre;
+    white-space: pre-wrap;
+    word-wrap: break-word;
+}
+
+/*
+ * 1. Addresses CSS quotes not supported in IE6/7
+ * 2. Addresses quote property not supported in S4
+ */
+
+/* 1 */
+
+q {
+    quotes: none;
+}
+
+/* 2 */
+
+q:before,
+q:after {
+    content: '';
+    content: none;
+}
+
+small {
+    font-size: 75%;
+}
+
+/*
+ * Prevents sub and sup affecting line-height in all browsers
+ * gist.github.com/413930
+ */
+
+sub,
+sup {
+    font-size: 75%;
+    line-height: 0;
+    position: relative;
+    vertical-align: baseline;
+}
+
+sup {
+    top: -0.5em;
+}
+
+sub {
+    bottom: -0.25em;
+}
+
+
+/* =============================================================================
+   Lists
+   ========================================================================== */
+
+ul,
+ol {
+    margin-left: 0;
+    padding: 0 0 0 40px;
+}
+
+dd {
+    margin: 0 0 0 40px;
+}
+
+nav ul,
+nav ol {
+    list-style: none;
+    list-style-image: none;
+}
+
+
+/* =============================================================================
+   Embedded content
+   ========================================================================== */
+
+/*
+ * 1. Removes border when inside 'a' element in IE6/7/8/9, FF3
+ * 2. Improves image quality when scaled in IE7
+ *    code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
+ */
+
+img {
+    border: 0; /* 1 */
+    -ms-interpolation-mode: bicubic; /* 2 */
+}
+
+/*
+ * Corrects overflow displayed oddly in IE9 
+ */
+
+svg:not(:root) {
+    overflow: hidden;
+}
+
+
+/* =============================================================================
+   Figures
+   ========================================================================== */
+
+/*
+ * Addresses margin not present in IE6/7/8/9, S5, O11
+ */
+
+figure {
+    margin: 0;
+}
+
+
+/* =============================================================================
+   Forms
+   ========================================================================== */
+
+/*
+ * Corrects margin displayed oddly in IE6/7
+ */
+
+form {
+    margin: 0;
+}
+
+/*
+ * Define consistent border, margin, and padding
+ */
+
+fieldset {
+    border: 1px solid #c0c0c0;
+    margin: 0 2px;
+    padding: 0.35em 0.625em 0.75em;
+}
+
+/*
+ * 1. Corrects color not being inherited in IE6/7/8/9
+ * 2. Corrects alignment displayed oddly in IE6/7
+ */
+
+legend {
+    border: 0; /* 1 */
+    *margin-left: -7px; /* 2 */
+}
+
+/*
+ * 1. Corrects font size not being inherited in all browsers
+ * 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome
+ * 3. Improves appearance and consistency in all browsers
+ */
+
+button,
+input,
+select,
+textarea {
+    font-size: 100%; /* 1 */
+    margin: 0; /* 2 */
+    vertical-align: baseline; /* 3 */
+    *vertical-align: middle; /* 3 */
+}
+
+/*
+ * Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet
+ */
+
+button,
+input {
+    line-height: normal; /* 1 */
+}
+
+/*
+ * 1. Improves usability and consistency of cursor style between image-type 'input' and others
+ * 2. Corrects inability to style clickable 'input' types in iOS
+ * 3. Removes inner spacing in IE7 without affecting normal text inputs
+ *    Known issue: inner spacing remains in IE6
+ */
+
+button,
+input[type="button"], 
+input[type="reset"], 
+input[type="submit"] {
+    cursor: pointer; /* 1 */
+    -webkit-appearance: button; /* 2 */
+    *overflow: visible;  /* 3 */
+}
+
+/*
+ * 1. Addresses box sizing set to content-box in IE8/9
+ * 2. Removes excess padding in IE8/9
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+    box-sizing: border-box; /* 1 */
+    padding: 0; /* 2 */
+}
+
+/*
+ * 1. Addresses appearance set to searchfield in S5, Chrome
+ * 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof)
+ */
+
+input[type="search"] {
+    -webkit-appearance: textfield; /* 1 */
+    -moz-box-sizing: content-box;
+    -webkit-box-sizing: content-box; /* 2 */
+    box-sizing: content-box;
+}
+
+/*
+ * Removes inner padding that is displayed in S5, Chrome on OS X
+ */
+
+input[type="search"]::-webkit-search-decoration {
+    -webkit-appearance: none;
+}
+
+/*
+ * Removes inner padding and border in FF3+
+ * www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+    border: 0;
+    padding: 0;
+}
+
+/*
+ * 1. Removes default vertical scrollbar in IE6/7/8/9
+ * 2. Improves readability and alignment in all browsers
+ */
+
+textarea {
+    overflow: auto; /* 1 */
+    vertical-align: top; /* 2 */
+}
+
+
+/* =============================================================================
+   Tables
+   ========================================================================== */
+
+/* 
+ * Remove most spacing between table cells
+ */
+
+table {
+    border-collapse: collapse;
+    border-spacing: 0;
+}
diff --git a/themes/greydragon/css/rtl.css b/themes/greydragon/css/rtl.css
new file mode 100644
index 0000000..1d74d90
--- /dev/null
+++ b/themes/greydragon/css/rtl.css
@@ -0,0 +1,47 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules related to general layout
+ * Defined as 70em wide
+ */
+
+.rtl { direction: rtl; }
+
+.rtl #g-header, .rtl #g-main, .rtl #g-sidebar, .rtl #g-footer, 
+.rtl caption, .rtl th, .rtl #g-dialog, 
+.rtl .g-context-menu li a, .rtl #g-site-menu a,
+.rtl .g-metadata li, .rtl DIV.g-resize .g-description,
+.rtl .g-message-box li, .rtl #g-site-status li { text-align: right; }
+
+.rtl .g-text-right { text-align: left; }
+
+.rtl #g-site-menu li:hover ul ul,
+.rtl #g-site-menu li:hover ul ul ul,
+.rtl #g-site-menu li.iemhover ul ul,
+.rtl #g-site-menu li.iemhover ul ul ul { left: 999em; }
+
+.rtl .g-left, .rtl .g-inline li, .rtl .g-breadcrumbs li, .rtl .g-paginator li,
+.rtl .g-navigation li .rtl .g-buttonset li, .rtl .ui-icon-left .ui-icon,
+.rtl .g-metadata li, 
+.rtl #g-column-bottom .g-block,
+.rtl .g-short-form li, .rtl form ul ul li, .rtl input[type="submit"],
+.rtl input[type="reset"], .rtl input.checkbox, .rtl input[type=checkbox],
+.rtl input.radio, .rtl input[type=radio] { float: right; }
+
+.rtl .g-paginator .g-navigation { text-align: left; }
+
+.rtl #g-column-centerfull #g-album-header h1 { padding-right: 12em; }
+.rtl .g-buttonset .g-menu-link { text-indent: 9999px; }
+
+.rtl .g-thumbslide { padding-left: 0; padding-right: 6px; }
+.rtl .g-thumbslide .g-description { padding-left: 10px; }
+
+.rtl .ui-icon-first { background-position: -210px -178px; }
+.rtl .ui-icon-first-d { background-position: -210px -162px; }
+.rtl .ui-icon-prev { background-position: -194px -178px; }
+.rtl .ui-icon-prev-d { background-position: -194px -162px; }
+.rtl .ui-icon-next { background-position: -178px -178px; }
+.rtl .ui-icon-next-d { background-position: -178px -162px; }
+.rtl .ui-icon-last { background-position: -162px -178px; }
+.rtl .ui-icon-last-d { background-position: -162px -162px; }
diff --git a/themes/greydragon/css/screen.css b/themes/greydragon/css/screen.css
new file mode 100644
index 0000000..d820ad5
--- /dev/null
+++ b/themes/greydragon/css/screen.css
@@ -0,0 +1,17 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules - Kitchen sync
+ *
+ * Color rules for font/background/lines can be found in dedicated colorpack files
+ */
+
+@import "normalize.css";
+@import "layout.css";
+@import "menus.css";
+@import "modules.css";
+@import "forms.css";
+@import "base.css";
+@import "ipad.css";
+@import "rtl.css";
diff --git a/themes/greydragon/helpers/exif_event.php b/themes/greydragon/helpers/exif_event.php
new file mode 100644
index 0000000..02536ff
--- /dev/null
+++ b/themes/greydragon/helpers/exif_event.php
@@ -0,0 +1,45 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+class exif_event_Core {
+  static function item_created($item) {
+    if (!$item->is_album()) {
+      exif::extract($item);
+    }
+  }
+
+  static function item_deleted($item) {
+    db::build()
+      ->delete("exif_records")
+      ->where("item_id", "=", $item->id)
+      ->execute();
+  }
+
+  static function photo_menu($menu, $theme) {
+    $item = $theme->item();
+    $menu->append(
+      Menu::factory("link")
+      ->id("exifdata-link")
+      ->label(t("Photo Details"))
+      ->url(url::site("exif/show/$item->id"))
+      ->css_id("g-exifdata-link")
+      ->css_class("g-dialog-link"));
+  }
+}
+?>
diff --git a/themes/greydragon/helpers/greydragon_event.php b/themes/greydragon/helpers/greydragon_event.php
new file mode 100644
index 0000000..8761b1a
--- /dev/null
+++ b/themes/greydragon/helpers/greydragon_event.php
@@ -0,0 +1,92 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+class greydragon_event_Core {
+
+  static function site_menu($menu, $theme) {
+    $submenu = $menu->get("add_menu");
+    if (!empty($submenu)) {
+      $item = $submenu->get("add_photos_item");
+      if (!empty($item)) { $item->css_class("ui-icon-plus"); }
+
+      $item = $submenu->get("add_album_item");
+      if (!empty($item)) { $item->css_class("ui-icon-note"); }
+    }
+
+    $submenu = $menu->get("options_menu");
+    if (!empty($submenu)) {
+      $item = $submenu->get("edit_item");
+      if (!empty($item)) { $item->css_class("ui-icon-pencil"); }
+
+      $item = $submenu->get("edit_permissions");
+      if (!empty($item)) { $item->css_class("ui-icon-key"); }
+    }
+  }
+
+  static function read_session_cmdparam($cmd, $cookie, $default) {
+    try {
+      $_cmd = $_GET[$cmd]; 
+    } catch (Exception $e) {
+    };
+
+    if (isset($_cmd)):
+      $_var = strtolower($_cmd);
+      $_from_cmd = TRUE;
+      if ($_var == "default"):
+        $_var = $default;
+      endif;
+    else:
+      $_from_cmd = FALSE;
+      if ($cookie):
+        try { 
+          $_var = $_COOKIE[$cookie];
+        } catch (Exception $e) {
+        };
+      endif;
+    endif;
+
+    if (!isset($_var)):
+      $_var = $default;
+    endif;
+
+    return $_var;
+  }
+
+  static function add_path($path) {
+    $config = Kohana_Config::instance();
+    $kohana_modules = $config->get("core.modules");                                                  
+    array_unshift($kohana_modules, THEMEPATH . $path); 
+    $config->set("core.modules",  $kohana_modules);
+    Kohana::include_paths(true);
+  }
+
+  static function add_path_ex($setting, $cmd, $cookie, $path, $default) {
+    $value = module::get_var("th_greydragon", $setting, $default);
+    $value = self::read_session_cmdparam($cmd, $cookie, $value);
+
+    self::add_path("greydragon/css/" . $path . "/" . $value);
+  }
+
+  static function gallery_ready() {
+    self::add_path_ex("frame_pack", "framepack", "gd_framepack", "framepacks", "greydragon");
+    self::add_path_ex("color_pack", "colorpack", "gd_colorpack", "colorpacks", "greydragon");
+    self::add_path("custom");
+  }
+}
+?>
\ No newline at end of file
diff --git a/themes/greydragon/helpers/greydragon_installer.php b/themes/greydragon/helpers/greydragon_installer.php
new file mode 100644
index 0000000..4f19787
--- /dev/null
+++ b/themes/greydragon/helpers/greydragon_installer.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+class greydragon_installer {
+  static function install() {
+    site_status::warning(t("Initial configuration for the theme may be required. Visit Admin\Appearance\Theme Options before continue."), "gd_init_configuration");
+  }
+
+  static function deactivate() {
+    site_status::clear("gd_init_configuration");
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/themes/greydragon/images/apple-touch-icon.png b/themes/greydragon/images/apple-touch-icon.png
new file mode 100644
index 0000000..5017ea4
Binary files /dev/null and b/themes/greydragon/images/apple-touch-icon.png differ
diff --git a/themes/greydragon/images/arrows_left.png b/themes/greydragon/images/arrows_left.png
new file mode 100644
index 0000000..dc9dcdf
Binary files /dev/null and b/themes/greydragon/images/arrows_left.png differ
diff --git a/themes/greydragon/images/arrows_right.png b/themes/greydragon/images/arrows_right.png
new file mode 100644
index 0000000..80188c1
Binary files /dev/null and b/themes/greydragon/images/arrows_right.png differ
diff --git a/themes/greydragon/images/avatar.jpg b/themes/greydragon/images/avatar.jpg
new file mode 100644
index 0000000..71166cc
Binary files /dev/null and b/themes/greydragon/images/avatar.jpg differ
diff --git a/themes/greydragon/images/blue-grad.png b/themes/greydragon/images/blue-grad.png
new file mode 100644
index 0000000..868a657
Binary files /dev/null and b/themes/greydragon/images/blue-grad.png differ
diff --git a/themes/greydragon/images/button-grad-active-vs.png b/themes/greydragon/images/button-grad-active-vs.png
new file mode 100644
index 0000000..dc64172
Binary files /dev/null and b/themes/greydragon/images/button-grad-active-vs.png differ
diff --git a/themes/greydragon/images/button-grad-vs.png b/themes/greydragon/images/button-grad-vs.png
new file mode 100644
index 0000000..51c55a3
Binary files /dev/null and b/themes/greydragon/images/button-grad-vs.png differ
diff --git a/themes/greydragon/images/close.png b/themes/greydragon/images/close.png
new file mode 100644
index 0000000..d874f9a
Binary files /dev/null and b/themes/greydragon/images/close.png differ
diff --git a/themes/greydragon/images/donate.png b/themes/greydragon/images/donate.png
new file mode 100644
index 0000000..f36bb57
Binary files /dev/null and b/themes/greydragon/images/donate.png differ
diff --git a/themes/greydragon/images/gallery.png b/themes/greydragon/images/gallery.png
new file mode 100644
index 0000000..038b18a
Binary files /dev/null and b/themes/greydragon/images/gallery.png differ
diff --git a/themes/greydragon/images/ico-allowed.png b/themes/greydragon/images/ico-allowed.png
new file mode 100644
index 0000000..08f2493
Binary files /dev/null and b/themes/greydragon/images/ico-allowed.png differ
diff --git a/themes/greydragon/images/ico-denied-inactive.png b/themes/greydragon/images/ico-denied-inactive.png
new file mode 100644
index 0000000..56db3ff
Binary files /dev/null and b/themes/greydragon/images/ico-denied-inactive.png differ
diff --git a/themes/greydragon/images/ico-denied-passive.png b/themes/greydragon/images/ico-denied-passive.png
new file mode 100644
index 0000000..1e99223
Binary files /dev/null and b/themes/greydragon/images/ico-denied-passive.png differ
diff --git a/themes/greydragon/images/ico-denied.png b/themes/greydragon/images/ico-denied.png
new file mode 100644
index 0000000..08f2493
Binary files /dev/null and b/themes/greydragon/images/ico-denied.png differ
diff --git a/themes/greydragon/images/ico-error.png b/themes/greydragon/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon/images/ico-error.png differ
diff --git a/themes/greydragon/images/ico-help.png b/themes/greydragon/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon/images/ico-help.png differ
diff --git a/themes/greydragon/images/ico-info.png b/themes/greydragon/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon/images/ico-info.png differ
diff --git a/themes/greydragon/images/ico-lock.png b/themes/greydragon/images/ico-lock.png
new file mode 100644
index 0000000..2ebc4f6
Binary files /dev/null and b/themes/greydragon/images/ico-lock.png differ
diff --git a/themes/greydragon/images/ico-success-inactive.png b/themes/greydragon/images/ico-success-inactive.png
new file mode 100644
index 0000000..a209fb6
Binary files /dev/null and b/themes/greydragon/images/ico-success-inactive.png differ
diff --git a/themes/greydragon/images/ico-success-passive.png b/themes/greydragon/images/ico-success-passive.png
new file mode 100644
index 0000000..c8460d1
Binary files /dev/null and b/themes/greydragon/images/ico-success-passive.png differ
diff --git a/themes/greydragon/images/ico-success.png b/themes/greydragon/images/ico-success.png
new file mode 100644
index 0000000..a9925a0
Binary files /dev/null and b/themes/greydragon/images/ico-success.png differ
diff --git a/themes/greydragon/images/ico-warning.png b/themes/greydragon/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon/images/ico-warning.png differ
diff --git a/themes/greydragon/images/missing-img.png b/themes/greydragon/images/missing-img.png
new file mode 100644
index 0000000..12b7394
Binary files /dev/null and b/themes/greydragon/images/missing-img.png differ
diff --git a/themes/greydragon/js/gallery.ajax.custom.js b/themes/greydragon/js/gallery.ajax.custom.js
new file mode 100644
index 0000000..5be029f
--- /dev/null
+++ b/themes/greydragon/js/gallery.ajax.custom.js
@@ -0,0 +1,14 @@
+(function($) {
+  $.widget("ui.gallery_ajax",  {
+    _init: function() {
+      this.element.click(function(event) {
+        eval("var ajax_handler = " + $(event.currentTarget).attr("ajax_handler"));
+        $.get($(event.currentTarget).attr("href"), function(data) {
+          ajax_handler(data);
+        });
+        event.preventDefault();
+        return false;
+      });
+    }
+  });
+})(jQuery);
diff --git a/themes/greydragon/js/gallery.dialog.custom.js b/themes/greydragon/js/gallery.dialog.custom.js
new file mode 100644
index 0000000..2e3b8a1
--- /dev/null
+++ b/themes/greydragon/js/gallery.dialog.custom.js
@@ -0,0 +1,232 @@
+(function($) { 
+  var fixDialogAutoWidth = $.noop; 
+
+  jQuery.browser = {};
+  jQuery.browser.mozilla = /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase());
+  jQuery.browser.webkit = /webkit/.test(navigator.userAgent.toLowerCase());
+  jQuery.browser.opera = /opera/.test(navigator.userAgent.toLowerCase());
+  jQuery.browser.msie = /msie/.test(navigator.userAgent.toLowerCase());
+
+  if ( $.browser.msie ) { 
+    fixDialogAutoWidth = function(content) { 
+      var dialog = $(content).parent('.ui-dialog'); 
+      var width = dialog.innerWidth(); 
+      if ( width ) dialog.css('width', width); 
+    } 
+  } 
+ 
+  var _init = $.ui.dialog.prototype._init; 
+  $.ui.dialog.prototype._init = function() { 
+    // IE magick: (width: 'auto' not working correctly) : 
+    // http://dev.jqueryui.com/ticket/4437 
+    if ( this.options.width == 'auto' ) { 
+      var open = this.options.open; 
+      this.options.open = function() { 
+        fixDialogAutoWidth(this); 
+        if ( open ) open.apply(this); 
+      } 
+    } 
+    // yet another bug options.hide: 'drop' does not work 
+    // in IE http://dev.jqueryui.com/ticket/5615 
+    if ( $.browser.msie && this.options.hide == 'drop' ) { 
+      this.options.hide = 'fold'; 
+    } 
+    return _init.apply(this); // calls open() if autoOpen 
+  }; 
+
+  $.widget("ui.gallery_dialog",  {
+    _init: function() {
+      var self = this;
+      if (!self.options.immediate) {
+        this.element.click(function(event) {
+          event.preventDefault();
+          self._show($(event.currentTarget).attr("href"));
+          return false;
+        });
+      } else {
+        self._show(this.element.attr("href"));
+      }
+    },
+
+    _show: function(sHref) {
+      var self = this;
+      var eDialog = '<div id="g-dialog"></div>';
+
+      if ($("#g-dialog").length) {
+        $("#g-dialog").dialog("close");
+      }
+      $("body").append(eDialog);
+
+      if (!self.options.close) {
+        self.options.close = self.close_dialog;
+      }
+      $("#g-dialog").dialog(self.options);
+      $("#g-dialog").dialog('option', 'resizable', false);
+
+      $("#g-dialog").gallery_show_loading();
+
+      $.ajax({
+        url: sHref,
+        type: "GET",
+        success: function(data, textStatus, xhr) {
+          var mimeType = /^(\w+\/\w+)\;?/.exec(xhr.getResponseHeader("Content-Type"));
+
+          var content = "";
+          if (mimeType[1] == "application/json") {
+            data = JSON.parse(data);
+            content = data.html;
+          } else {
+            content = data;
+          }
+
+          $("#g-dialog").html(content).gallery_show_loading();
+
+          if ($("#g-dialog form").length) {
+            self.form_loaded(null, $("#g-dialog form"));
+          }
+          self._layout();
+
+          $("#g-dialog").dialog("open");
+          self._set_title();
+
+          if ($("#g-dialog form").length) {
+            self._ajaxify_dialog();
+          }
+        }
+      });
+      $("#g-dialog").dialog("option", "self", self);
+    },
+
+    error: function(xhr, textStatus, errorThrown) {
+      $("#g-dialog").html(xhr.responseText);
+      self._set_title();
+      self._layout();
+    },
+
+    _layout: function() {
+      var dialogWidth;
+      var dialogHeight = $("#g-dialog").height();
+      var cssWidth = new String($("#g-dialog form").css("width"));
+      var childWidth = cssWidth.replace(/[^0-9]/g,"");
+      var size = $.gallery_get_viewport_size();
+      if ($("#g-dialog iframe").length) {
+        dialogWidth = size.width() - 100;
+        // Set the iframe width and height
+        $("#g-dialog iframe").width("100%").height(size.height() - 100);
+      } else if ($("#g-dialog .g-dialog-panel").length) {
+        dialogWidth = size.width() - 100;
+        $("#g-dialog").dialog("option", "height", size.height() - 100);
+      } else if (childWidth == "" ) {
+        dialogWidth = 500;
+      } else {
+        dialogWidth = parseInt(childWidth) + 28;
+      }
+
+      var leftPos = (size.width() - dialogWidth) / 2;
+      var rightPos = (size.height() - dialogHeight) / 2;
+
+      $("#g-dialog").dialog('option', 'width', dialogWidth);
+      $("#g-dialog").dialog('option', 'position', [leftPos, rightPos]);
+    },
+
+    form_loaded: function(event, ui) {
+      // Should be defined (and localized) in the theme
+      MSG_CANCEL = MSG_CANCEL || 'Cancel';
+      var eCancel = '<a href="#" class="g-cancel g-left">' + MSG_CANCEL + '</a>';
+      if ($("#g-dialog .submit").length) {
+        $("#g-dialog .submit").addClass("ui-state-default ui-corner-all");
+        $.fn.gallery_hover_init();
+        $("#g-dialog .submit").parent().append(eCancel);
+        $("#g-dialog .g-cancel").click(function(event) {
+          $("#g-dialog").dialog("close");
+          event.preventDefault();
+        });
+      }
+      $("#g-dialog .ui-state-default").hover(
+        function() {
+          $(this).addClass("ui-state-hover");
+        },
+        function() {
+          $(this).removeClass("ui-state-hover");
+        }
+      );
+    },
+
+    close_dialog: function(event, ui) {
+       var self = $("#g-dialog").dialog("option", "self");
+       if ($("#g-dialog form").length) {
+         self._trigger("form_closing", null, $("#g-dialog form"));
+       }
+       self._trigger("dialog_closing", null, $("#g-dialog"));
+       $("#g-dialog").dialog("destroy").remove();
+     },
+
+     _ajaxify_dialog: function() {
+       var self = this;
+       $("#g-dialog form").ajaxForm({
+         dataType: 'json',
+         beforeSubmit: function(formData, form, options) {
+           form.find(":submit")
+             .addClass("ui-state-disabled")
+             .attr("disabled", "disabled");
+           return true;
+         },
+         success: function(data) {
+           if (data.html) {
+             $("#g-dialog").html(data.html);
+             $("#g-dialog").dialog("option", "position", "center");
+             $("#g-dialog form :submit").removeClass("ui-state-disabled")
+               .attr("disabled", null);
+             self._set_title();
+             self._ajaxify_dialog();
+             self.form_loaded(null, $("#g-dialog form"));
+             if (typeof data.reset == 'function') {
+               eval(data.reset + '()');
+             }
+           }
+           if (data.result == "success") {
+             if (data.location) {
+               window.location = data.location;
+             } else {
+               window.location.reload();
+             }
+           }
+         },
+         error: function(xhr, textStatus, errorThrown) {
+           $("#g-dialog").html(xhr.responseText);
+           self._set_title();
+           self._layout();         
+         }
+       });
+     },
+
+     _set_title: function() {
+       // Remove titlebar for progress dialogs or set title
+       if ($("#g-dialog #g-progress").length) {
+         $(".ui-dialog-titlebar").remove();
+       } else if ($("#g-dialog h1").length) {
+         $("#g-dialog").dialog('option', 'title', $("#g-dialog h1:eq(0)").html());
+         $("#g-dialog h1:eq(0)").hide();
+       } else if ($("#g-dialog fieldset legend").length) {
+         $("#g-dialog").dialog('option', 'title', $("#g-dialog fieldset legend:eq(0)").html());
+       }
+     },
+
+     form_closing: function(event, ui) {},
+     dialog_closing: function(event, ui) {}
+   });
+
+   $.extend($.ui.gallery_dialog,  {
+     defaults: {
+         autoResize: false
+        ,show: 'clip'
+        ,hide: 'clip'
+        ,height: 'auto'
+        ,width: 'auto'
+        ,autoOpen: false
+        ,modal: true
+        ,position: 'center'
+        ,draggable: false
+     }
+   });
+})(jQuery);
diff --git a/themes/greydragon/js/jquery-ui.min.js b/themes/greydragon/js/jquery-ui.min.js
new file mode 100644
index 0000000..efbd3e5
--- /dev/null
+++ b/themes/greydragon/js/jquery-ui.min.js
@@ -0,0 +1,7 @@
+/*! jQuery UI - v1.10.4 - 2014-03-16
+* http://jqueryui.com
+* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+
+(function(e,t){function i(t,i){var s,a,o,r=t.nodeName.toLowerCase();return"area"===r?(s=t.parentNode,a=s.name,t.href&&a&&"map"===s.nodeName.toLowerCase()?(o=e("img[usemap=#"+a+"]")[0],!!o&&n(o)):!1):(/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||i:i)&&n(t)}function n(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var s=0,a=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.4",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,n){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),n&&n.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var n,s,a=e(this[0]);a.length&&a[0]!==document;){if(n=a.css("position"),("absolute"===n||"relative"===n||"fixed"===n)&&(s=parseInt(a.css("zIndex"),10),!isNaN(s)&&0!==s))return s;a=a.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++s)})},removeUniqueId:function(){return this.each(function(){a.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,n){return!!e.data(t,n[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),s=isNaN(n);return(s||n>=0)&&i(t,!s)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,n){function s(t,i,n,s){return e.each(a,function(){i-=parseFloat(e.css(t,"padding"+this))||0,n&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var a="Width"===n?["Left","Right"]:["Top","Bottom"],o=n.toLowerCase(),r={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+n]=function(i){return i===t?r["inner"+n].call(this):this.each(function(){e(this).css(o,s(this,i)+"px")})},e.fn["outer"+n]=function(t,i){return"number"!=typeof t?r["outer"+n].call(this,t):this.each(function(){e(this).css(o,s(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,n){var s,a=e.ui[t].prototype;for(s in n)a.plugins[s]=a.plugins[s]||[],a.plugins[s].push([i,n[s]])},call:function(e,t,i){var n,s=e.plugins[t];if(s&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(n=0;s.length>n;n++)e.options[s[n][0]]&&s[n][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var n=i&&"left"===i?"scrollLeft":"scrollTop",s=!1;return t[n]>0?!0:(t[n]=1,s=t[n]>0,t[n]=0,s)}})})(jQuery);(function(t,e){var i=0,s=Array.prototype.slice,n=t.cleanData;t.cleanData=function(e){for(var i,s=0;null!=(i=e[s]);s++)try{t(i).triggerHandler("remove")}catch(o){}n(e)},t.widget=function(i,s,n){var o,a,r,h,l={},c=i.split(".")[0];i=i.split(".")[1],o=c+"-"+i,n||(n=s,s=t.Widget),t.expr[":"][o.toLowerCase()]=function(e){return!!t.data(e,o)},t[c]=t[c]||{},a=t[c][i],r=t[c][i]=function(t,i){return this._createWidget?(arguments.length&&this._createWidget(t,i),e):new r(t,i)},t.extend(r,a,{version:n.version,_proto:t.extend({},n),_childConstructors:[]}),h=new s,h.options=t.widget.extend({},h.options),t.each(n,function(i,n){return t.isFunction(n)?(l[i]=function(){var t=function(){return s.prototype[i].apply(this,arguments)},e=function(t){return s.prototype[i].apply(this,t)};return function(){var i,s=this._super,o=this._superApply;return this._super=t,this._superApply=e,i=n.apply(this,arguments),this._super=s,this._superApply=o,i}}(),e):(l[i]=n,e)}),r.prototype=t.widget.extend(h,{widgetEventPrefix:a?h.widgetEventPrefix||i:i},l,{constructor:r,namespace:c,widgetName:i,widgetFullName:o}),a?(t.each(a._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,r,i._proto)}),delete a._childConstructors):s._childConstructors.push(r),t.widget.bridge(i,r)},t.widget.extend=function(i){for(var n,o,a=s.call(arguments,1),r=0,h=a.length;h>r;r++)for(n in a[r])o=a[r][n],a[r].hasOwnProperty(n)&&o!==e&&(i[n]=t.isPlainObject(o)?t.isPlainObject(i[n])?t.widget.extend({},i[n],o):t.widget.extend({},o):o);return i},t.widget.bridge=function(i,n){var o=n.prototype.widgetFullName||i;t.fn[i]=function(a){var r="string"==typeof a,h=s.call(arguments,1),l=this;return a=!r&&h.length?t.widget.extend.apply(null,[a].concat(h)):a,r?this.each(function(){var s,n=t.data(this,o);return n?t.isFunction(n[a])&&"_"!==a.charAt(0)?(s=n[a].apply(n,h),s!==n&&s!==e?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):e):t.error("no such method '"+a+"' for "+i+" widget instance"):t.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+a+"'")}):this.each(function(){var e=t.data(this,o);e?e.option(a||{})._init():t.data(this,o,new n(a,this))}),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this.bindings=t(),this.hoverable=t(),this.focusable=t(),s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(i,s){var n,o,a,r=i;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof i)if(r={},n=i.split("."),i=n.shift(),n.length){for(o=r[i]=t.widget.extend({},this.options[i]),a=0;n.length-1>a;a++)o[n[a]]=o[n[a]]||{},o=o[n[a]];if(i=n.pop(),1===arguments.length)return o[i]===e?null:o[i];o[i]=s}else{if(1===arguments.length)return this.options[i]===e?null:this.options[i];r[i]=s}return this._setOptions(r),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!e).attr("aria-disabled",e),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var o,a=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=o=t(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,o=this.widget()),t.each(n,function(n,r){function h(){return i||a.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof r?a[r]:r).apply(a,arguments):e}"string"!=typeof r&&(h.guid=r.guid=r.guid||h.guid||t.guid++);var l=n.match(/^(\w+)\s*(.*)$/),c=l[1]+a.eventNamespace,u=l[2];u?o.delegate(u,c,h):s.bind(c,h)})},_off:function(t,e){e=(e||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(e).undelegate(e)},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}})})(jQuery);(function(t){var e=!1;t(document).mouseup(function(){e=!1}),t.widget("ui.mouse",{version:"1.10.4",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.bind("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).bind("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!e){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?t(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===t.data(i.target,this.widgetName+".preventClickEvent")&&t.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return s._mouseMove(t)},this._mouseUpDelegate=function(t){return s._mouseUp(t)},t(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),e=!0,!0)):!0}},_mouseMove:function(e){return t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button?this._mouseUp(e):this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){return t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),!1},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(t,e){function i(t,e,i){return[parseFloat(t[0])*(p.test(t[0])?e/100:1),parseFloat(t[1])*(p.test(t[1])?i/100:1)]}function s(e,i){return parseInt(t.css(e,i),10)||0}function n(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}t.ui=t.ui||{};var a,o=Math.max,r=Math.abs,l=Math.round,h=/left|center|right/,c=/top|center|bottom/,u=/[\+\-]\d+(\.[\d]+)?%?/,d=/^\w+/,p=/%$/,f=t.fn.position;t.position={scrollbarWidth:function(){if(a!==e)return a;var i,s,n=t("<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=n.children()[0];return t("body").append(n),i=o.offsetWidth,n.css("overflow","scroll"),s=o.offsetWidth,i===s&&(s=n[0].clientWidth),n.remove(),a=i-s},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,a="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:a?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]),n=!!i[0]&&9===i[0].nodeType;return{element:i,isWindow:s,isDocument:n,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s?i.width():i.outerWidth(),height:s?i.height():i.outerHeight()}}},t.fn.position=function(e){if(!e||!e.of)return f.apply(this,arguments);e=t.extend({},e);var a,p,g,m,v,_,b=t(e.of),y=t.position.getWithinInfo(e.within),k=t.position.getScrollInfo(y),w=(e.collision||"flip").split(" "),D={};return _=n(b),b[0].preventDefault&&(e.at="left top"),p=_.width,g=_.height,m=_.offset,v=t.extend({},m),t.each(["my","at"],function(){var t,i,s=(e[this]||"").split(" ");1===s.length&&(s=h.test(s[0])?s.concat(["center"]):c.test(s[0])?["center"].concat(s):["center","center"]),s[0]=h.test(s[0])?s[0]:"center",s[1]=c.test(s[1])?s[1]:"center",t=u.exec(s[0]),i=u.exec(s[1]),D[this]=[t?t[0]:0,i?i[0]:0],e[this]=[d.exec(s[0])[0],d.exec(s[1])[0]]}),1===w.length&&(w[1]=w[0]),"right"===e.at[0]?v.left+=p:"center"===e.at[0]&&(v.left+=p/2),"bottom"===e.at[1]?v.top+=g:"center"===e.at[1]&&(v.top+=g/2),a=i(D.at,p,g),v.left+=a[0],v.top+=a[1],this.each(function(){var n,h,c=t(this),u=c.outerWidth(),d=c.outerHeight(),f=s(this,"marginLeft"),_=s(this,"marginTop"),x=u+f+s(this,"marginRight")+k.width,C=d+_+s(this,"marginBottom")+k.height,M=t.extend({},v),T=i(D.my,c.outerWidth(),c.outerHeight());"right"===e.my[0]?M.left-=u:"center"===e.my[0]&&(M.left-=u/2),"bottom"===e.my[1]?M.top-=d:"center"===e.my[1]&&(M.top-=d/2),M.left+=T[0],M.top+=T[1],t.support.offsetFractions||(M.left=l(M.left),M.top=l(M.top)),n={marginLeft:f,marginTop:_},t.each(["left","top"],function(i,s){t.ui.position[w[i]]&&t.ui.position[w[i]][s](M,{targetWidth:p,targetHeight:g,elemWidth:u,elemHeight:d,collisionPosition:n,collisionWidth:x,collisionHeight:C,offset:[a[0]+T[0],a[1]+T[1]],my:e.my,at:e.at,within:y,elem:c})}),e.using&&(h=function(t){var i=m.left-M.left,s=i+p-u,n=m.top-M.top,a=n+g-d,l={target:{element:b,left:m.left,top:m.top,width:p,height:g},element:{element:c,left:M.left,top:M.top,width:u,height:d},horizontal:0>s?"left":i>0?"right":"center",vertical:0>a?"top":n>0?"bottom":"middle"};u>p&&p>r(i+s)&&(l.horizontal="center"),d>g&&g>r(n+a)&&(l.vertical="middle"),l.important=o(r(i),r(s))>o(r(n),r(a))?"horizontal":"vertical",e.using.call(this,t,l)}),c.offset(t.extend(M,{using:h}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,l=n-r,h=r+e.collisionWidth-a-n;e.collisionWidth>a?l>0&&0>=h?(i=t.left+l+e.collisionWidth-a-n,t.left+=l-i):t.left=h>0&&0>=l?n:l>h?n+a-e.collisionWidth:n:l>0?t.left+=l:h>0?t.left-=h:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,l=n-r,h=r+e.collisionHeight-a-n;e.collisionHeight>a?l>0&&0>=h?(i=t.top+l+e.collisionHeight-a-n,t.top+=l-i):t.top=h>0&&0>=l?n:l>h?n+a-e.collisionHeight:n:l>0?t.top+=l:h>0?t.top-=h:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,a=n.offset.left+n.scrollLeft,o=n.width,l=n.isWindow?n.scrollLeft:n.offset.left,h=t.left-e.collisionPosition.marginLeft,c=h-l,u=h+e.collisionWidth-o-l,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-o-a,(0>i||r(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-l,(s>0||u>r(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,a=n.offset.top+n.scrollTop,o=n.height,l=n.isWindow?n.scrollTop:n.offset.top,h=t.top-e.collisionPosition.marginTop,c=h-l,u=h+e.collisionHeight-o-l,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-o-a,t.top+p+f+g>c&&(0>s||r(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-l,t.top+p+f+g>u&&(i>0||u>r(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}},function(){var e,i,s,n,a,o=document.getElementsByTagName("body")[0],r=document.createElement("div");e=document.createElement(o?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&t.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(a in s)e.style[a]=s[a];e.appendChild(r),i=o||document.documentElement,i.insertBefore(e,i.firstChild),r.style.cssText="position: absolute; left: 10.7432222px;",n=t(r).offset().left,t.support.offsetFractions=n>10&&11>n,e.innerHTML="",i.removeChild(e)}()})(jQuery);(function(t){t.widget("ui.draggable",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(t(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){t("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(t(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_mouseDrag:function(e,i){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"original"!==this.options.helper||t.contains(this.element[0].ownerDocument,this.element[0])?("invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1):!1},_mouseUp:function(e){return t("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return s.parents("body").length||s.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s[0]===this.element[0]||/(fixed|absolute)/.test(s.css("position"))||s.css("position","absolute"),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.element.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;return n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):"document"===n.containment?(this.containment=[0,0,t(document).width()-this.helperProportions.width-this.margins.left,(t(document).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):n.containment.constructor===Array?(this.containment=n.containment,undefined):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e="hidden"!==i.css("overflow"),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=i),undefined):(this.containment=null,undefined)},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent;return this.offset.scroll||(this.offset.scroll={top:n.scrollTop(),left:n.scrollLeft()}),{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top)*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)*s}},_generatePosition:function(e){var i,s,n,a,o=this.options,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,l=e.pageX,h=e.pageY;return this.offset.scroll||(this.offset.scroll={top:r.scrollTop(),left:r.scrollLeft()}),this.originalPosition&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.left<i[0]&&(l=i[0]+this.offset.click.left),e.pageY-this.offset.click.top<i[1]&&(h=i[1]+this.offset.click.top),e.pageX-this.offset.click.left>i[2]&&(l=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(h=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,h=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((l-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,l=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a)),{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top),left:l-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s]),"drag"===e&&(this.positionAbs=this._convertPositionTo("absolute")),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i){var s=t(this).data("ui-draggable"),n=s.options,a=t.extend({},i,{item:s.element});s.sortables=[],t(n.connectToSortable).each(function(){var i=t.data(this,"ui-sortable");i&&!i.options.disabled&&(s.sortables.push({instance:i,shouldRevert:i.options.revert}),i.refreshPositions(),i._trigger("activate",e,a))})},stop:function(e,i){var s=t(this).data("ui-draggable"),n=t.extend({},i,{item:s.element});t.each(s.sortables,function(){this.instance.isOver?(this.instance.isOver=0,s.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(e),this.instance.options.helper=this.instance.options._helper,"original"===s.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",e,n))})},drag:function(e,i){var s=t(this).data("ui-draggable"),n=this;t.each(s.sortables,function(){var a=!1,o=this;this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(a=!0,t.each(s.sortables,function(){return this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&t.contains(o.instance.element[0],this.instance.element[0])&&(a=!1),a})),a?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=t(n).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return i.helper[0]},e.target=this.instance.currentItem[0],this.instance._mouseCapture(e,!0),this.instance._mouseStart(e,!0,!0),this.instance.offset.click.top=s.offset.click.top,this.instance.offset.click.left=s.offset.click.left,this.instance.offset.parent.left-=s.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=s.offset.parent.top-this.instance.offset.parent.top,s._trigger("toSortable",e),s.dropped=this.instance.element,s.currentItem=s.element,this.instance.fromOutside=s),this.instance.currentItem&&this.instance._mouseDrag(e)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",e,this.instance._uiHash(this.instance)),this.instance._mouseStop(e,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),s._trigger("fromSortable",e),s.dropped=!1)})}}),t.ui.plugin.add("draggable","cursor",{start:function(){var e=t("body"),i=t(this).data("ui-draggable").options;e.css("cursor")&&(i._cursor=e.css("cursor")),e.css("cursor",i.cursor)},stop:function(){var e=t(this).data("ui-draggable").options;e._cursor&&t("body").css("cursor",e._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("opacity")&&(n._opacity=s.css("opacity")),s.css("opacity",n.opacity)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._opacity&&t(i.helper).css("opacity",s._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(){var e=t(this).data("ui-draggable");e.scrollParent[0]!==document&&"HTML"!==e.scrollParent[0].tagName&&(e.overflowOffset=e.scrollParent.offset())},drag:function(e){var i=t(this).data("ui-draggable"),s=i.options,n=!1;i.scrollParent[0]!==document&&"HTML"!==i.scrollParent[0].tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-e.pageY<s.scrollSensitivity?i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop+s.scrollSpeed:e.pageY-i.overflowOffset.top<s.scrollSensitivity&&(i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop-s.scrollSpeed)),s.axis&&"y"===s.axis||(i.overflowOffset.left+i.scrollParent[0].offsetWidth-e.pageX<s.scrollSensitivity?i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft+s.scrollSpeed:e.pageX-i.overflowOffset.left<s.scrollSensitivity&&(i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft-s.scrollSpeed))):(s.axis&&"x"===s.axis||(e.pageY-t(document).scrollTop()<s.scrollSensitivity?n=t(document).scrollTop(t(document).scrollTop()-s.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<s.scrollSensitivity&&(n=t(document).scrollTop(t(document).scrollTop()+s.scrollSpeed))),s.axis&&"y"===s.axis||(e.pageX-t(document).scrollLeft()<s.scrollSensitivity?n=t(document).scrollLeft(t(document).scrollLeft()-s.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<s.scrollSensitivity&&(n=t(document).scrollLeft(t(document).scrollLeft()+s.scrollSpeed)))),n!==!1&&t.ui.ddmanager&&!s.dropBehaviour&&t.ui.ddmanager.prepareOffsets(i,e)}}),t.ui.plugin.add("draggable","snap",{start:function(){var e=t(this).data("ui-draggable"),i=e.options;e.snapElements=[],t(i.snap.constructor!==String?i.snap.items||":data(ui-draggable)":i.snap).each(function(){var i=t(this),s=i.offset();this!==e.element[0]&&e.snapElements.push({item:this,width:i.outerWidth(),height:i.outerHeight(),top:s.top,left:s.left})})},drag:function(e,i){var s,n,a,o,r,l,h,c,u,d,p=t(this).data("ui-draggable"),g=p.options,f=g.snapTolerance,m=i.offset.left,_=m+p.helperProportions.width,v=i.offset.top,b=v+p.helperProportions.height;for(u=p.snapElements.length-1;u>=0;u--)r=p.snapElements[u].left,l=r+p.snapElements[u].width,h=p.snapElements[u].top,c=h+p.snapElements[u].height,r-f>_||m>l+f||h-f>b||v>c+f||!t.contains(p.snapElements[u].item.ownerDocument,p.snapElements[u].item)?(p.snapElements[u].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=!1):("inner"!==g.snapMode&&(s=f>=Math.abs(h-b),n=f>=Math.abs(c-v),a=f>=Math.abs(r-_),o=f>=Math.abs(l-m),s&&(i.position.top=p._convertPositionTo("relative",{top:h-p.helperProportions.height,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r-p.helperProportions.width}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:l}).left-p.margins.left)),d=s||n||a||o,"outer"!==g.snapMode&&(s=f>=Math.abs(h-v),n=f>=Math.abs(c-b),a=f>=Math.abs(r-m),o=f>=Math.abs(l-_),s&&(i.position.top=p._convertPositionTo("relative",{top:h,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c-p.helperProportions.height,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:l-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[u].snapping&&(s||n||a||o||d)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=s||n||a||o||d)}}),t.ui.plugin.add("draggable","stack",{start:function(){var e,i=this.data("ui-draggable").options,s=t.makeArray(t(i.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});s.length&&(e=parseInt(t(s[0]).css("zIndex"),10)||0,t(s).each(function(i){t(this).css("zIndex",e+i)}),this.css("zIndex",e+s.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("zIndex")&&(n._zIndex=s.css("zIndex")),s.css("zIndex",n.zIndex)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._zIndex&&t(i.helper).css("zIndex",s._zIndex)}})})(jQuery);(function(t){function e(t,e,i){return t>e&&e+i>t}t.widget("ui.droppable",{version:"1.10.4",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var e,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=t.isFunction(s)?s:function(t){return t.is(s)},this.proportions=function(){return arguments.length?(e=arguments[0],undefined):e?e:e={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},t.ui.ddmanager.droppables[i.scope]=t.ui.ddmanager.droppables[i.scope]||[],t.ui.ddmanager.droppables[i.scope].push(this),i.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){for(var e=0,i=t.ui.ddmanager.droppables[this.options.scope];i.length>e;e++)i[e]===this&&i.splice(e,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(e,i){"accept"===e&&(this.accept=t.isFunction(i)?i:function(t){return t.is(i)}),t.Widget.prototype._setOption.apply(this,arguments)},_activate:function(e){var i=t.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",e,this.ui(i))},_deactivate:function(e){var i=t.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",e,this.ui(i))},_over:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",e,this.ui(i)))},_out:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",e,this.ui(i)))},_drop:function(e,i){var s=i||t.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var e=t.data(this,"ui-droppable");return e.options.greedy&&!e.options.disabled&&e.options.scope===s.options.scope&&e.accept.call(e.element[0],s.currentItem||s.element)&&t.ui.intersect(s,t.extend(e,{offset:e.element.offset()}),e.options.tolerance)?(n=!0,!1):undefined}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",e,this.ui(s)),this.element):!1):!1},ui:function(t){return{draggable:t.currentItem||t.element,helper:t.helper,position:t.position,offset:t.positionAbs}}}),t.ui.intersect=function(t,i,s){if(!i.offset)return!1;var n,a,o=(t.positionAbs||t.position.absolute).left,r=(t.positionAbs||t.position.absolute).top,l=o+t.helperProportions.width,h=r+t.helperProportions.height,c=i.offset.left,u=i.offset.top,d=c+i.proportions().width,p=u+i.proportions().height;switch(s){case"fit":return o>=c&&d>=l&&r>=u&&p>=h;case"intersect":return o+t.helperProportions.width/2>c&&d>l-t.helperProportions.width/2&&r+t.helperProportions.height/2>u&&p>h-t.helperProportions.height/2;case"pointer":return n=(t.positionAbs||t.position.absolute).left+(t.clickOffset||t.offset.click).left,a=(t.positionAbs||t.position.absolute).top+(t.clickOffset||t.offset.click).top,e(a,u,i.proportions().height)&&e(n,c,i.proportions().width);case"touch":return(r>=u&&p>=r||h>=u&&p>=h||u>r&&h>p)&&(o>=c&&d>=o||l>=c&&d>=l||c>o&&l>d);default:return!1}},t.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,i){var s,n,a=t.ui.ddmanager.droppables[e.options.scope]||[],o=i?i.type:null,r=(e.currentItem||e.element).find(":data(ui-droppable)").addBack();t:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||e&&!a[s].accept.call(a[s].element[0],e.currentItem||e.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions().height=0;continue t}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions({width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight}))}},drop:function(e,i){var s=!1;return t.each((t.ui.ddmanager.droppables[e.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&t.ui.intersect(e,this,this.options.tolerance)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],e.currentItem||e.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(e,i){e.element.parentsUntil("body").bind("scroll.droppable",function(){e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)})},drag:function(e,i){e.options.refreshPositions&&t.ui.ddmanager.prepareOffsets(e,i),t.each(t.ui.ddmanager.droppables[e.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=t.ui.intersect(e,this,this.options.tolerance),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return t.data(this,"ui-droppable").options.scope===n}),a.length&&(s=t.data(a[0],"ui-droppable"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(e,i){e.element.parentsUntil("body").unbind("scroll.droppable"),e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)}}})(jQuery);(function(t){function e(t){return parseInt(t,10)||0}function i(t){return!isNaN(parseInt(t,10))}t.widget("ui.resizable",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var e,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(t("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),e=this.handles.split(","),this.handles={},i=0;e.length>i;i++)s=t.trim(e[i]),a="ui-resizable-"+s,n=t("<div class='ui-resizable-handle "+a+"'></div>"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(e){var i,s,n,a;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=t(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=t(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,a),this._proportionallyResize()),t(this.handles[i]).length},this._renderAxis(this.element),this._handles=t(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),t(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(t(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(t(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=e(this.helper.css("left")),n=e(this.helper.css("top")),o.containment&&(s+=t(o.containment).scrollLeft()||0,n+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(e){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,c=this.size.height,u=e.pageX-a.left||0,d=e.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[e,u,d]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==c&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(n)||this._trigger("resize",e,this.ui()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&t.ui.hasScroll(i[0],"left")?0:c.sizeDiff.height,a=s?0:c.sizeDiff.width,o={width:c.helper.width()-a,height:c.helper.height()-n},r=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null,h=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(o,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(t){var e,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),i(t.left)&&(this.position.left=t.left),i(t.top)&&(this.position.top=t.top),i(t.height)&&(this.size.height=t.height),i(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,s=this.size,n=this.axis;return i(t.height)?t.width=t.height*this.aspectRatio:i(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===n&&(t.left=e.left+(s.width-t.width),t.top=null),"nw"===n&&(t.top=e.top+(s.height-t.height),t.left=e.left+(s.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,s=this.axis,n=i(t.width)&&e.maxWidth&&e.maxWidth<t.width,a=i(t.height)&&e.maxHeight&&e.maxHeight<t.height,o=i(t.width)&&e.minWidth&&e.minWidth>t.width,r=i(t.height)&&e.minHeight&&e.minHeight>t.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,c=/sw|nw|w/.test(s),u=/nw|ne|n/.test(s);return o&&(t.width=e.minWidth),r&&(t.height=e.minHeight),n&&(t.width=e.maxWidth),a&&(t.height=e.maxHeight),o&&c&&(t.left=h-e.minWidth),n&&c&&(t.left=h-e.maxWidth),r&&u&&(t.top=l-e.minHeight),a&&u&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var t,e,i,s,n,a=this.helper||this.element;for(t=0;this._proportionallyResizeElements.length>t;t++){if(n=this._proportionallyResizeElements[t],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],e=0;i.length>e;e++)this.borderDif[e]=(parseInt(i[e],10)||0)+(parseInt(s[e],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&t.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,c=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=t(this).data("ui-resizable"),c=l.options,u=l.element,d=c.containment,p=d instanceof t?d.get(0):/parent/.test(d)?u.parent().get(0):d;p&&(l.containerElement=t(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(i=t(p),s=[],t(["Top","Right","Left","Bottom"]).each(function(t,n){s[t]=e(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=t.ui.hasScroll(p,"left")?p.scrollWidth:o,h=t.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(e){var i,s,n,a,o=t(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,c=o._aspectRatio||e.shiftKey,u={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-u.left),c&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),c&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-u.left:o.offset.left-u.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-u.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=Math.abs(o.parentData.left)),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,c&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,c&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.containerOffset,n=e.containerPosition,a=e.containerElement,o=t(e.helper),r=o.offset(),h=o.outerWidth()-e.sizeDiff.width,l=o.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(a.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(a.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=function(e){t(e).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseInt(e.width(),10),height:parseInt(e.height(),10),left:parseInt(e.css("left"),10),top:parseInt(e.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):t.each(i.alsoResize,function(t){s(t)})},resize:function(e,i){var s=t(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(e,s){t(e).each(function(){var e=t(this),n=t(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(n[e]||0)+(r[e]||0);i&&i>=0&&(a[e]=i||null)}),e.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):t.each(n.alsoResize,function(t,e){h(t,e)})},stop:function(){t(this).removeData("resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).data("ui-resizable");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).data("ui-resizable");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size,n=e.originalSize,a=e.originalPosition,o=e.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,c=Math.round((s.width-n.width)/h)*h,u=Math.round((s.height-n.height)/l)*l,d=n.width+c,p=n.height+u,f=i.maxWidth&&d>i.maxWidth,g=i.maxHeight&&p>i.maxHeight,m=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,m&&(d+=h),v&&(p+=l),f&&(d-=h),g&&(p-=l),/^(se|s|e)$/.test(o)?(e.size.width=d,e.size.height=p):/^(ne)$/.test(o)?(e.size.width=d,e.size.height=p,e.position.top=a.top-u):/^(sw)$/.test(o)?(e.size.width=d,e.size.height=p,e.position.left=a.left-c):(p-l>0?(e.size.height=p,e.position.top=a.top-u):(e.size.height=l,e.position.top=a.top+n.height-l),d-h>0?(e.size.width=d,e.position.left=a.left-c):(e.size.width=h,e.position.left=a.left+n.width-h))}})})(jQuery);(function(t){t.widget("ui.selectable",t.ui.mouse,{version:"1.10.4",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var e,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){e=t(i.options.filter,i.element[0]),e.addClass("ui-selectee"),e.each(function(){var e=t(this),i=e.offset();t.data(this,"selectable-item",{element:this,$element:e,left:i.left,top:i.top,right:i.left+e.outerWidth(),bottom:i.top+e.outerHeight(),startselected:!1,selected:e.hasClass("ui-selected"),selecting:e.hasClass("ui-selecting"),unselecting:e.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=e.addClass("ui-selectee"),this._mouseInit(),this.helper=t("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(e){var i=this,s=this.options;this.opos=[e.pageX,e.pageY],this.options.disabled||(this.selectees=t(s.filter,this.element[0]),this._trigger("start",e),t(s.appendTo).append(this.helper),this.helper.css({left:e.pageX,top:e.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=t.data(this,"selectable-item");s.startselected=!0,e.metaKey||e.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",e,{unselecting:s.element}))}),t(e.target).parents().addBack().each(function(){var s,n=t.data(this,"selectable-item");return n?(s=!e.metaKey&&!e.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",e,{selecting:n.element}):i._trigger("unselecting",e,{unselecting:n.element}),!1):undefined}))},_mouseDrag:function(e){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=e.pageX,l=e.pageY;return a>r&&(i=r,r=a,a=i),o>l&&(i=l,l=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:l-o}),this.selectees.each(function(){var i=t.data(this,"selectable-item"),h=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?h=!(i.left>r||a>i.right||i.top>l||o>i.bottom):"fit"===n.tolerance&&(h=i.left>a&&r>i.right&&i.top>o&&l>i.bottom),h?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",e,{selecting:i.element}))):(i.selecting&&((e.metaKey||e.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",e,{unselecting:i.element}))),i.selected&&(e.metaKey||e.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",e,{unselecting:i.element})))))}),!1}},_mouseStop:function(e){var i=this;return this.dragged=!1,t(".ui-unselecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",e,{unselected:s.element})}),t(".ui-selecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",e,{selected:s.element})}),this._trigger("stop",e),this.helper.remove(),!1}})})(jQuery);(function(t){function e(t,e,i){return t>e&&e+i>t}function i(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))}t.widget("ui.sortable",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var t=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===t.axis||i(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_setOption:function(e,i){"disabled"===e?(this.options[e]=i,this.widget().toggleClass("ui-sortable-disabled",!!i)):t.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(e,i){var s=null,n=!1,o=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,o.widgetName+"-item")===o?(s=t(this),!1):undefined}),t.data(e.target,o.widgetName+"-item")===o&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,o,a=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,a.cursorAt&&this._adjustOffsetFromHelper(a.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),a.containment&&this._setContainment(),a.cursor&&"auto"!==a.cursor&&(o=this.document.find("body"),this.storedCursor=o.css("cursor"),o.css("cursor",a.cursor),this.storedStylesheet=t("<style>*{ cursor: "+a.cursor+" !important; }</style>").appendTo(o)),a.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",a.opacity)),a.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",a.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,o,a=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY<a.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+a.scrollSpeed:e.pageY-this.overflowOffset.top<a.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-a.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-e.pageX<a.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+a.scrollSpeed:e.pageX-this.overflowOffset.left<a.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-a.scrollSpeed)):(e.pageY-t(document).scrollTop()<a.scrollSensitivity?r=t(document).scrollTop(t(document).scrollTop()-a.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<a.scrollSensitivity&&(r=t(document).scrollTop(t(document).scrollTop()+a.scrollSpeed)),e.pageX-t(document).scrollLeft()<a.scrollSensitivity?r=t(document).scrollLeft(t(document).scrollLeft()-a.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<a.scrollSensitivity&&(r=t(document).scrollLeft(t(document).scrollLeft()+a.scrollSpeed))),r!==!1&&t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],o=this._intersectsWithPointer(s),o&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===o?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===o?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),o=this.options.axis,a={};o&&"x"!==o||(a.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),o&&"y"!==o||(a.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(a,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,h=r+t.height,l=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+l>r&&h>s+l,d="y"===this.options.axis||e+c>o&&a>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>o&&a>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var i="x"===this.options.axis||e(this.positionAbs.top+this.offset.click.top,t.top,t.height),s="y"===this.options.axis||e(this.positionAbs.left+this.offset.click.left,t.left,t.width),n=i&&s,o=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return n?this.floating?a&&"right"===a||"down"===o?2:1:o&&("down"===o?2:1):!1},_intersectsWithSides:function(t){var i=e(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),s=e(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),n=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return this.floating&&o?"right"===o&&s||"left"===o&&!s:n&&("down"===n&&i||"up"===n&&!i)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){function i(){r.push(this)}var s,n,o,a,r=[],h=[],l=this._connectWith();if(l&&e)for(s=l.length-1;s>=0;s--)for(o=t(l[s]),n=o.length-1;n>=0;n--)a=t.data(o[n],this.widgetFullName),a&&a!==this&&!a.options.disabled&&h.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(h.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=h.length-1;s>=0;s--)h[s][0].each(i);return t(r)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,o,a,r,h,l,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&(u.push([t.isFunction(o.options.items)?o.options.items.call(o.element[0],e,{item:this.currentItem}):t(o.options.items,o.element),o]),this.containers.push(o));for(i=u.length-1;i>=0;i--)for(a=u[i][1],r=u[i][0],s=0,l=r.length;l>s;s++)h=t(r[s]),h.data(this.widgetName+"-item",a),c.push({item:h,instance:a,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,o;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),o=n.offset(),s.left=o.left,s.top=o.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)o=this.containers[i].element.offset(),this.containers[i].containerCache.left=o.left,this.containers[i].containerCache.top=o.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]).addClass(i||e.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?e.currentItem.children().each(function(){t("<td>&#160;</td>",e.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(n)}):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_contactContainers:function(s){var n,o,a,r,h,l,c,u,d,p,f=null,g=null;for(n=this.containers.length-1;n>=0;n--)if(!t.contains(this.currentItem[0],this.containers[n].element[0]))if(this._intersectsWith(this.containers[n].containerCache)){if(f&&t.contains(this.containers[n].element[0],f.element[0]))continue;f=this.containers[n],g=n}else this.containers[n].containerCache.over&&(this.containers[n]._trigger("out",s,this._uiHash(this)),this.containers[n].containerCache.over=0);if(f)if(1===this.containers.length)this.containers[g].containerCache.over||(this.containers[g]._trigger("over",s,this._uiHash(this)),this.containers[g].containerCache.over=1);else{for(a=1e4,r=null,p=f.floating||i(this.currentItem),h=p?"left":"top",l=p?"width":"height",c=this.positionAbs[h]+this.offset.click[h],o=this.items.length-1;o>=0;o--)t.contains(this.containers[g].element[0],this.items[o].item[0])&&this.items[o].item[0]!==this.currentItem[0]&&(!p||e(this.positionAbs.top+this.offset.click.top,this.items[o].top,this.items[o].height))&&(u=this.items[o].item.offset()[h],d=!1,Math.abs(u-c)>Math.abs(u+this.items[o][l]-c)&&(d=!0,u+=this.items[o][l]),a>Math.abs(u-c)&&(a=Math.abs(u-c),r=this.items[o],this.direction=d?"up":"down"));if(!r&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[g])return;r?this._rearrange(s,r,null,!0):this._rearrange(s,null,this.containers[g].element,!0),this._trigger("change",s,this._uiHash()),this.containers[g]._trigger("change",s,this._uiHash(this)),this.currentContainer=this.containers[g],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[g]._trigger("over",s,this._uiHash(this)),this.containers[g].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,t("document"===n.containment?document:window).width()-this.helperProportions.width-this.margins.left,(t("document"===n.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.left<this.containment[0]&&(o=this.containment[0]+this.offset.click.left),e.pageY-this.offset.click.top<this.containment[1]&&(a=this.containment[1]+this.offset.click.top),e.pageX-this.offset.click.left>this.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,this.cancelHelperRemoval){if(!e){for(this._trigger("beforeStop",t,this._uiHash()),s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}if(e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null,!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}})})(jQuery);(function(e){var t=0,i={},a={};i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="hide",a.height=a.paddingTop=a.paddingBottom=a.borderTopWidth=a.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.10.4",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),t.collapsible||t.active!==!1&&null!=t.active||(t.active=0),this._processPanels(),0>t.active&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():e(),content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("<span>").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),"content"!==this.options.heightStyle&&e.css("height","")},_setOption:function(e,t){return"active"===e?(this._activate(t),undefined):("event"===e&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),"collapsible"!==e||t||this.options.active!==!1||this._activate(0),"icons"===e&&(this._destroyIcons(),t&&this._createIcons()),"disabled"===e&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t),undefined)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var i=e.ui.keyCode,a=this.headers.length,s=this.headers.index(t.target),n=!1;switch(t.keyCode){case i.RIGHT:case i.DOWN:n=this.headers[(s+1)%a];break;case i.LEFT:case i.UP:n=this.headers[(s-1+a)%a];break;case i.SPACE:case i.ENTER:this._eventHandler(t);break;case i.HOME:n=this.headers[0];break;case i.END:n=this.headers[a-1]}n&&(e(t.target).attr("tabIndex",-1),e(n).attr("tabIndex",0),n.focus(),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels(),t.active===!1&&t.collapsible===!0||!this.headers.length?(t.active=!1,this.active=e()):t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide()},_refresh:function(){var i,a=this.options,s=a.heightStyle,n=this.element.parent(),r=this.accordionId="ui-accordion-"+(this.element.attr("id")||++t);this.active=this._findActive(a.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(t){var i=e(this),a=i.attr("id"),s=i.next(),n=s.attr("id");a||(a=r+"-header-"+t,i.attr("id",a)),n||(n=r+"-panel-"+t,s.attr("id",n)),i.attr("aria-controls",n),s.attr("aria-labelledby",a)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(a.event),"fill"===s?(i=n.height(),this.element.siblings(":visible").each(function(){var t=e(this),a=t.css("position");"absolute"!==a&&"fixed"!==a&&(i-=t.outerHeight(!0))}),this.headers.each(function(){i-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,i-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===s&&(i=0,this.headers.next().each(function(){i=Math.max(i,e(this).css("height","").height())}).height(i))},_activate:function(t){var i=this._findActive(t)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):e()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var i=this.options,a=this.active,s=e(t.currentTarget),n=s[0]===a[0],r=n&&i.collapsible,o=r?e():s.next(),h=a.next(),d={oldHeader:a,oldPanel:h,newHeader:r?e():s,newPanel:o};t.preventDefault(),n&&!i.collapsible||this._trigger("beforeActivate",t,d)===!1||(i.active=r?!1:this.headers.index(s),this.active=n?e():s,this._toggle(d),a.removeClass("ui-accordion-header-active ui-state-active"),i.icons&&a.children(".ui-accordion-header-icon").removeClass(i.icons.activeHeader).addClass(i.icons.header),n||(s.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),i.icons&&s.children(".ui-accordion-header-icon").removeClass(i.icons.header).addClass(i.icons.activeHeader),s.next().addClass("ui-accordion-content-active")))},_toggle:function(t){var i=t.newPanel,a=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=a,this.options.animate?this._animate(i,a,t):(a.hide(),i.show(),this._toggleComplete(t)),a.attr({"aria-hidden":"true"}),a.prev().attr("aria-selected","false"),i.length&&a.length?a.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===e(this).attr("tabIndex")}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true",tabIndex:0,"aria-expanded":"true"})},_animate:function(e,t,s){var n,r,o,h=this,d=0,c=e.length&&(!t.length||e.index()<t.index()),l=this.options.animate||{},u=c&&l.down||l,v=function(){h._toggleComplete(s)};return"number"==typeof u&&(o=u),"string"==typeof u&&(r=u),r=r||u.easing||l.easing,o=o||u.duration||l.duration,t.length?e.length?(n=e.show().outerHeight(),t.animate(i,{duration:o,easing:r,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(a,{duration:o,easing:r,complete:v,step:function(e,i){i.now=Math.round(e),"height"!==i.prop?d+=i.now:"content"!==h.options.heightStyle&&(i.now=Math.round(n-t.outerHeight()-d),d=0)}}),undefined):t.animate(i,o,r,v):e.animate(a,o,r,v)},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger("activate",null,e)}})})(jQuery);(function(e){e.widget("ui.autocomplete",{version:"1.10.4",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var t,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return t=!0,s=!0,i=!0,undefined;t=!1,s=!1,i=!1;var a=e.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:t=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:t=!0,this._move("nextPage",n);break;case a.UP:t=!0,this._keyEvent("previous",n);break;case a.DOWN:t=!0,this._keyEvent("next",n);break;case a.ENTER:case a.NUMPAD_ENTER:this.menu.active&&(t=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),undefined;if(!i){var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(e){return s?(s=!1,e.preventDefault(),undefined):(this._searchTimeout(e),undefined)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,undefined):(clearTimeout(this.searching),this.close(e),this._change(e),undefined)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().data("ui-menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(s){s.target===t.element[0]||s.target===i||e.contains(i,s.target)||t.close()})})},menufocus:function(t,i){if(this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type)))return this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)}),undefined;var s=i.item.data("ui-autocomplete-item");!1!==this._trigger("focus",t,{item:s})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(s.value):this.liveRegion.text(s.value)},menuselect:function(e,t){var i=t.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",e,{item:i})&&this._value(i.value),this.term=this._value(),this.close(e),this.selectedItem=i}}),this.liveRegion=e("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertBefore(this.element),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),"source"===e&&this._initSource(),"appendTo"===e&&this.menu.element.appendTo(this._appendTo()),"disabled"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,i,s=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(i,s){s(e.ui.autocomplete.filter(t,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(t,n){s.xhr&&s.xhr.abort(),s.xhr=e.ajax({url:i,data:t,dataType:"json",success:function(e){n(e)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length<this.options.minLength?this.close(t):this._trigger("search",t)!==!1?this._search(e):undefined},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var t=++this.requestIndex;return e.proxy(function(e){t===this.requestIndex&&this.__response(e),this.pending--,this.pending||this.element.removeClass("ui-autocomplete-loading")},this)},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return"string"==typeof t?{label:t,value:t}:e.extend({label:t.label||t.value,value:t.value||t.label},t)})},_suggest:function(t){var i=this.menu.element.empty();this._renderMenu(i,t),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,i){var s=this;e.each(i,function(e,i){s._renderItemData(t,i)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,i){return e("<li>").append(e("<a>").text(i.label)).appendTo(t)},_move:function(e,t){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this._value(this.term),this.menu.blur(),undefined):(this.menu[e](t),undefined):(this.search(null,t),undefined)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,i){var s=RegExp(e.ui.autocomplete.escapeRegex(i),"i");return e.grep(t,function(e){return s.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments),this.options.disabled||this.cancelSearch||(t=e&&e.length?this.options.messages.results(e.length):this.options.messages.noResults,this.liveRegion.text(t))}})})(jQuery);(function(e){var t,i="ui-button ui-widget ui-state-default ui-corner-all",n="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",s=function(){var t=e(this);setTimeout(function(){t.find(":ui-button").button("refresh")},1)},a=function(t){var i=t.name,n=t.form,s=e([]);return i&&(i=i.replace(/'/g,"\\'"),s=n?e(n).find("[name='"+i+"']"):e("[name='"+i+"']",t.ownerDocument).filter(function(){return!this.form})),s};e.widget("ui.button",{version:"1.10.4",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,s),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var n=this,o=this.options,r="checkbox"===this.type||"radio"===this.type,h=r?"":"ui-state-active";null===o.label&&(o.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(i).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){o.disabled||this===t&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){o.disabled||e(this).removeClass(h)}).bind("click"+this.eventNamespace,function(e){o.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this._on({focus:function(){this.buttonElement.addClass("ui-state-focus")},blur:function(){this.buttonElement.removeClass("ui-state-focus")}}),r&&this.element.bind("change"+this.eventNamespace,function(){n.refresh()}),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return o.disabled?!1:undefined}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(o.disabled)return!1;e(this).addClass("ui-state-active"),n.buttonElement.attr("aria-pressed","true");var t=n.element[0];a(t).not(t).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return o.disabled?!1:(e(this).addClass("ui-state-active"),t=this,n.document.one("mouseup",function(){t=null}),undefined)}).bind("mouseup"+this.eventNamespace,function(){return o.disabled?!1:(e(this).removeClass("ui-state-active"),undefined)}).bind("keydown"+this.eventNamespace,function(t){return o.disabled?!1:((t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active"),undefined)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",o.disabled),this._resetButton()},_determineButtonType:function(){var e,t,i;this.type=this.element.is("[type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),i=this.element.is(":checked"),i&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(i+" ui-state-active "+n).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){return this._super(e,t),"disabled"===e?(this.element.prop("disabled",!!t),t&&this.buttonElement.removeClass("ui-state-focus"),undefined):(this._resetButton(),undefined)},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),"radio"===this.type?a(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),undefined;var t=this.buttonElement.removeClass(n),i=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),s=this.options.icons,a=s.primary&&s.secondary,o=[];s.primary||s.secondary?(this.options.text&&o.push("ui-button-text-icon"+(a?"s":s.primary?"-primary":"-secondary")),s.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+s.primary+"'></span>"),s.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+s.secondary+"'></span>"),this.options.text||(o.push(a?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(i)))):o.push("ui-button-text-only"),t.addClass(o.join(" "))}}),e.widget("ui.buttonset",{version:"1.10.4",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){"disabled"===e&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t="rtl"===this.element.css("direction");this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(e,t){function i(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},e.extend(this._defaults,this.regional[""]),this.dpDiv=a(e("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function a(t){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.delegate(i,"mouseout",function(){e(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",function(){e.datepicker._isDisabledDatepicker(n.inline?t.parent()[0]:n.input[0])||(e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),e(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).addClass("ui-datepicker-next-hover"))})}function s(t,i){e.extend(t,i);for(var a in i)null==i[a]&&(t[a]=i[a]);return t}e.extend(e.ui,{datepicker:{version:"1.10.4"}});var n,r="datepicker";e.extend(i.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return s(this._defaults,e||{}),this},_attachDatepicker:function(t,i){var a,s,n;a=t.nodeName.toLowerCase(),s="div"===a||"span"===a,t.id||(this.uuid+=1,t.id="dp"+this.uuid),n=this._newInst(e(t),s),n.settings=e.extend({},i||{}),"input"===a?this._connectDatepicker(t,n):s&&this._inlineDatepicker(t,n)},_newInst:function(t,i){var s=t[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:s,input:t,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?a(e("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(t,i){var a=e(t);i.append=e([]),i.trigger=e([]),a.hasClass(this.markerClassName)||(this._attachments(a,i),a.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(i),e.data(t,r,i),i.settings.disabled&&this._disableDatepicker(t))},_attachments:function(t,i){var a,s,n,r=this._get(i,"appendText"),o=this._get(i,"isRTL");i.append&&i.append.remove(),r&&(i.append=e("<span class='"+this._appendClass+"'>"+r+"</span>"),t[o?"before":"after"](i.append)),t.unbind("focus",this._showDatepicker),i.trigger&&i.trigger.remove(),a=this._get(i,"showOn"),("focus"===a||"both"===a)&&t.focus(this._showDatepicker),("button"===a||"both"===a)&&(s=this._get(i,"buttonText"),n=this._get(i,"buttonImage"),i.trigger=e(this._get(i,"buttonImageOnly")?e("<img/>").addClass(this._triggerClass).attr({src:n,alt:s,title:s}):e("<button type='button'></button>").addClass(this._triggerClass).html(n?e("<img/>").attr({src:n,alt:s,title:s}):s)),t[o?"before":"after"](i.trigger),i.trigger.click(function(){return e.datepicker._datepickerShowing&&e.datepicker._lastInput===t[0]?e.datepicker._hideDatepicker():e.datepicker._datepickerShowing&&e.datepicker._lastInput!==t[0]?(e.datepicker._hideDatepicker(),e.datepicker._showDatepicker(t[0])):e.datepicker._showDatepicker(t[0]),!1}))},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t,i,a,s,n=new Date(2009,11,20),r=this._get(e,"dateFormat");r.match(/[DM]/)&&(t=function(e){for(i=0,a=0,s=0;e.length>s;s++)e[s].length>i&&(i=e[s].length,a=s);return a},n.setMonth(t(this._get(e,r.match(/MM/)?"monthNames":"monthNamesShort"))),n.setDate(t(this._get(e,r.match(/DD/)?"dayNames":"dayNamesShort"))+20-n.getDay())),e.input.attr("size",this._formatDate(e,n).length)}},_inlineDatepicker:function(t,i){var a=e(t);a.hasClass(this.markerClassName)||(a.addClass(this.markerClassName).append(i.dpDiv),e.data(t,r,i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(t),i.dpDiv.css("display","block"))},_dialogDatepicker:function(t,i,a,n,o){var u,c,h,l,d,p=this._dialogInst;return p||(this.uuid+=1,u="dp"+this.uuid,this._dialogInput=e("<input type='text' id='"+u+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),e("body").append(this._dialogInput),p=this._dialogInst=this._newInst(this._dialogInput,!1),p.settings={},e.data(this._dialogInput[0],r,p)),s(p.settings,n||{}),i=i&&i.constructor===Date?this._formatDate(p,i):i,this._dialogInput.val(i),this._pos=o?o.length?o:[o.pageX,o.pageY]:null,this._pos||(c=document.documentElement.clientWidth,h=document.documentElement.clientHeight,l=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[c/2-100+l,h/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),p.settings.onSelect=a,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),e.blockUI&&e.blockUI(this.dpDiv),e.data(this._dialogInput[0],r,p),this},_destroyDatepicker:function(t){var i,a=e(t),s=e.data(t,r);a.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),e.removeData(t,r),"input"===i?(s.append.remove(),s.trigger.remove(),a.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&a.removeClass(this.markerClassName).empty())},_enableDatepicker:function(t){var i,a,s=e(t),n=e.data(t,r);s.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!1,n.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(a=s.children("."+this._inlineClass),a.children().removeClass("ui-state-disabled"),a.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}))},_disableDatepicker:function(t){var i,a,s=e(t),n=e.data(t,r);s.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!0,n.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(a=s.children("."+this._inlineClass),a.children().addClass("ui-state-disabled"),a.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}),this._disabledInputs[this._disabledInputs.length]=t)},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;this._disabledInputs.length>t;t++)if(this._disabledInputs[t]===e)return!0;return!1},_getInst:function(t){try{return e.data(t,r)}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(i,a,n){var r,o,u,c,h=this._getInst(i);return 2===arguments.length&&"string"==typeof a?"defaults"===a?e.extend({},e.datepicker._defaults):h?"all"===a?e.extend({},h.settings):this._get(h,a):null:(r=a||{},"string"==typeof a&&(r={},r[a]=n),h&&(this._curInst===h&&this._hideDatepicker(),o=this._getDateDatepicker(i,!0),u=this._getMinMaxDate(h,"min"),c=this._getMinMaxDate(h,"max"),s(h.settings,r),null!==u&&r.dateFormat!==t&&r.minDate===t&&(h.settings.minDate=this._formatDate(h,u)),null!==c&&r.dateFormat!==t&&r.maxDate===t&&(h.settings.maxDate=this._formatDate(h,c)),"disabled"in r&&(r.disabled?this._disableDatepicker(i):this._enableDatepicker(i)),this._attachments(e(i),h),this._autoSize(h),this._setDate(h,o),this._updateAlternate(h),this._updateDatepicker(h)),t)},_changeDatepicker:function(e,t,i){this._optionDatepicker(e,t,i)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var i=this._getInst(e);i&&(this._setDate(i,t),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(e,t){var i=this._getInst(e);return i&&!i.inline&&this._setDateFromField(i,t),i?this._getDate(i):null},_doKeyDown:function(t){var i,a,s,n=e.datepicker._getInst(t.target),r=!0,o=n.dpDiv.is(".ui-datepicker-rtl");if(n._keyEvent=!0,e.datepicker._datepickerShowing)switch(t.keyCode){case 9:e.datepicker._hideDatepicker(),r=!1;break;case 13:return s=e("td."+e.datepicker._dayOverClass+":not(."+e.datepicker._currentClass+")",n.dpDiv),s[0]&&e.datepicker._selectDay(t.target,n.selectedMonth,n.selectedYear,s[0]),i=e.datepicker._get(n,"onSelect"),i?(a=e.datepicker._formatDate(n),i.apply(n.input?n.input[0]:null,[a,n])):e.datepicker._hideDatepicker(),!1;case 27:e.datepicker._hideDatepicker();break;case 33:e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(n,"stepBigMonths"):-e.datepicker._get(n,"stepMonths"),"M");break;case 34:e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(n,"stepBigMonths"):+e.datepicker._get(n,"stepMonths"),"M");break;case 35:(t.ctrlKey||t.metaKey)&&e.datepicker._clearDate(t.target),r=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&e.datepicker._gotoToday(t.target),r=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,o?1:-1,"D"),r=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(n,"stepBigMonths"):-e.datepicker._get(n,"stepMonths"),"M");break;case 38:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,-7,"D"),r=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,o?-1:1,"D"),r=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(n,"stepBigMonths"):+e.datepicker._get(n,"stepMonths"),"M");break;case 40:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,7,"D"),r=t.ctrlKey||t.metaKey;break;default:r=!1}else 36===t.keyCode&&t.ctrlKey?e.datepicker._showDatepicker(this):r=!1;r&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(i){var a,s,n=e.datepicker._getInst(i.target);return e.datepicker._get(n,"constrainInput")?(a=e.datepicker._possibleChars(e.datepicker._get(n,"dateFormat")),s=String.fromCharCode(null==i.charCode?i.keyCode:i.charCode),i.ctrlKey||i.metaKey||" ">s||!a||a.indexOf(s)>-1):t},_doKeyUp:function(t){var i,a=e.datepicker._getInst(t.target);if(a.input.val()!==a.lastVal)try{i=e.datepicker.parseDate(e.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,e.datepicker._getFormatConfig(a)),i&&(e.datepicker._setDateFromField(a),e.datepicker._updateAlternate(a),e.datepicker._updateDatepicker(a))}catch(s){}return!0},_showDatepicker:function(t){if(t=t.target||t,"input"!==t.nodeName.toLowerCase()&&(t=e("input",t.parentNode)[0]),!e.datepicker._isDisabledDatepicker(t)&&e.datepicker._lastInput!==t){var i,a,n,r,o,u,c;i=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==i&&(e.datepicker._curInst.dpDiv.stop(!0,!0),i&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),a=e.datepicker._get(i,"beforeShow"),n=a?a.apply(t,[t,i]):{},n!==!1&&(s(i.settings,n),i.lastVal=null,e.datepicker._lastInput=t,e.datepicker._setDateFromField(i),e.datepicker._inDialog&&(t.value=""),e.datepicker._pos||(e.datepicker._pos=e.datepicker._findPos(t),e.datepicker._pos[1]+=t.offsetHeight),r=!1,e(t).parents().each(function(){return r|="fixed"===e(this).css("position"),!r}),o={left:e.datepicker._pos[0],top:e.datepicker._pos[1]},e.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),e.datepicker._updateDatepicker(i),o=e.datepicker._checkOffset(i,o,r),i.dpDiv.css({position:e.datepicker._inDialog&&e.blockUI?"static":r?"fixed":"absolute",display:"none",left:o.left+"px",top:o.top+"px"}),i.inline||(u=e.datepicker._get(i,"showAnim"),c=e.datepicker._get(i,"duration"),i.dpDiv.zIndex(e(t).zIndex()+1),e.datepicker._datepickerShowing=!0,e.effects&&e.effects.effect[u]?i.dpDiv.show(u,e.datepicker._get(i,"showOptions"),c):i.dpDiv[u||"show"](u?c:null),e.datepicker._shouldFocusInput(i)&&i.input.focus(),e.datepicker._curInst=i))}},_updateDatepicker:function(t){this.maxRows=4,n=t,t.dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t),t.dpDiv.find("."+this._dayOverClass+" a").mouseover();var i,a=this._getNumberOfMonths(t),s=a[1],r=17;t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),s>1&&t.dpDiv.addClass("ui-datepicker-multi-"+s).css("width",r*s+"em"),t.dpDiv[(1!==a[0]||1!==a[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),t.dpDiv[(this._get(t,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),t===e.datepicker._curInst&&e.datepicker._datepickerShowing&&e.datepicker._shouldFocusInput(t)&&t.input.focus(),t.yearshtml&&(i=t.yearshtml,setTimeout(function(){i===t.yearshtml&&t.yearshtml&&t.dpDiv.find("select.ui-datepicker-year:first").replaceWith(t.yearshtml),i=t.yearshtml=null},0))},_shouldFocusInput:function(e){return e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&!e.input.is(":focus")},_checkOffset:function(t,i,a){var s=t.dpDiv.outerWidth(),n=t.dpDiv.outerHeight(),r=t.input?t.input.outerWidth():0,o=t.input?t.input.outerHeight():0,u=document.documentElement.clientWidth+(a?0:e(document).scrollLeft()),c=document.documentElement.clientHeight+(a?0:e(document).scrollTop());return i.left-=this._get(t,"isRTL")?s-r:0,i.left-=a&&i.left===t.input.offset().left?e(document).scrollLeft():0,i.top-=a&&i.top===t.input.offset().top+o?e(document).scrollTop():0,i.left-=Math.min(i.left,i.left+s>u&&u>s?Math.abs(i.left+s-u):0),i.top-=Math.min(i.top,i.top+n>c&&c>n?Math.abs(n+o):0),i},_findPos:function(t){for(var i,a=this._getInst(t),s=this._get(a,"isRTL");t&&("hidden"===t.type||1!==t.nodeType||e.expr.filters.hidden(t));)t=t[s?"previousSibling":"nextSibling"];return i=e(t).offset(),[i.left,i.top]},_hideDatepicker:function(t){var i,a,s,n,o=this._curInst;!o||t&&o!==e.data(t,r)||this._datepickerShowing&&(i=this._get(o,"showAnim"),a=this._get(o,"duration"),s=function(){e.datepicker._tidyDialog(o)},e.effects&&(e.effects.effect[i]||e.effects[i])?o.dpDiv.hide(i,e.datepicker._get(o,"showOptions"),a,s):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?a:null,s),i||s(),this._datepickerShowing=!1,n=this._get(o,"onClose"),n&&n.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),e.blockUI&&(e.unblockUI(),e("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(t){if(e.datepicker._curInst){var i=e(t.target),a=e.datepicker._getInst(i[0]);(i[0].id!==e.datepicker._mainDivId&&0===i.parents("#"+e.datepicker._mainDivId).length&&!i.hasClass(e.datepicker.markerClassName)&&!i.closest("."+e.datepicker._triggerClass).length&&e.datepicker._datepickerShowing&&(!e.datepicker._inDialog||!e.blockUI)||i.hasClass(e.datepicker.markerClassName)&&e.datepicker._curInst!==a)&&e.datepicker._hideDatepicker()}},_adjustDate:function(t,i,a){var s=e(t),n=this._getInst(s[0]);this._isDisabledDatepicker(s[0])||(this._adjustInstDate(n,i+("M"===a?this._get(n,"showCurrentAtPos"):0),a),this._updateDatepicker(n))},_gotoToday:function(t){var i,a=e(t),s=this._getInst(a[0]);this._get(s,"gotoCurrent")&&s.currentDay?(s.selectedDay=s.currentDay,s.drawMonth=s.selectedMonth=s.currentMonth,s.drawYear=s.selectedYear=s.currentYear):(i=new Date,s.selectedDay=i.getDate(),s.drawMonth=s.selectedMonth=i.getMonth(),s.drawYear=s.selectedYear=i.getFullYear()),this._notifyChange(s),this._adjustDate(a)},_selectMonthYear:function(t,i,a){var s=e(t),n=this._getInst(s[0]);n["selected"+("M"===a?"Month":"Year")]=n["draw"+("M"===a?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(n),this._adjustDate(s)},_selectDay:function(t,i,a,s){var n,r=e(t);e(s).hasClass(this._unselectableClass)||this._isDisabledDatepicker(r[0])||(n=this._getInst(r[0]),n.selectedDay=n.currentDay=e("a",s).html(),n.selectedMonth=n.currentMonth=i,n.selectedYear=n.currentYear=a,this._selectDate(t,this._formatDate(n,n.currentDay,n.currentMonth,n.currentYear)))},_clearDate:function(t){var i=e(t);this._selectDate(i,"")},_selectDate:function(t,i){var a,s=e(t),n=this._getInst(s[0]);i=null!=i?i:this._formatDate(n),n.input&&n.input.val(i),this._updateAlternate(n),a=this._get(n,"onSelect"),a?a.apply(n.input?n.input[0]:null,[i,n]):n.input&&n.input.trigger("change"),n.inline?this._updateDatepicker(n):(this._hideDatepicker(),this._lastInput=n.input[0],"object"!=typeof n.input[0]&&n.input.focus(),this._lastInput=null)},_updateAlternate:function(t){var i,a,s,n=this._get(t,"altField");n&&(i=this._get(t,"altFormat")||this._get(t,"dateFormat"),a=this._getDate(t),s=this.formatDate(i,a,this._getFormatConfig(t)),e(n).each(function(){e(this).val(s)}))},noWeekends:function(e){var t=e.getDay();return[t>0&&6>t,""]},iso8601Week:function(e){var t,i=new Date(e.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),t=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((t-i)/864e5)/7)+1},parseDate:function(i,a,s){if(null==i||null==a)throw"Invalid arguments";if(a="object"==typeof a?""+a:a+"",""===a)return null;var n,r,o,u,c=0,h=(s?s.shortYearCutoff:null)||this._defaults.shortYearCutoff,l="string"!=typeof h?h:(new Date).getFullYear()%100+parseInt(h,10),d=(s?s.dayNamesShort:null)||this._defaults.dayNamesShort,p=(s?s.dayNames:null)||this._defaults.dayNames,g=(s?s.monthNamesShort:null)||this._defaults.monthNamesShort,m=(s?s.monthNames:null)||this._defaults.monthNames,f=-1,_=-1,v=-1,k=-1,y=!1,b=function(e){var t=i.length>n+1&&i.charAt(n+1)===e;return t&&n++,t},D=function(e){var t=b(e),i="@"===e?14:"!"===e?20:"y"===e&&t?4:"o"===e?3:2,s=RegExp("^\\d{1,"+i+"}"),n=a.substring(c).match(s);if(!n)throw"Missing number at position "+c;return c+=n[0].length,parseInt(n[0],10)},w=function(i,s,n){var r=-1,o=e.map(b(i)?n:s,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)});if(e.each(o,function(e,i){var s=i[1];return a.substr(c,s.length).toLowerCase()===s.toLowerCase()?(r=i[0],c+=s.length,!1):t}),-1!==r)return r+1;throw"Unknown name at position "+c},M=function(){if(a.charAt(c)!==i.charAt(n))throw"Unexpected literal at position "+c;c++};for(n=0;i.length>n;n++)if(y)"'"!==i.charAt(n)||b("'")?M():y=!1;else switch(i.charAt(n)){case"d":v=D("d");break;case"D":w("D",d,p);break;case"o":k=D("o");break;case"m":_=D("m");break;case"M":_=w("M",g,m);break;case"y":f=D("y");break;case"@":u=new Date(D("@")),f=u.getFullYear(),_=u.getMonth()+1,v=u.getDate();break;case"!":u=new Date((D("!")-this._ticksTo1970)/1e4),f=u.getFullYear(),_=u.getMonth()+1,v=u.getDate();break;case"'":b("'")?M():y=!0;break;default:M()}if(a.length>c&&(o=a.substr(c),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===f?f=(new Date).getFullYear():100>f&&(f+=(new Date).getFullYear()-(new Date).getFullYear()%100+(l>=f?0:-100)),k>-1)for(_=1,v=k;;){if(r=this._getDaysInMonth(f,_-1),r>=v)break;_++,v-=r}if(u=this._daylightSavingAdjust(new Date(f,_-1,v)),u.getFullYear()!==f||u.getMonth()+1!==_||u.getDate()!==v)throw"Invalid date";return u},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(e,t,i){if(!t)return"";var a,s=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,n=(i?i.dayNames:null)||this._defaults.dayNames,r=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,o=(i?i.monthNames:null)||this._defaults.monthNames,u=function(t){var i=e.length>a+1&&e.charAt(a+1)===t;return i&&a++,i},c=function(e,t,i){var a=""+t;if(u(e))for(;i>a.length;)a="0"+a;return a},h=function(e,t,i,a){return u(e)?a[t]:i[t]},l="",d=!1;if(t)for(a=0;e.length>a;a++)if(d)"'"!==e.charAt(a)||u("'")?l+=e.charAt(a):d=!1;else switch(e.charAt(a)){case"d":l+=c("d",t.getDate(),2);break;case"D":l+=h("D",t.getDay(),s,n);break;case"o":l+=c("o",Math.round((new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()-new Date(t.getFullYear(),0,0).getTime())/864e5),3);break;case"m":l+=c("m",t.getMonth()+1,2);break;case"M":l+=h("M",t.getMonth(),r,o);break;case"y":l+=u("y")?t.getFullYear():(10>t.getYear()%100?"0":"")+t.getYear()%100;break;case"@":l+=t.getTime();break;case"!":l+=1e4*t.getTime()+this._ticksTo1970;break;case"'":u("'")?l+="'":d=!0;break;default:l+=e.charAt(a)}return l},_possibleChars:function(e){var t,i="",a=!1,s=function(i){var a=e.length>t+1&&e.charAt(t+1)===i;return a&&t++,a};for(t=0;e.length>t;t++)if(a)"'"!==e.charAt(t)||s("'")?i+=e.charAt(t):a=!1;else switch(e.charAt(t)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":s("'")?i+="'":a=!0;break;default:i+=e.charAt(t)}return i},_get:function(e,i){return e.settings[i]!==t?e.settings[i]:this._defaults[i]},_setDateFromField:function(e,t){if(e.input.val()!==e.lastVal){var i=this._get(e,"dateFormat"),a=e.lastVal=e.input?e.input.val():null,s=this._getDefaultDate(e),n=s,r=this._getFormatConfig(e);try{n=this.parseDate(i,a,r)||s}catch(o){a=t?"":a}e.selectedDay=n.getDate(),e.drawMonth=e.selectedMonth=n.getMonth(),e.drawYear=e.selectedYear=n.getFullYear(),e.currentDay=a?n.getDate():0,e.currentMonth=a?n.getMonth():0,e.currentYear=a?n.getFullYear():0,this._adjustInstDate(e)}},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(t,i,a){var s=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},n=function(i){try{return e.datepicker.parseDate(e.datepicker._get(t,"dateFormat"),i,e.datepicker._getFormatConfig(t))}catch(a){}for(var s=(i.toLowerCase().match(/^c/)?e.datepicker._getDate(t):null)||new Date,n=s.getFullYear(),r=s.getMonth(),o=s.getDate(),u=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,c=u.exec(i);c;){switch(c[2]||"d"){case"d":case"D":o+=parseInt(c[1],10);break;case"w":case"W":o+=7*parseInt(c[1],10);break;case"m":case"M":r+=parseInt(c[1],10),o=Math.min(o,e.datepicker._getDaysInMonth(n,r));break;case"y":case"Y":n+=parseInt(c[1],10),o=Math.min(o,e.datepicker._getDaysInMonth(n,r))}c=u.exec(i)}return new Date(n,r,o)},r=null==i||""===i?a:"string"==typeof i?n(i):"number"==typeof i?isNaN(i)?a:s(i):new Date(i.getTime());return r=r&&"Invalid Date"==""+r?a:r,r&&(r.setHours(0),r.setMinutes(0),r.setSeconds(0),r.setMilliseconds(0)),this._daylightSavingAdjust(r)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,i){var a=!t,s=e.selectedMonth,n=e.selectedYear,r=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=r.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=r.getMonth(),e.drawYear=e.selectedYear=e.currentYear=r.getFullYear(),s===e.selectedMonth&&n===e.selectedYear||i||this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(a?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&""===e.input.val()?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(t){var i=this._get(t,"stepMonths"),a="#"+t.id.replace(/\\\\/g,"\\");t.dpDiv.find("[data-handler]").map(function(){var t={prev:function(){e.datepicker._adjustDate(a,-i,"M")},next:function(){e.datepicker._adjustDate(a,+i,"M")},hide:function(){e.datepicker._hideDatepicker()},today:function(){e.datepicker._gotoToday(a)},selectDay:function(){return e.datepicker._selectDay(a,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return e.datepicker._selectMonthYear(a,this,"M"),!1},selectYear:function(){return e.datepicker._selectMonthYear(a,this,"Y"),!1}};e(this).bind(this.getAttribute("data-event"),t[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t,i,a,s,n,r,o,u,c,h,l,d,p,g,m,f,_,v,k,y,b,D,w,M,C,x,I,N,T,A,E,S,Y,F,P,O,j,K,R,H=new Date,W=this._daylightSavingAdjust(new Date(H.getFullYear(),H.getMonth(),H.getDate())),L=this._get(e,"isRTL"),U=this._get(e,"showButtonPanel"),B=this._get(e,"hideIfNoPrevNext"),z=this._get(e,"navigationAsDateFormat"),q=this._getNumberOfMonths(e),G=this._get(e,"showCurrentAtPos"),J=this._get(e,"stepMonths"),Q=1!==q[0]||1!==q[1],V=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),$=this._getMinMaxDate(e,"min"),X=this._getMinMaxDate(e,"max"),Z=e.drawMonth-G,et=e.drawYear;if(0>Z&&(Z+=12,et--),X)for(t=this._daylightSavingAdjust(new Date(X.getFullYear(),X.getMonth()-q[0]*q[1]+1,X.getDate())),t=$&&$>t?$:t;this._daylightSavingAdjust(new Date(et,Z,1))>t;)Z--,0>Z&&(Z=11,et--);for(e.drawMonth=Z,e.drawYear=et,i=this._get(e,"prevText"),i=z?this.formatDate(i,this._daylightSavingAdjust(new Date(et,Z-J,1)),this._getFormatConfig(e)):i,a=this._canAdjustMonth(e,-1,et,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"e":"w")+"'>"+i+"</span></a>":B?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"e":"w")+"'>"+i+"</span></a>",s=this._get(e,"nextText"),s=z?this.formatDate(s,this._daylightSavingAdjust(new Date(et,Z+J,1)),this._getFormatConfig(e)):s,n=this._canAdjustMonth(e,1,et,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+s+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"w":"e")+"'>"+s+"</span></a>":B?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+s+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"w":"e")+"'>"+s+"</span></a>",r=this._get(e,"currentText"),o=this._get(e,"gotoCurrent")&&e.currentDay?V:W,r=z?this.formatDate(r,o,this._getFormatConfig(e)):r,u=e.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(e,"closeText")+"</button>",c=U?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(L?u:"")+(this._isInRange(e,o)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+r+"</button>":"")+(L?"":u)+"</div>":"",h=parseInt(this._get(e,"firstDay"),10),h=isNaN(h)?0:h,l=this._get(e,"showWeek"),d=this._get(e,"dayNames"),p=this._get(e,"dayNamesMin"),g=this._get(e,"monthNames"),m=this._get(e,"monthNamesShort"),f=this._get(e,"beforeShowDay"),_=this._get(e,"showOtherMonths"),v=this._get(e,"selectOtherMonths"),k=this._getDefaultDate(e),y="",D=0;q[0]>D;D++){for(w="",this.maxRows=4,M=0;q[1]>M;M++){if(C=this._daylightSavingAdjust(new Date(et,Z,e.selectedDay)),x=" ui-corner-all",I="",Q){if(I+="<div class='ui-datepicker-group",q[1]>1)switch(M){case 0:I+=" ui-datepicker-group-first",x=" ui-corner-"+(L?"right":"left");break;case q[1]-1:I+=" ui-datepicker-group-last",x=" ui-corner-"+(L?"left":"right");break;default:I+=" ui-datepicker-group-middle",x=""}I+="'>"}for(I+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+x+"'>"+(/all|left/.test(x)&&0===D?L?n:a:"")+(/all|right/.test(x)&&0===D?L?a:n:"")+this._generateMonthYearHeader(e,Z,et,$,X,D>0||M>0,g,m)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",N=l?"<th class='ui-datepicker-week-col'>"+this._get(e,"weekHeader")+"</th>":"",b=0;7>b;b++)T=(b+h)%7,N+="<th"+((b+h+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+d[T]+"'>"+p[T]+"</span></th>";for(I+=N+"</tr></thead><tbody>",A=this._getDaysInMonth(et,Z),et===e.selectedYear&&Z===e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,A)),E=(this._getFirstDayOfMonth(et,Z)-h+7)%7,S=Math.ceil((E+A)/7),Y=Q?this.maxRows>S?this.maxRows:S:S,this.maxRows=Y,F=this._daylightSavingAdjust(new Date(et,Z,1-E)),P=0;Y>P;P++){for(I+="<tr>",O=l?"<td class='ui-datepicker-week-col'>"+this._get(e,"calculateWeek")(F)+"</td>":"",b=0;7>b;b++)j=f?f.apply(e.input?e.input[0]:null,[F]):[!0,""],K=F.getMonth()!==Z,R=K&&!v||!j[0]||$&&$>F||X&&F>X,O+="<td class='"+((b+h+6)%7>=5?" ui-datepicker-week-end":"")+(K?" ui-datepicker-other-month":"")+(F.getTime()===C.getTime()&&Z===e.selectedMonth&&e._keyEvent||k.getTime()===F.getTime()&&k.getTime()===C.getTime()?" "+this._dayOverClass:"")+(R?" "+this._unselectableClass+" ui-state-disabled":"")+(K&&!_?"":" "+j[1]+(F.getTime()===V.getTime()?" "+this._currentClass:"")+(F.getTime()===W.getTime()?" ui-datepicker-today":""))+"'"+(K&&!_||!j[2]?"":" title='"+j[2].replace(/'/g,"&#39;")+"'")+(R?"":" data-handler='selectDay' data-event='click' data-month='"+F.getMonth()+"' data-year='"+F.getFullYear()+"'")+">"+(K&&!_?"&#xa0;":R?"<span class='ui-state-default'>"+F.getDate()+"</span>":"<a class='ui-state-default"+(F.getTime()===W.getTime()?" ui-state-highlight":"")+(F.getTime()===V.getTime()?" ui-state-active":"")+(K?" ui-priority-secondary":"")+"' href='#'>"+F.getDate()+"</a>")+"</td>",F.setDate(F.getDate()+1),F=this._daylightSavingAdjust(F);I+=O+"</tr>"}Z++,Z>11&&(Z=0,et++),I+="</tbody></table>"+(Q?"</div>"+(q[0]>0&&M===q[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),w+=I}y+=w}return y+=c,e._keyEvent=!1,y},_generateMonthYearHeader:function(e,t,i,a,s,n,r,o){var u,c,h,l,d,p,g,m,f=this._get(e,"changeMonth"),_=this._get(e,"changeYear"),v=this._get(e,"showMonthAfterYear"),k="<div class='ui-datepicker-title'>",y="";if(n||!f)y+="<span class='ui-datepicker-month'>"+r[t]+"</span>";else{for(u=a&&a.getFullYear()===i,c=s&&s.getFullYear()===i,y+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",h=0;12>h;h++)(!u||h>=a.getMonth())&&(!c||s.getMonth()>=h)&&(y+="<option value='"+h+"'"+(h===t?" selected='selected'":"")+">"+o[h]+"</option>");y+="</select>"}if(v||(k+=y+(!n&&f&&_?"":"&#xa0;")),!e.yearshtml)if(e.yearshtml="",n||!_)k+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(l=this._get(e,"yearRange").split(":"),d=(new Date).getFullYear(),p=function(e){var t=e.match(/c[+\-].*/)?i+parseInt(e.substring(1),10):e.match(/[+\-].*/)?d+parseInt(e,10):parseInt(e,10);
+return isNaN(t)?d:t},g=p(l[0]),m=Math.max(g,p(l[1]||"")),g=a?Math.max(g,a.getFullYear()):g,m=s?Math.min(m,s.getFullYear()):m,e.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";m>=g;g++)e.yearshtml+="<option value='"+g+"'"+(g===i?" selected='selected'":"")+">"+g+"</option>";e.yearshtml+="</select>",k+=e.yearshtml,e.yearshtml=null}return k+=this._get(e,"yearSuffix"),v&&(k+=(!n&&f&&_?"":"&#xa0;")+y),k+="</div>"},_adjustInstDate:function(e,t,i){var a=e.drawYear+("Y"===i?t:0),s=e.drawMonth+("M"===i?t:0),n=Math.min(e.selectedDay,this._getDaysInMonth(a,s))+("D"===i?t:0),r=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(a,s,n)));e.selectedDay=r.getDate(),e.drawMonth=e.selectedMonth=r.getMonth(),e.drawYear=e.selectedYear=r.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(e)},_restrictMinMax:function(e,t){var i=this._getMinMaxDate(e,"min"),a=this._getMinMaxDate(e,"max"),s=i&&i>t?i:t;return a&&s>a?a:s},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return null==t?[1,1]:"number"==typeof t?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return new Date(e,t,1).getDay()},_canAdjustMonth:function(e,t,i,a){var s=this._getNumberOfMonths(e),n=this._daylightSavingAdjust(new Date(i,a+(0>t?t:s[0]*s[1]),1));return 0>t&&n.setDate(this._getDaysInMonth(n.getFullYear(),n.getMonth())),this._isInRange(e,n)},_isInRange:function(e,t){var i,a,s=this._getMinMaxDate(e,"min"),n=this._getMinMaxDate(e,"max"),r=null,o=null,u=this._get(e,"yearRange");return u&&(i=u.split(":"),a=(new Date).getFullYear(),r=parseInt(i[0],10),o=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(r+=a),i[1].match(/[+\-].*/)&&(o+=a)),(!s||t.getTime()>=s.getTime())&&(!n||t.getTime()<=n.getTime())&&(!r||t.getFullYear()>=r)&&(!o||o>=t.getFullYear())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t="string"!=typeof t?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,i,a){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var s=t?"object"==typeof t?t:this._daylightSavingAdjust(new Date(a,i,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),s,this._getFormatConfig(e))}}),e.fn.datepicker=function(t){if(!this.length)return this;e.datepicker.initialized||(e(document).mousedown(e.datepicker._checkExternalClick),e.datepicker.initialized=!0),0===e("#"+e.datepicker._mainDivId).length&&e("body").append(e.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof t||"isDisabled"!==t&&"getDate"!==t&&"widget"!==t?"option"===t&&2===arguments.length&&"string"==typeof arguments[1]?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof t?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this].concat(i)):e.datepicker._attachDatepicker(this,t)}):e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i))},e.datepicker=new i,e.datepicker.initialized=!1,e.datepicker.uuid=(new Date).getTime(),e.datepicker.version="1.10.4"})(jQuery);(function(e){var t={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.10.4",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var i=e(this).css(t).offset().top;0>i&&e(this).css("top",t.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var i,a=this;if(this._isOpen&&this._trigger("beforeClose",t)!==!1){if(this._isOpen=!1,this._destroyOverlay(),!this.opener.filter(":focusable").focus().length)try{i=this.document[0].activeElement,i&&"body"!==i.nodeName.toLowerCase()&&e(i).blur()}catch(s){}this._hide(this.uiDialog,this.options.hide,function(){a._trigger("close",t)})}},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(e,t){var i=!!this.uiDialog.nextAll(":visible").insertBefore(this.uiDialog).length;return i&&!t&&this._trigger("focus",e),i},open:function(){var t=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),undefined):(this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._trigger("open"),undefined)},_focusTabbable:function(){var e=this.element.find("[autofocus]");e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function i(){var t=this.document[0].activeElement,i=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);i||this._focusTabbable()}t.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=e("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE)return t.preventDefault(),this.close(t),undefined;if(t.keyCode===e.ui.keyCode.TAB){var i=this.uiDialog.find(":tabbable"),a=i.filter(":first"),s=i.filter(":last");t.target!==s[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==a[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(s.focus(1),t.preventDefault()):(a.focus(1),t.preventDefault())}},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("<button type='button'></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html("&#160;"),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),e.isEmptyObject(i)||e.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),undefined):(e.each(i,function(i,a){var s,n;a=e.isFunction(a)?{click:a,text:i}:a,a=e.extend({type:"button"},a),s=a.click,a.click=function(){s.apply(t.element[0],arguments)},n={icons:a.icons,text:a.showText},delete a.icons,delete a.showText,e("<button></button>",a).button(n).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),undefined)},_makeDraggable:function(){function t(e){return{position:e.position,offset:e.offset}}var i=this,a=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(a,s){e(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",a,t(s))},drag:function(e,a){i._trigger("drag",e,t(a))},stop:function(s,n){a.position=[n.position.left-i.document.scrollLeft(),n.position.top-i.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",s,t(n))}})},_makeResizable:function(){function t(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var i=this,a=this.options,s=a.resizable,n=this.uiDialog.css("position"),r="string"==typeof s?s:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:a.maxWidth,maxHeight:a.maxHeight,minWidth:a.minWidth,minHeight:this._minHeight(),handles:r,start:function(a,s){e(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",a,t(s))},resize:function(e,a){i._trigger("resize",e,t(a))},stop:function(s,n){a.height=e(this).height(),a.width=e(this).width(),e(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",s,t(n))}}).css("position",n)},_minHeight:function(){var e=this.options;return"auto"===e.height?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(a){var s=this,n=!1,r={};e.each(a,function(e,a){s._setOption(e,a),e in t&&(n=!0),e in i&&(r[e]=a)}),n&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",r)},_setOption:function(e,t){var i,a,s=this.uiDialog;"dialogClass"===e&&s.removeClass(this.options.dialogClass).addClass(t),"disabled"!==e&&(this._super(e,t),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:""+t}),"draggable"===e&&(i=s.is(":data(ui-draggable)"),i&&!t&&s.draggable("destroy"),!i&&t&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(a=s.is(":data(ui-resizable)"),a&&!t&&s.resizable("destroy"),a&&"string"==typeof t&&s.resizable("option","handles",t),a||t===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var e,t,i,a=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),a.minWidth>a.width&&(a.width=a.minWidth),e=this.uiDialog.css({height:"auto",width:a.width}).outerHeight(),t=Math.max(0,a.minHeight-e),i="number"==typeof a.maxHeight?Math.max(0,a.maxHeight-e):"none","auto"===a.height?this.element.css({minHeight:t,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,a.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=e(this);return e("<div>").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return e(t.target).closest(".ui-dialog").length?!0:!!e(t.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var t=this,i=this.widgetFullName;e.ui.dialog.overlayInstances||this._delay(function(){e.ui.dialog.overlayInstances&&this.document.bind("focusin.dialog",function(a){t._allowInteraction(a)||(a.preventDefault(),e(".ui-dialog:visible:last .ui-dialog-content").data(i)._focusTabbable())})}),this.overlay=e("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),e.ui.dialog.overlayInstances++}},_destroyOverlay:function(){this.options.modal&&this.overlay&&(e.ui.dialog.overlayInstances--,e.ui.dialog.overlayInstances||this.document.unbind("focusin.dialog"),this.overlay.remove(),this.overlay=null)}}),e.ui.dialog.overlayInstances=0,e.uiBackCompat!==!1&&e.widget("ui.dialog",e.ui.dialog,{_position:function(){var t,i=this.options.position,a=[],s=[0,0];i?(("string"==typeof i||"object"==typeof i&&"0"in i)&&(a=i.split?i.split(" "):[i[0],i[1]],1===a.length&&(a[1]=a[0]),e.each(["left","top"],function(e,t){+a[e]===a[e]&&(s[e]=a[e],a[e]=t)}),i={my:a[0]+(0>s[0]?s[0]:"+"+s[0])+" "+a[1]+(0>s[1]?s[1]:"+"+s[1]),at:a.join(" ")}),i=e.extend({},e.ui.dialog.prototype.options.position,i)):i=e.ui.dialog.prototype.options.position,t=this.uiDialog.is(":visible"),t||this.uiDialog.show(),this.uiDialog.position(i),t||this.uiDialog.hide()}})})(jQuery);(function(t){t.widget("ui.menu",{version:"1.10.4",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,t.proxy(function(t){this.options.disabled&&t.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(t){t.preventDefault()},"click .ui-state-disabled > a":function(t){t.preventDefault()},"click .ui-menu-item:has(a)":function(e){var i=t(e.target).closest(".ui-menu-item");!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(e),e.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(e):!this.element.is(":focus")&&t(this.document[0].activeElement).closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){var i=t(e.currentTarget);i.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(e,i)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.children(".ui-menu-item").eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){t.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){t(e.target).closest(".ui-menu").length||this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var e=t(this);e.data("ui-menu-submenu-carat")&&e.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(e){function i(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var s,n,a,o,r,l=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:l=!1,n=this.previousFilter||"",a=String.fromCharCode(e.keyCode),o=!1,clearTimeout(this.filterTimer),a===n?o=!0:a=n+a,r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())}),s=o&&-1!==s.index(this.active.next())?this.active.nextAll(".ui-menu-item"):s,s.length||(a=String.fromCharCode(e.keyCode),r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())})),s.length?(this.focus(e,s),s.length>1?(this.previousFilter=a,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}l&&e.preventDefault()},_activate:function(t){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i=this.options.icons.submenu,s=this.element.find(this.options.menus);this.element.toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length),s.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),s=e.prev("a"),n=t("<span>").addClass("ui-menu-icon ui-icon "+i).data("ui-menu-submenu-carat",!0);s.attr("aria-haspopup","true").prepend(n),e.attr("aria-labelledby",s.attr("id"))}),e=s.add(this.element),e.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),e.children(":not(.ui-menu-item)").each(function(){var e=t(this);/[^\-\u2014\u2013\s]/.test(e.text())||e.addClass("ui-widget-content ui-menu-divider")}),e.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){"icons"===t&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(e.submenu),this._super(t,e)},focus:function(t,e){var i,s;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=e.height(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",t,{item:this.active}))},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.children(".ui-menu-item")[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())),undefined):(this.next(e),undefined)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item").first())),undefined):(this.next(e),undefined)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(e){this.active=this.active||t(e.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(e,!0),this._trigger("select",e,i)}})})(jQuery);(function(t,e){t.widget("ui.progressbar",{version:"1.10.4",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=t("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(t){return t===e?this.options.value:(this.options.value=this._constrainedValue(t),this._refreshValue(),e)},_constrainedValue:function(t){return t===e&&(t=this.options.value),this.indeterminate=t===!1,"number"!=typeof t&&(t=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,t))},_setOptions:function(t){var e=t.value;delete t.value,this._super(t),this.options.value=this._constrainedValue(e),this._refreshValue()},_setOption:function(t,e){"max"===t&&(e=Math.max(this.min,e)),this._super(t,e)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var e=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(i.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=t("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":e}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),e===this.options.max&&this._trigger("complete")}})})(jQuery);(function(t){var e=5;t.widget("ui.slider",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this._refresh(),this._setOption("disabled",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,i,s=this.options,n=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),a="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",o=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),e=n.length;i>e;e++)o.push(a);this.handles=n.add(t(o.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(e){t(this).data("ui-slider-handle-index",e)})},_createRange:function(){var e=this.options,i="";e.range?(e.range===!0&&(e.values?e.values.length&&2!==e.values.length?e.values=[e.values[0],e.values[0]]:t.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({left:"",bottom:""}):(this.range=t("<div></div>").appendTo(this.element),i="ui-slider-range ui-widget-header ui-corner-all"),this.range.addClass(i+("min"===e.range||"max"===e.range?" ui-slider-range-"+e.range:""))):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){var t=this.handles.add(this.range).filter("a");this._off(t),this._on(t,this._handleEvents),this._hoverable(t),this._focusable(t)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,a,o,r,l,h,u=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),i={x:e.pageX,y:e.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var i=Math.abs(s-u.values(e));(n>i||n===i&&(e===u._lastChangedValue||u.values(e)===c.min))&&(n=i,a=t(this),o=e)}),r=this._start(e,o),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,a.addClass("ui-state-active").focus(),l=a.offset(),h=!t(e.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=h?{left:0,top:0}:{left:e.pageX-l.left-a.width()/2,top:e.pageY-l.top-a.height()/2-(parseInt(a.css("borderTopWidth"),10)||0)-(parseInt(a.css("borderBottomWidth"),10)||0)+(parseInt(a.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(e,o,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,i),!1},_mouseStop:function(t){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,i,s,n,a;return"horizontal"===this.orientation?(e=this.elementSize.width,i=t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,i=t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/e,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),a=this._valueMin()+s*n,this._trimAlignValue(a)},_start:function(t,e){var i={handle:this.handles[e],value:this.value()};return this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("start",t,i)},_slide:function(t,e,i){var s,n,a;this.options.values&&this.options.values.length?(s=this.values(e?0:1),2===this.options.values.length&&this.options.range===!0&&(0===e&&i>s||1===e&&s>i)&&(i=s),i!==this.values(e)&&(n=this.values(),n[e]=i,a=this._trigger("slide",t,{handle:this.handles[e],value:i,values:n}),s=this.values(e?0:1),a!==!1&&this.values(e,i))):i!==this.value()&&(a=this._trigger("slide",t,{handle:this.handles[e],value:i}),a!==!1&&this.value(i))},_stop:function(t,e){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("stop",t,i)},_change:function(t,e){if(!this._keySliding&&!this._mouseSliding){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._lastChangedValue=e,this._trigger("change",t,i)}},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),this._change(null,0),undefined):this._value()},values:function(e,i){var s,n,a;if(arguments.length>1)return this.options.values[e]=this._trimAlignValue(i),this._refreshValue(),this._change(null,e),undefined;if(!arguments.length)return this._values();if(!t.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(e):this.value();for(s=this.options.values,n=arguments[0],a=0;s.length>a;a+=1)s[a]=this._trimAlignValue(n[a]),this._change(null,a);this._refreshValue()},_setOption:function(e,i){var s,n=0;switch("range"===e&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.values=null):"max"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),t.isArray(this.options.values)&&(n=this.options.values.length),t.Widget.prototype._setOption.apply(this,arguments),e){case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),s=0;n>s;s+=1)this._change(null,s);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var t=this.options.value;return t=this._trimAlignValue(t)},_values:function(t){var e,i,s;if(arguments.length)return e=this.options.values[t],e=this._trimAlignValue(e);if(this.options.values&&this.options.values.length){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(t){if(this._valueMin()>=t)return this._valueMin();if(t>=this._valueMax())return this._valueMax();var e=this.options.step>0?this.options.step:1,i=(t-this._valueMin())%e,s=t-i;return 2*Math.abs(i)>=e&&(s+=i>0?e:-e),parseFloat(s.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var e,i,s,n,a,o=this.options.range,r=this.options,l=this,h=this._animateOff?!1:r.animate,u={};this.options.values&&this.options.values.length?this.handles.each(function(s){i=100*((l.values(s)-l._valueMin())/(l._valueMax()-l._valueMin())),u["horizontal"===l.orientation?"left":"bottom"]=i+"%",t(this).stop(1,1)[h?"animate":"css"](u,r.animate),l.options.range===!0&&("horizontal"===l.orientation?(0===s&&l.range.stop(1,1)[h?"animate":"css"]({left:i+"%"},r.animate),1===s&&l.range[h?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:r.animate})):(0===s&&l.range.stop(1,1)[h?"animate":"css"]({bottom:i+"%"},r.animate),1===s&&l.range[h?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:r.animate}))),e=i}):(s=this.value(),n=this._valueMin(),a=this._valueMax(),i=a!==n?100*((s-n)/(a-n)):0,u["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[h?"animate":"css"](u,r.animate),"min"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[h?"animate":"css"]({width:i+"%"},r.animate),"max"===o&&"horizontal"===this.orientation&&this.range[h?"animate":"css"]({width:100-i+"%"},{queue:!1,duration:r.animate}),"min"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[h?"animate":"css"]({height:i+"%"},r.animate),"max"===o&&"vertical"===this.orientation&&this.range[h?"animate":"css"]({height:100-i+"%"},{queue:!1,duration:r.animate}))},_handleEvents:{keydown:function(i){var s,n,a,o,r=t(i.target).data("ui-slider-handle-index");switch(i.keyCode){case t.ui.keyCode.HOME:case t.ui.keyCode.END:case t.ui.keyCode.PAGE_UP:case t.ui.keyCode.PAGE_DOWN:case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(i.preventDefault(),!this._keySliding&&(this._keySliding=!0,t(i.target).addClass("ui-state-active"),s=this._start(i,r),s===!1))return}switch(o=this.options.step,n=a=this.options.values&&this.options.values.length?this.values(r):this.value(),i.keyCode){case t.ui.keyCode.HOME:a=this._valueMin();break;case t.ui.keyCode.END:a=this._valueMax();break;case t.ui.keyCode.PAGE_UP:a=this._trimAlignValue(n+(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.PAGE_DOWN:a=this._trimAlignValue(n-(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:if(n===this._valueMax())return;a=this._trimAlignValue(n+o);break;case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(n===this._valueMin())return;a=this._trimAlignValue(n-o)}this._slide(i,r,a)},click:function(t){t.preventDefault()},keyup:function(e){var i=t(e.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(e,i),this._change(e,i),t(e.target).removeClass("ui-state-active"))}}})})(jQuery);(function(t){function e(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._trigger("change")}}t.widget("ui.spinner",{version:"1.10.4",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e={},i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);void 0!==n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var t=this.element[0]===this.document[0].activeElement;t||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._start(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var t=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=t.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*t.height())&&t.height()>0&&t.height(t.height()),this.options.disabled&&this.disable()},_keydown:function(e){var i=this.options,s=t.ui.keyCode;switch(e.keyCode){case s.UP:return this._repeat(null,1,e),!0;case s.DOWN:return this._repeat(null,-1,e),!0;case s.PAGE_UP:return this._repeat(null,i.page,e),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,e),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>&#9650;</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>&#9660;</span>"+"</a>"},_start:function(t){return this.spinning||this._trigger("start",t)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&this._trigger("spin",e,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(e){var i=this.options.incremental;return i?t.isFunction(i)?i(e):Math.floor(e*e*e/5e4-e*e/500+17*e/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.min&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_adjustValue:function(t){var e,i,s=this.options;return e=null!==s.min?s.min:0,i=t-e,i=Math.round(i/s.step)*s.step,t=e+i,t=parseFloat(t.toFixed(this._precision())),null!==s.max&&t>s.max?s.max:null!==s.min&&s.min>t?s.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){if("culture"===t||"numberFormat"===t){var i=this._parse(this.element.val());return this.options[t]=e,this.element.val(this._format(i)),void 0}("max"===t||"min"===t||"step"===t)&&"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(e.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(e.down)),this._super(t,e),"disabled"===t&&(e?(this.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:e(function(t){this._super(t),this._value(this.element.val())}),_parse:function(t){return"string"==typeof t&&""!==t&&(t=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t),""===t||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(t,e){var i;""!==t&&(i=this._parse(t),null!==i&&(e||(i=this._adjustValue(i)),t=this._format(i))),this.element.val(t),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:e(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:e(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:e(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:e(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){return arguments.length?(e(this._value).call(this,t),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}})})(jQuery);(function(t,e){function i(){return++n}function s(t){return t=t.cloneNode(!1),t.hash.length>1&&decodeURIComponent(t.href.replace(a,""))===decodeURIComponent(location.href.replace(a,""))}var n=0,a=/#.*$/;t.widget("ui.tabs",{version:"1.10.4",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var e=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var i=this.options.active,s=this.options.collapsible,n=location.hash.substring(1);return null===i&&(n&&this.tabs.each(function(s,a){return t(a).attr("aria-controls")===n?(i=s,!1):e}),null===i&&(i=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===i||-1===i)&&(i=this.tabs.length?0:!1)),i!==!1&&(i=this.tabs.index(this.tabs.eq(i)),-1===i&&(i=s?!1:0)),!s&&i===!1&&this.anchors.length&&(i=0),i},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(i){var s=t(this.document[0].activeElement).closest("li"),n=this.tabs.index(s),a=!0;if(!this._handlePageNav(i)){switch(i.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:n++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:a=!1,n--;break;case t.ui.keyCode.END:n=this.anchors.length-1;break;case t.ui.keyCode.HOME:n=0;break;case t.ui.keyCode.SPACE:return i.preventDefault(),clearTimeout(this.activating),this._activate(n),e;case t.ui.keyCode.ENTER:return i.preventDefault(),clearTimeout(this.activating),this._activate(n===this.options.active?!1:n),e;default:return}i.preventDefault(),clearTimeout(this.activating),n=this._focusNextTab(n,a),i.ctrlKey||(s.attr("aria-selected","false"),this.tabs.eq(n).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",n)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.focus())},_handlePageNav:function(i){return i.altKey&&i.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):i.altKey&&i.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):e},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).focus(),t},_setOption:function(t,i){return"active"===t?(this._activate(i),e):"disabled"===t?(this._setupDisabled(i),e):(this._super(t,i),"collapsible"===t&&(this.element.toggleClass("ui-tabs-collapsible",i),i||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(i),"heightStyle"===t&&this._setupHeightStyle(i),e)},_tabId:function(t){return t.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=t(),this.anchors.each(function(i,n){var a,o,r,h=t(n).uniqueId().attr("id"),l=t(n).closest("li"),c=l.attr("aria-controls");s(n)?(a=n.hash,o=e.element.find(e._sanitizeSelector(a))):(r=e._tabId(l),a="#"+r,o=e.element.find(a),o.length||(o=e._createPanel(r),o.insertAfter(e.panels[i-1]||e.tablist)),o.attr("aria-live","polite")),o.length&&(e.panels=e.panels.add(o)),c&&l.data("ui-tabs-aria-controls",c),l.attr({"aria-controls":a.substring(1),"aria-labelledby":h}),o.attr("aria-labelledby",h)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.tablist||this.element.find("ol,ul").eq(0)},_createPanel:function(e){return t("<div>").attr("id",e).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(e){t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1);for(var i,s=0;i=this.tabs[s];s++)e===!0||-1!==t.inArray(s,e)?t(i).addClass("ui-state-disabled").attr("aria-disabled","true"):t(i).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=e},_setupEvents:function(e){var i={click:function(t){t.preventDefault()}};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i))},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?t():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):t(),c={oldTab:s,oldPanel:l,newTab:r?t():a,newPanel:h};e.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",e,c)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?t():a,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),e),this._toggle(e,c))},_toggle:function(e,i){function s(){a.running=!1,a._trigger("activate",e,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr({"aria-expanded":"false","aria-hidden":"true"}),i.oldTab.attr("aria-selected","false"),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr({"aria-expanded":"true","aria-hidden":"false"}),i.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(t){return"string"==typeof t&&(t=this.anchors.index(this.anchors.filter("[href$='"+t+"']"))),t},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var s=this.options.disabled;s!==!1&&(i===e?s=!1:(i=this._getIndex(i),s=t.isArray(s)?t.map(s,function(t){return t!==i?t:null}):t.map(this.tabs,function(t,e){return e!==i?e:null})),this._setupDisabled(s))},disable:function(i){var s=this.options.disabled;if(s!==!0){if(i===e)s=!0;else{if(i=this._getIndex(i),-1!==t.inArray(i,s))return;s=t.isArray(s)?t.merge([i],s).sort():[i]}this._setupDisabled(s)}},load:function(e,i){e=this._getIndex(e);var n=this,a=this.tabs.eq(e),o=a.find(".ui-tabs-anchor"),r=this._getPanelForTab(a),h={tab:a,panel:r};s(o[0])||(this.xhr=t.ajax(this._ajaxSettings(o,i,h)),this.xhr&&"canceled"!==this.xhr.statusText&&(a.addClass("ui-tabs-loading"),r.attr("aria-busy","true"),this.xhr.success(function(t){setTimeout(function(){r.html(t),n._trigger("load",i,h)},1)}).complete(function(t,e){setTimeout(function(){"abort"===e&&n.panels.stop(!1,!0),a.removeClass("ui-tabs-loading"),r.removeAttr("aria-busy"),t===n.xhr&&delete n.xhr},1)})))},_ajaxSettings:function(e,i,s){var n=this;return{url:e.attr("href"),beforeSend:function(e,a){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:a},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}})})(jQuery);(function(t){function e(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))}function i(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")}var s=0;t.widget("ui.tooltip",{version:"1.10.4",options:{content:function(){var e=t(this).attr("title")||"";return t("<a>").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(e,i){var s=this;return"disabled"===e?(this[i?"_disable":"_enable"](),this.options[e]=i,void 0):(this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e)}),void 0)},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.is("[title]")&&e.data("ui-tooltip-title",e.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))})},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,o=e?e.type:null;return"string"==typeof s?this._open(e,t,s):(i=s.call(t[0],function(i){t.data("ui-tooltip-open")&&n._delay(function(){e&&(e.type=o),this._open(e,t,i)})}),i&&this._open(e,t,i),void 0)},_open:function(i,s,n){function o(t){l.of=t,a.is(":hidden")||a.position(l)}var a,r,h,l=t.extend({},this.options.position);if(n){if(a=this._find(s),a.length)return a.find(".ui-tooltip-content").html(n),void 0;s.is("[title]")&&(i&&"mouseover"===i.type?s.attr("title",""):s.removeAttr("title")),a=this._tooltip(s),e(s,a.attr("id")),a.find(".ui-tooltip-content").html(n),this.options.track&&i&&/^mouse/.test(i.type)?(this._on(this.document,{mousemove:o}),o(i)):a.position(t.extend({of:s},this.options.position)),a.hide(),this._show(a,this.options.show),this.options.show&&this.options.show.delay&&(h=this.delayedShow=setInterval(function(){a.is(":visible")&&(o(l.of),clearInterval(h))},t.fx.interval)),this._trigger("open",i,{tooltip:a}),r={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var i=t.Event(e);i.currentTarget=s[0],this.close(i,!0)}},remove:function(){this._removeTooltip(a)}},i&&"mouseover"!==i.type||(r.mouseleave="close"),i&&"focusin"!==i.type||(r.focusout="close"),this._on(!0,s,r)}},close:function(e){var s=this,n=t(e?e.currentTarget:this.element),o=this._find(n);this.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&n.attr("title",n.data("ui-tooltip-title")),i(n),o.stop(!0),this._hide(o,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),this.closing=!0,this._trigger("close",e,{tooltip:o}),this.closing=!1)},_tooltip:function(e){var i="ui-tooltip-"+s++,n=t("<div>").attr({id:i,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return t("<div>").addClass("ui-tooltip-content").appendTo(n),n.appendTo(this.document[0].body),this.tooltips[i]=e,n},_find:function(e){var i=e.data("ui-tooltip-id");return i?t("#"+i):t()},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0),t("#"+i).remove(),s.data("ui-tooltip-title")&&(s.attr("title",s.data("ui-tooltip-title")),s.removeData("ui-tooltip-title"))})}})})(jQuery);(function(t,e){var i="ui-effects-";t.effects={effect:{}},function(t,e){function i(t,e,i){var s=u[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:0>t?0:t>s.max?s.max:t)}function s(i){var s=h(),n=s._rgba=[];return i=i.toLowerCase(),f(l,function(t,a){var o,r=a.re.exec(i),l=r&&a.parse(r),h=a.space||"rgba";return l?(o=s[h](l),s[c[h].cache]=o[c[h].cache],n=s._rgba=o._rgba,!1):e}),n.length?("0,0,0,0"===n.join()&&t.extend(n,a.transparent),s):a[i]}function n(t,e,i){return i=(i+1)%1,1>6*i?t+6*(e-t)*i:1>2*i?e:2>3*i?t+6*(e-t)*(2/3-i):t}var a,o="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,l=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[t[1],t[2],t[3],t[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[2.55*t[1],2.55*t[2],2.55*t[3],t[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(t){return[t[1],t[2]/100,t[3]/100,t[4]]}}],h=t.Color=function(e,i,s,n){return new t.Color.fn.parse(e,i,s,n)},c={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},d=h.support={},p=t("<p>")[0],f=t.each;p.style.cssText="background-color:rgba(1,1,1,.5)",d.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(c,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),h.fn=t.extend(h.prototype,{parse:function(n,o,r,l){if(n===e)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=t(n).css(o),o=e);var u=this,d=t.type(n),p=this._rgba=[];return o!==e&&(n=[n,o,r,l],d="array"),"string"===d?this.parse(s(n)||a._default):"array"===d?(f(c.rgba.props,function(t,e){p[e.idx]=i(n[e.idx],e)}),this):"object"===d?(n instanceof h?f(c,function(t,e){n[e.cache]&&(u[e.cache]=n[e.cache].slice())}):f(c,function(e,s){var a=s.cache;f(s.props,function(t,e){if(!u[a]&&s.to){if("alpha"===t||null==n[t])return;u[a]=s.to(u._rgba)}u[a][e.idx]=i(n[t],e,!0)}),u[a]&&0>t.inArray(null,u[a].slice(0,3))&&(u[a][3]=1,s.from&&(u._rgba=s.from(u[a])))}),this):e},is:function(t){var i=h(t),s=!0,n=this;return f(c,function(t,a){var o,r=i[a.cache];return r&&(o=n[a.cache]||a.to&&a.to(n._rgba)||[],f(a.props,function(t,i){return null!=r[i.idx]?s=r[i.idx]===o[i.idx]:e})),s}),s},_space:function(){var t=[],e=this;return f(c,function(i,s){e[s.cache]&&t.push(i)}),t.pop()},transition:function(t,e){var s=h(t),n=s._space(),a=c[n],o=0===this.alpha()?h("transparent"):this,r=o[a.cache]||a.to(o._rgba),l=r.slice();return s=s[a.cache],f(a.props,function(t,n){var a=n.idx,o=r[a],h=s[a],c=u[n.type]||{};null!==h&&(null===o?l[a]=h:(c.mod&&(h-o>c.mod/2?o+=c.mod:o-h>c.mod/2&&(o-=c.mod)),l[a]=i((h-o)*e+o,n)))}),this[n](l)},blend:function(e){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=h(e)._rgba;return h(t.map(i,function(t,e){return(1-s)*n[e]+s*t}))},toRgbaString:function(){var e="rgba(",i=t.map(this._rgba,function(t,e){return null==t?e>2?1:0:t});return 1===i[3]&&(i.pop(),e="rgb("),e+i.join()+")"},toHslaString:function(){var e="hsla(",i=t.map(this.hsla(),function(t,e){return null==t&&(t=e>2?1:0),e&&3>e&&(t=Math.round(100*t)+"%"),t});return 1===i[3]&&(i.pop(),e="hsl("),e+i.join()+")"},toHexString:function(e){var i=this._rgba.slice(),s=i.pop();return e&&i.push(~~(255*s)),"#"+t.map(i,function(t){return t=(t||0).toString(16),1===t.length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),h.fn.parse.prototype=h.fn,c.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e,i,s=t[0]/255,n=t[1]/255,a=t[2]/255,o=t[3],r=Math.max(s,n,a),l=Math.min(s,n,a),h=r-l,c=r+l,u=.5*c;return e=l===r?0:s===r?60*(n-a)/h+360:n===r?60*(a-s)/h+120:60*(s-n)/h+240,i=0===h?0:.5>=u?h/c:h/(2-c),[Math.round(e)%360,i,u,null==o?1:o]},c.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],a=t[3],o=.5>=s?s*(1+i):s+i-s*i,r=2*s-o;return[Math.round(255*n(r,o,e+1/3)),Math.round(255*n(r,o,e)),Math.round(255*n(r,o,e-1/3)),a]},f(c,function(s,n){var a=n.props,o=n.cache,l=n.to,c=n.from;h.fn[s]=function(s){if(l&&!this[o]&&(this[o]=l(this._rgba)),s===e)return this[o].slice();var n,r=t.type(s),u="array"===r||"object"===r?s:arguments,d=this[o].slice();return f(a,function(t,e){var s=u["object"===r?t:e.idx];null==s&&(s=d[e.idx]),d[e.idx]=i(s,e)}),c?(n=h(c(d)),n[o]=d,n):h(d)},f(a,function(e,i){h.fn[e]||(h.fn[e]=function(n){var a,o=t.type(n),l="alpha"===e?this._hsla?"hsla":"rgba":s,h=this[l](),c=h[i.idx];return"undefined"===o?c:("function"===o&&(n=n.call(this,c),o=t.type(n)),null==n&&i.empty?this:("string"===o&&(a=r.exec(n),a&&(n=c+parseFloat(a[2])*("+"===a[1]?1:-1))),h[i.idx]=n,this[l](h)))})})}),h.hook=function(e){var i=e.split(" ");f(i,function(e,i){t.cssHooks[i]={set:function(e,n){var a,o,r="";if("transparent"!==n&&("string"!==t.type(n)||(a=s(n)))){if(n=h(a||n),!d.rgba&&1!==n._rgba[3]){for(o="backgroundColor"===i?e.parentNode:e;(""===r||"transparent"===r)&&o&&o.style;)try{r=t.css(o,"backgroundColor"),o=o.parentNode}catch(l){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{e.style[i]=n}catch(l){}}},t.fx.step[i]=function(e){e.colorInit||(e.start=h(e.elem,i),e.end=h(e.end),e.colorInit=!0),t.cssHooks[i].set(e.elem,e.start.transition(e.end,e.pos))}})},h.hook(o),t.cssHooks.borderColor={expand:function(t){var e={};return f(["Top","Right","Bottom","Left"],function(i,s){e["border"+s+"Color"]=t}),e}},a=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(e){var i,s,n=e.ownerDocument.defaultView?e.ownerDocument.defaultView.getComputedStyle(e,null):e.currentStyle,a={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(a[t.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(a[i]=n[i]);return a}function s(e,i){var s,n,o={};for(s in i)n=i[s],e[s]!==n&&(a[s]||(t.fx.step[s]||!isNaN(parseFloat(n)))&&(o[s]=n));return o}var n=["add","remove","toggle"],a={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};t.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(e,i){t.fx.step[i]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(jQuery.style(t.elem,i,t.end),t.setAttr=!0)}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.effects.animateClass=function(e,a,o,r){var l=t.speed(a,o,r);return this.queue(function(){var a,o=t(this),r=o.attr("class")||"",h=l.children?o.find("*").addBack():o;h=h.map(function(){var e=t(this);return{el:e,start:i(this)}}),a=function(){t.each(n,function(t,i){e[i]&&o[i+"Class"](e[i])})},a(),h=h.map(function(){return this.end=i(this.el[0]),this.diff=s(this.start,this.end),this}),o.attr("class",r),h=h.map(function(){var e=this,i=t.Deferred(),s=t.extend({},l,{queue:!1,complete:function(){i.resolve(e)}});return this.el.animate(this.diff,s),i.promise()}),t.when.apply(t,h.get()).done(function(){a(),t.each(arguments,function(){var e=this.el;t.each(this.diff,function(t){e.css(t,"")})}),l.complete.call(o[0])})})},t.fn.extend({addClass:function(e){return function(i,s,n,a){return s?t.effects.animateClass.call(this,{add:i},s,n,a):e.apply(this,arguments)}}(t.fn.addClass),removeClass:function(e){return function(i,s,n,a){return arguments.length>1?t.effects.animateClass.call(this,{remove:i},s,n,a):e.apply(this,arguments)}}(t.fn.removeClass),toggleClass:function(i){return function(s,n,a,o,r){return"boolean"==typeof n||n===e?a?t.effects.animateClass.call(this,n?{add:s}:{remove:s},a,o,r):i.apply(this,arguments):t.effects.animateClass.call(this,{toggle:s},n,a,o)}}(t.fn.toggleClass),switchClass:function(e,i,s,n,a){return t.effects.animateClass.call(this,{add:i,remove:e},s,n,a)}})}(),function(){function s(e,i,s,n){return t.isPlainObject(e)&&(i=e,e=e.effect),e={effect:e},null==i&&(i={}),t.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||t.fx.speeds[i])&&(n=s,s=i,i={}),t.isFunction(s)&&(n=s,s=null),i&&t.extend(e,i),s=s||i.duration,e.duration=t.fx.off?0:"number"==typeof s?s:s in t.fx.speeds?t.fx.speeds[s]:t.fx.speeds._default,e.complete=n||i.complete,e}function n(e){return!e||"number"==typeof e||t.fx.speeds[e]?!0:"string"!=typeof e||t.effects.effect[e]?t.isFunction(e)?!0:"object"!=typeof e||e.effect?!1:!0:!0}t.extend(t.effects,{version:"1.10.4",save:function(t,e){for(var s=0;e.length>s;s++)null!==e[s]&&t.data(i+e[s],t[0].style[e[s]])},restore:function(t,s){var n,a;for(a=0;s.length>a;a++)null!==s[a]&&(n=t.data(i+s[a]),n===e&&(n=""),t.css(s[a],n))},setMode:function(t,e){return"toggle"===e&&(e=t.is(":hidden")?"show":"hide"),e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createWrapper:function(e){if(e.parent().is(".ui-effects-wrapper"))return e.parent();var i={width:e.outerWidth(!0),height:e.outerHeight(!0),"float":e.css("float")},s=t("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:e.width(),height:e.height()},a=document.activeElement;try{a.id}catch(o){a=document.body}return e.wrap(s),(e[0]===a||t.contains(e[0],a))&&t(a).focus(),s=e.parent(),"static"===e.css("position")?(s.css({position:"relative"}),e.css({position:"relative"})):(t.extend(i,{position:e.css("position"),zIndex:e.css("z-index")}),t.each(["top","left","bottom","right"],function(t,s){i[s]=e.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),e.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),e.css(n),s.css(i).show()},removeWrapper:function(e){var i=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),(e[0]===i||t.contains(e[0],i))&&t(i).focus()),e},setTransition:function(e,i,s,n){return n=n||{},t.each(i,function(t,i){var a=e.cssUnit(i);a[0]>0&&(n[i]=a[0]*s+a[1])}),n}}),t.fn.extend({effect:function(){function e(e){function s(){t.isFunction(a)&&a.call(n[0]),t.isFunction(e)&&e()}var n=t(this),a=i.complete,r=i.mode;(n.is(":hidden")?"hide"===r:"show"===r)?(n[r](),s()):o.call(n[0],i,s)}var i=s.apply(this,arguments),n=i.mode,a=i.queue,o=t.effects.effect[i.effect];return t.fx.off||!o?n?this[n](i.duration,i.complete):this.each(function(){i.complete&&i.complete.call(this)}):a===!1?this.each(e):this.queue(a||"fx",e)},show:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="show",this.effect.call(this,i)}}(t.fn.show),hide:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="hide",this.effect.call(this,i)}}(t.fn.hide),toggle:function(t){return function(e){if(n(e)||"boolean"==typeof e)return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="toggle",this.effect.call(this,i)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s}})}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}()})(jQuery);(function(t){var e=/up|down|vertical/,i=/up|left|vertical|horizontal/;t.effects.effect.blind=function(s,n){var a,o,r,l=t(this),h=["position","top","bottom","left","right","height","width"],c=t.effects.setMode(l,s.mode||"hide"),u=s.direction||"up",d=e.test(u),p=d?"height":"width",f=d?"top":"left",g=i.test(u),m={},v="show"===c;l.parent().is(".ui-effects-wrapper")?t.effects.save(l.parent(),h):t.effects.save(l,h),l.show(),a=t.effects.createWrapper(l).css({overflow:"hidden"}),o=a[p](),r=parseFloat(a.css(f))||0,m[p]=v?o:0,g||(l.css(d?"bottom":"right",0).css(d?"top":"left","auto").css({position:"absolute"}),m[f]=v?r:o+r),v&&(a.css(p,0),g||a.css(f,r+o)),a.animate(m,{duration:s.duration,easing:s.easing,queue:!1,complete:function(){"hide"===c&&l.hide(),t.effects.restore(l,h),t.effects.removeWrapper(l),n()}})}})(jQuery);(function(t){t.effects.effect.bounce=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","height","width"],l=t.effects.setMode(o,e.mode||"effect"),h="hide"===l,c="show"===l,u=e.direction||"up",d=e.distance,p=e.times||5,f=2*p+(c||h?1:0),g=e.duration/f,m=e.easing,v="up"===u||"down"===u?"top":"left",_="up"===u||"left"===u,b=o.queue(),y=b.length;for((c||h)&&r.push("opacity"),t.effects.save(o,r),o.show(),t.effects.createWrapper(o),d||(d=o["top"===v?"outerHeight":"outerWidth"]()/3),c&&(a={opacity:1},a[v]=0,o.css("opacity",0).css(v,_?2*-d:2*d).animate(a,g,m)),h&&(d/=Math.pow(2,p-1)),a={},a[v]=0,s=0;p>s;s++)n={},n[v]=(_?"-=":"+=")+d,o.animate(n,g,m).animate(a,g,m),d=h?2*d:d/2;h&&(n={opacity:0},n[v]=(_?"-=":"+=")+d,o.animate(n,g,m)),o.queue(function(){h&&o.hide(),t.effects.restore(o,r),t.effects.removeWrapper(o),i()}),y>1&&b.splice.apply(b,[1,0].concat(b.splice(y,f+1))),o.dequeue()}})(jQuery);(function(t){t.effects.effect.clip=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","height","width"],l=t.effects.setMode(o,e.mode||"hide"),h="show"===l,c=e.direction||"vertical",u="vertical"===c,d=u?"height":"width",p=u?"top":"left",f={};t.effects.save(o,r),o.show(),s=t.effects.createWrapper(o).css({overflow:"hidden"}),n="IMG"===o[0].tagName?s:o,a=n[d](),h&&(n.css(d,0),n.css(p,a/2)),f[d]=h?a:0,f[p]=h?0:a/2,n.animate(f,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){h||o.hide(),t.effects.restore(o,r),t.effects.removeWrapper(o),i()}})}})(jQuery);(function(t){t.effects.effect.drop=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","opacity","height","width"],o=t.effects.setMode(n,e.mode||"hide"),r="show"===o,l=e.direction||"left",h="up"===l||"down"===l?"top":"left",c="up"===l||"left"===l?"pos":"neg",u={opacity:r?1:0};t.effects.save(n,a),n.show(),t.effects.createWrapper(n),s=e.distance||n["top"===h?"outerHeight":"outerWidth"](!0)/2,r&&n.css("opacity",0).css(h,"pos"===c?-s:s),u[h]=(r?"pos"===c?"+=":"-=":"pos"===c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}})}})(jQuery);(function(t){t.effects.effect.explode=function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),g||p.hide(),i()}var a,o,r,l,h,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=t.effects.setMode(p,e.mode||"hide"),g="show"===f,m=p.show().css("visibility","hidden").offset(),v=Math.ceil(p.outerWidth()/d),_=Math.ceil(p.outerHeight()/u),b=[];for(a=0;u>a;a++)for(l=m.top+a*_,c=a-(u-1)/2,o=0;d>o;o++)r=m.left+o*v,h=o-(d-1)/2,p.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-o*v,top:-a*_}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:v,height:_,left:r+(g?h*v:0),top:l+(g?c*_:0),opacity:g?0:1}).animate({left:r+(g?0:h*v),top:l+(g?0:c*_),opacity:g?1:0},e.duration||500,e.easing,s)}})(jQuery);(function(t){t.effects.effect.fade=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"toggle");s.animate({opacity:n},{queue:!1,duration:e.duration,easing:e.easing,complete:i})}})(jQuery);(function(t){t.effects.effect.fold=function(e,i){var s,n,a=t(this),o=["position","top","bottom","left","right","height","width"],r=t.effects.setMode(a,e.mode||"hide"),l="show"===r,h="hide"===r,c=e.size||15,u=/([0-9]+)%/.exec(c),d=!!e.horizFirst,p=l!==d,f=p?["width","height"]:["height","width"],g=e.duration/2,m={},v={};t.effects.save(a,o),a.show(),s=t.effects.createWrapper(a).css({overflow:"hidden"}),n=p?[s.width(),s.height()]:[s.height(),s.width()],u&&(c=parseInt(u[1],10)/100*n[h?0:1]),l&&s.css(d?{height:0,width:c}:{height:c,width:0}),m[f[0]]=l?n[0]:c,v[f[1]]=l?n[1]:0,s.animate(m,g,e.easing).animate(v,g,e.easing,function(){h&&a.hide(),t.effects.restore(a,o),t.effects.removeWrapper(a),i()})}})(jQuery);(function(t){t.effects.effect.highlight=function(e,i){var s=t(this),n=["backgroundImage","backgroundColor","opacity"],a=t.effects.setMode(s,e.mode||"show"),o={backgroundColor:s.css("backgroundColor")};"hide"===a&&(o.opacity=0),t.effects.save(s,n),s.show().css({backgroundImage:"none",backgroundColor:e.color||"#ffff99"}).animate(o,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===a&&s.hide(),t.effects.restore(s,n),i()}})}})(jQuery);(function(t){t.effects.effect.pulsate=function(e,i){var s,n=t(this),a=t.effects.setMode(n,e.mode||"show"),o="show"===a,r="hide"===a,l=o||"hide"===a,h=2*(e.times||5)+(l?1:0),c=e.duration/h,u=0,d=n.queue(),p=d.length;for((o||!n.is(":visible"))&&(n.css("opacity",0).show(),u=1),s=1;h>s;s++)n.animate({opacity:u},c,e.easing),u=1-u;n.animate({opacity:u},c,e.easing),n.queue(function(){r&&n.hide(),i()}),p>1&&d.splice.apply(d,[1,0].concat(d.splice(p,h+1))),n.dequeue()}})(jQuery);(function(t){t.effects.effect.puff=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"hide"),a="hide"===n,o=parseInt(e.percent,10)||150,r=o/100,l={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()};t.extend(e,{effect:"scale",queue:!1,fade:!0,mode:n,complete:i,percent:a?o:100,from:a?l:{height:l.height*r,width:l.width*r,outerHeight:l.outerHeight*r,outerWidth:l.outerWidth*r}}),s.effect(e)},t.effects.effect.scale=function(e,i){var s=t(this),n=t.extend(!0,{},e),a=t.effects.setMode(s,e.mode||"effect"),o=parseInt(e.percent,10)||(0===parseInt(e.percent,10)?0:"hide"===a?0:100),r=e.direction||"both",l=e.origin,h={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()},c={y:"horizontal"!==r?o/100:1,x:"vertical"!==r?o/100:1};n.effect="size",n.queue=!1,n.complete=i,"effect"!==a&&(n.origin=l||["middle","center"],n.restore=!0),n.from=e.from||("show"===a?{height:0,width:0,outerHeight:0,outerWidth:0}:h),n.to={height:h.height*c.y,width:h.width*c.x,outerHeight:h.outerHeight*c.y,outerWidth:h.outerWidth*c.x},n.fade&&("show"===a&&(n.from.opacity=0,n.to.opacity=1),"hide"===a&&(n.from.opacity=1,n.to.opacity=0)),s.effect(n)},t.effects.effect.size=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","width","height","overflow","opacity"],l=["position","top","bottom","left","right","overflow","opacity"],h=["width","height","overflow"],c=["fontSize"],u=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],d=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=t.effects.setMode(o,e.mode||"effect"),f=e.restore||"effect"!==p,g=e.scale||"both",m=e.origin||["middle","center"],v=o.css("position"),_=f?r:l,b={height:0,width:0,outerHeight:0,outerWidth:0};"show"===p&&o.show(),s={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},"toggle"===e.mode&&"show"===p?(o.from=e.to||b,o.to=e.from||s):(o.from=e.from||("show"===p?b:s),o.to=e.to||("hide"===p?b:s)),a={from:{y:o.from.height/s.height,x:o.from.width/s.width},to:{y:o.to.height/s.height,x:o.to.width/s.width}},("box"===g||"both"===g)&&(a.from.y!==a.to.y&&(_=_.concat(u),o.from=t.effects.setTransition(o,u,a.from.y,o.from),o.to=t.effects.setTransition(o,u,a.to.y,o.to)),a.from.x!==a.to.x&&(_=_.concat(d),o.from=t.effects.setTransition(o,d,a.from.x,o.from),o.to=t.effects.setTransition(o,d,a.to.x,o.to))),("content"===g||"both"===g)&&a.from.y!==a.to.y&&(_=_.concat(c).concat(h),o.from=t.effects.setTransition(o,c,a.from.y,o.from),o.to=t.effects.setTransition(o,c,a.to.y,o.to)),t.effects.save(o,_),o.show(),t.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),m&&(n=t.effects.getBaseline(m,s),o.from.top=(s.outerHeight-o.outerHeight())*n.y,o.from.left=(s.outerWidth-o.outerWidth())*n.x,o.to.top=(s.outerHeight-o.to.outerHeight)*n.y,o.to.left=(s.outerWidth-o.to.outerWidth)*n.x),o.css(o.from),("content"===g||"both"===g)&&(u=u.concat(["marginTop","marginBottom"]).concat(c),d=d.concat(["marginLeft","marginRight"]),h=r.concat(u).concat(d),o.find("*[width]").each(function(){var i=t(this),s={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()};f&&t.effects.save(i,h),i.from={height:s.height*a.from.y,width:s.width*a.from.x,outerHeight:s.outerHeight*a.from.y,outerWidth:s.outerWidth*a.from.x},i.to={height:s.height*a.to.y,width:s.width*a.to.x,outerHeight:s.height*a.to.y,outerWidth:s.width*a.to.x},a.from.y!==a.to.y&&(i.from=t.effects.setTransition(i,u,a.from.y,i.from),i.to=t.effects.setTransition(i,u,a.to.y,i.to)),a.from.x!==a.to.x&&(i.from=t.effects.setTransition(i,d,a.from.x,i.from),i.to=t.effects.setTransition(i,d,a.to.x,i.to)),i.css(i.from),i.animate(i.to,e.duration,e.easing,function(){f&&t.effects.restore(i,h)})})),o.animate(o.to,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){0===o.to.opacity&&o.css("opacity",o.from.opacity),"hide"===p&&o.hide(),t.effects.restore(o,_),f||("static"===v?o.css({position:"relative",top:o.to.top,left:o.to.left}):t.each(["top","left"],function(t,e){o.css(e,function(e,i){var s=parseInt(i,10),n=t?o.to.left:o.to.top;return"auto"===i?n+"px":s+n+"px"})})),t.effects.removeWrapper(o),i()}})}})(jQuery);(function(t){t.effects.effect.shake=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","height","width"],o=t.effects.setMode(n,e.mode||"effect"),r=e.direction||"left",l=e.distance||20,h=e.times||3,c=2*h+1,u=Math.round(e.duration/c),d="up"===r||"down"===r?"top":"left",p="up"===r||"left"===r,f={},g={},m={},v=n.queue(),_=v.length;for(t.effects.save(n,a),n.show(),t.effects.createWrapper(n),f[d]=(p?"-=":"+=")+l,g[d]=(p?"+=":"-=")+2*l,m[d]=(p?"-=":"+=")+2*l,n.animate(f,u,e.easing),s=1;h>s;s++)n.animate(g,u,e.easing).animate(m,u,e.easing);n.animate(g,u,e.easing).animate(f,u/2,e.easing).queue(function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}),_>1&&v.splice.apply(v,[1,0].concat(v.splice(_,c+1))),n.dequeue()}})(jQuery);(function(t){t.effects.effect.slide=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","width","height"],o=t.effects.setMode(n,e.mode||"show"),r="show"===o,l=e.direction||"left",h="up"===l||"down"===l?"top":"left",c="up"===l||"left"===l,u={};t.effects.save(n,a),n.show(),s=e.distance||n["top"===h?"outerHeight":"outerWidth"](!0),t.effects.createWrapper(n).css({overflow:"hidden"}),r&&n.css(h,c?isNaN(s)?"-"+s:-s:s),u[h]=(r?c?"+=":"-=":c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}})}})(jQuery);(function(t){t.effects.effect.transfer=function(e,i){var s=t(this),n=t(e.to),a="fixed"===n.css("position"),o=t("body"),r=a?o.scrollTop():0,l=a?o.scrollLeft():0,h=n.offset(),c={top:h.top-r,left:h.left-l,height:n.innerHeight(),width:n.innerWidth()},u=s.offset(),d=t("<div class='ui-effects-transfer'></div>").appendTo(document.body).addClass(e.className).css({top:u.top-r,left:u.left-l,height:s.innerHeight(),width:s.innerWidth(),position:a?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){d.remove(),i()})}})(jQuery);
\ No newline at end of file
diff --git a/themes/greydragon/js/jquery.cycle.js b/themes/greydragon/js/jquery.cycle.js
new file mode 100644
index 0000000..dc474ea
--- /dev/null
+++ b/themes/greydragon/js/jquery.cycle.js
@@ -0,0 +1,1543 @@
+/*!
+ * jQuery Cycle Plugin (with Transition Definitions)
+ * Examples and documentation at: http://jquery.malsup.com/cycle/
+ * Copyright (c) 2007-2013 M. Alsup
+ * Version: 3.0.3 (11-JUL-2013)
+ * Dual licensed under the MIT and GPL licenses.
+ * http://jquery.malsup.com/license.html
+ * Requires: jQuery v1.7.1 or later
+ */
+;(function($, undefined) {
+"use strict";
+
+var ver = '3.0.3';
+
+function debug(s) {
+	if ($.fn.cycle.debug)
+		log(s);
+}		
+function log() {
+	/*global console */
+	if (window.console && console.log)
+		console.log('[cycle] ' + Array.prototype.join.call(arguments,' '));
+}
+$.expr[':'].paused = function(el) {
+	return el.cyclePause;
+};
+
+
+// the options arg can be...
+//   a number  - indicates an immediate transition should occur to the given slide index
+//   a string  - 'pause', 'resume', 'toggle', 'next', 'prev', 'stop', 'destroy' or the name of a transition effect (ie, 'fade', 'zoom', etc)
+//   an object - properties to control the slideshow
+//
+// the arg2 arg can be...
+//   the name of an fx (only used in conjunction with a numeric value for 'options')
+//   the value true (only used in first arg == 'resume') and indicates
+//	 that the resume should occur immediately (not wait for next timeout)
+
+$.fn.cycle = function(options, arg2) {
+	var o = { s: this.selector, c: this.context };
+
+	// in 1.3+ we can fix mistakes with the ready state
+	if (this.length === 0 && options != 'stop') {
+		if (!$.isReady && o.s) {
+			log('DOM not ready, queuing slideshow');
+			$(function() {
+				$(o.s,o.c).cycle(options,arg2);
+			});
+			return this;
+		}
+		// is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
+		log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
+		return this;
+	}
+
+	// iterate the matched nodeset
+	return this.each(function() {
+		var opts = handleArguments(this, options, arg2);
+		if (opts === false)
+			return;
+
+		opts.updateActivePagerLink = opts.updateActivePagerLink || $.fn.cycle.updateActivePagerLink;
+		
+		// stop existing slideshow for this container (if there is one)
+		if (this.cycleTimeout)
+			clearTimeout(this.cycleTimeout);
+		this.cycleTimeout = this.cyclePause = 0;
+		this.cycleStop = 0; // issue #108
+
+		var $cont = $(this);
+		var $slides = opts.slideExpr ? $(opts.slideExpr, this) : $cont.children();
+		var els = $slides.get();
+
+		if (els.length < 2) {
+			log('terminating; too few slides: ' + els.length);
+			return;
+		}
+
+		var opts2 = buildOptions($cont, $slides, els, opts, o);
+		if (opts2 === false)
+			return;
+
+		var startTime = opts2.continuous ? 10 : getTimeout(els[opts2.currSlide], els[opts2.nextSlide], opts2, !opts2.backwards);
+
+		// if it's an auto slideshow, kick it off
+		if (startTime) {
+			startTime += (opts2.delay || 0);
+			if (startTime < 10)
+				startTime = 10;
+			debug('first timeout: ' + startTime);
+			this.cycleTimeout = setTimeout(function(){go(els,opts2,0,!opts.backwards);}, startTime);
+		}
+	});
+};
+
+function triggerPause(cont, byHover, onPager) {
+	var opts = $(cont).data('cycle.opts');
+	if (!opts)
+		return;
+	var paused = !!cont.cyclePause;
+	if (paused && opts.paused)
+		opts.paused(cont, opts, byHover, onPager);
+	else if (!paused && opts.resumed)
+		opts.resumed(cont, opts, byHover, onPager);
+}
+
+// process the args that were passed to the plugin fn
+function handleArguments(cont, options, arg2) {
+	if (cont.cycleStop === undefined)
+		cont.cycleStop = 0;
+	if (options === undefined || options === null)
+		options = {};
+	if (options.constructor == String) {
+		switch(options) {
+		case 'destroy':
+		case 'stop':
+			var opts = $(cont).data('cycle.opts');
+			if (!opts)
+				return false;
+			cont.cycleStop++; // callbacks look for change
+			if (cont.cycleTimeout)
+				clearTimeout(cont.cycleTimeout);
+			cont.cycleTimeout = 0;
+			if (opts.elements)
+				$(opts.elements).stop();
+			$(cont).removeData('cycle.opts');
+			if (options == 'destroy')
+				destroy(cont, opts);
+			return false;
+		case 'toggle':
+			cont.cyclePause = (cont.cyclePause === 1) ? 0 : 1;
+			checkInstantResume(cont.cyclePause, arg2, cont);
+			triggerPause(cont);
+			return false;
+		case 'pause':
+			cont.cyclePause = 1;
+			triggerPause(cont);
+			return false;
+		case 'resume':
+			cont.cyclePause = 0;
+			checkInstantResume(false, arg2, cont);
+			triggerPause(cont);
+			return false;
+		case 'prev':
+		case 'next':
+			opts = $(cont).data('cycle.opts');
+			if (!opts) {
+				log('options not found, "prev/next" ignored');
+				return false;
+			}
+			if (typeof arg2 == 'string') 
+				opts.oneTimeFx = arg2;
+			$.fn.cycle[options](opts);
+			return false;
+		default:
+			options = { fx: options };
+		}
+		return options;
+	}
+	else if (options.constructor == Number) {
+		// go to the requested slide
+		var num = options;
+		options = $(cont).data('cycle.opts');
+		if (!options) {
+			log('options not found, can not advance slide');
+			return false;
+		}
+		if (num < 0 || num >= options.elements.length) {
+			log('invalid slide index: ' + num);
+			return false;
+		}
+		options.nextSlide = num;
+		if (cont.cycleTimeout) {
+			clearTimeout(cont.cycleTimeout);
+			cont.cycleTimeout = 0;
+		}
+		if (typeof arg2 == 'string')
+			options.oneTimeFx = arg2;
+		go(options.elements, options, 1, num >= options.currSlide);
+		return false;
+	}
+	return options;
+	
+	function checkInstantResume(isPaused, arg2, cont) {
+		if (!isPaused && arg2 === true) { // resume now!
+			var options = $(cont).data('cycle.opts');
+			if (!options) {
+				log('options not found, can not resume');
+				return false;
+			}
+			if (cont.cycleTimeout) {
+				clearTimeout(cont.cycleTimeout);
+				cont.cycleTimeout = 0;
+			}
+			go(options.elements, options, 1, !options.backwards);
+		}
+	}
+}
+
+function removeFilter(el, opts) {
+	if (!$.support.opacity && opts.cleartype && el.style.filter) {
+		try { el.style.removeAttribute('filter'); }
+		catch(smother) {} // handle old opera versions
+	}
+}
+
+// unbind event handlers
+function destroy(cont, opts) {
+	if (opts.next)
+		$(opts.next).unbind(opts.prevNextEvent);
+	if (opts.prev)
+		$(opts.prev).unbind(opts.prevNextEvent);
+	
+	if (opts.pager || opts.pagerAnchorBuilder)
+		$.each(opts.pagerAnchors || [], function() {
+			this.unbind().remove();
+		});
+	opts.pagerAnchors = null;
+	$(cont).unbind('mouseenter.cycle mouseleave.cycle');
+	if (opts.destroy) // callback
+		opts.destroy(opts);
+}
+
+// one-time initialization
+function buildOptions($cont, $slides, els, options, o) {
+	var startingSlideSpecified;
+	// support metadata plugin (v1.0 and v2.0)
+	var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});
+	var meta = $.isFunction($cont.data) ? $cont.data(opts.metaAttr) : null;
+	if (meta)
+		opts = $.extend(opts, meta);
+	if (opts.autostop)
+		opts.countdown = opts.autostopCount || els.length;
+
+	var cont = $cont[0];
+	$cont.data('cycle.opts', opts);
+	opts.$cont = $cont;
+	opts.stopCount = cont.cycleStop;
+	opts.elements = els;
+	opts.before = opts.before ? [opts.before] : [];
+	opts.after = opts.after ? [opts.after] : [];
+
+	// push some after callbacks
+	if (!$.support.opacity && opts.cleartype)
+		opts.after.push(function() { removeFilter(this, opts); });
+	if (opts.continuous)
+		opts.after.push(function() { go(els,opts,0,!opts.backwards); });
+
+	saveOriginalOpts(opts);
+
+	// clearType corrections
+	if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
+		clearTypeFix($slides);
+
+	// container requires non-static position so that slides can be position within
+	if ($cont.css('position') == 'static')
+		$cont.css('position', 'relative');
+	if (opts.width)
+		$cont.width(opts.width);
+	if (opts.height && opts.height != 'auto')
+		$cont.height(opts.height);
+
+	if (opts.startingSlide !== undefined) {
+		opts.startingSlide = parseInt(opts.startingSlide,10);
+		if (opts.startingSlide >= els.length || opts.startSlide < 0)
+			opts.startingSlide = 0; // catch bogus input
+		else 
+			startingSlideSpecified = true;
+	}
+	else if (opts.backwards)
+		opts.startingSlide = els.length - 1;
+	else
+		opts.startingSlide = 0;
+
+	// if random, mix up the slide array
+	if (opts.random) {
+		opts.randomMap = [];
+		for (var i = 0; i < els.length; i++)
+			opts.randomMap.push(i);
+		opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+		if (startingSlideSpecified) {
+			// try to find the specified starting slide and if found set start slide index in the map accordingly
+			for ( var cnt = 0; cnt < els.length; cnt++ ) {
+				if ( opts.startingSlide == opts.randomMap[cnt] ) {
+					opts.randomIndex = cnt;
+				}
+			}
+		}
+		else {
+			opts.randomIndex = 1;
+			opts.startingSlide = opts.randomMap[1];
+		}
+	}
+	else if (opts.startingSlide >= els.length)
+		opts.startingSlide = 0; // catch bogus input
+	opts.currSlide = opts.startingSlide || 0;
+	var first = opts.startingSlide;
+
+	// set position and zIndex on all the slides
+	$slides.css({position: 'absolute', top:0, left:0}).hide().each(function(i) {
+		var z;
+		if (opts.backwards)
+			z = first ? i <= first ? els.length + (i-first) : first-i : els.length-i;
+		else
+			z = first ? i >= first ? els.length - (i-first) : first-i : els.length-i;
+		$(this).css('z-index', z);
+	});
+
+	// make sure first slide is visible
+	$(els[first]).css('opacity',1).show(); // opacity bit needed to handle restart use case
+	removeFilter(els[first], opts);
+
+	// stretch slides
+	if (opts.fit) {
+		if (!opts.aspect) {
+	        if (opts.width)
+	            $slides.width(opts.width);
+	        if (opts.height && opts.height != 'auto')
+	            $slides.height(opts.height);
+		} else {
+			$slides.each(function(){
+				var $slide = $(this);
+				var ratio = (opts.aspect === true) ? $slide.width()/$slide.height() : opts.aspect;
+				if( opts.width && $slide.width() != opts.width ) {
+					$slide.width( opts.width );
+					$slide.height( opts.width / ratio );
+				}
+
+				if( opts.height && $slide.height() < opts.height ) {
+					$slide.height( opts.height );
+					$slide.width( opts.height * ratio );
+				}
+			});
+		}
+	}
+
+	if (opts.center && ((!opts.fit) || opts.aspect)) {
+		$slides.each(function(){
+			var $slide = $(this);
+			$slide.css({
+				"margin-left": opts.width ?
+					((opts.width - $slide.width()) / 2) + "px" :
+					0,
+				"margin-top": opts.height ?
+					((opts.height - $slide.height()) / 2) + "px" :
+					0
+			});
+		});
+	}
+
+	if (opts.center && !opts.fit && !opts.slideResize) {
+		$slides.each(function(){
+			var $slide = $(this);
+			$slide.css({
+				"margin-left": opts.width ? ((opts.width - $slide.width()) / 2) + "px" : 0,
+				"margin-top": opts.height ? ((opts.height - $slide.height()) / 2) + "px" : 0
+			});
+		});
+	}
+		
+	// stretch container
+	var reshape = (opts.containerResize || opts.containerResizeHeight) && $cont.innerHeight() < 1;
+	if (reshape) { // do this only if container has no size http://tinyurl.com/da2oa9
+		var maxw = 0, maxh = 0;
+		for(var j=0; j < els.length; j++) {
+			var $e = $(els[j]), e = $e[0], w = $e.outerWidth(), h = $e.outerHeight();
+			if (!w) w = e.offsetWidth || e.width || $e.attr('width');
+			if (!h) h = e.offsetHeight || e.height || $e.attr('height');
+			maxw = w > maxw ? w : maxw;
+			maxh = h > maxh ? h : maxh;
+		}
+		if (opts.containerResize && maxw > 0 && maxh > 0)
+			$cont.css({width:maxw+'px',height:maxh+'px'});
+		if (opts.containerResizeHeight && maxh > 0)
+			$cont.css({height:maxh+'px'});
+	}
+
+	var pauseFlag = false;  // https://github.com/malsup/cycle/issues/44
+	if (opts.pause)
+		$cont.bind('mouseenter.cycle', function(){
+			pauseFlag = true;
+			this.cyclePause++;
+			triggerPause(cont, true);
+		}).bind('mouseleave.cycle', function(){
+				if (pauseFlag)
+					this.cyclePause--;
+				triggerPause(cont, true);
+		});
+
+	if (supportMultiTransitions(opts) === false)
+		return false;
+
+	// apparently a lot of people use image slideshows without height/width attributes on the images.
+	// Cycle 2.50+ requires the sizing info for every slide; this block tries to deal with that.
+	var requeue = false;
+	options.requeueAttempts = options.requeueAttempts || 0;
+	$slides.each(function() {
+		// try to get height/width of each slide
+		var $el = $(this);
+		this.cycleH = (opts.fit && opts.height) ? opts.height : ($el.height() || this.offsetHeight || this.height || $el.attr('height') || 0);
+		this.cycleW = (opts.fit && opts.width) ? opts.width : ($el.width() || this.offsetWidth || this.width || $el.attr('width') || 0);
+
+		if ( $el.is('img') ) {
+			var loading = (this.cycleH === 0 && this.cycleW === 0 && !this.complete);
+			// don't requeue for images that are still loading but have a valid size
+			if (loading) {
+				if (o.s && opts.requeueOnImageNotLoaded && ++options.requeueAttempts < 100) { // track retry count so we don't loop forever
+					log(options.requeueAttempts,' - img slide not loaded, requeuing slideshow: ', this.src, this.cycleW, this.cycleH);
+					setTimeout(function() {$(o.s,o.c).cycle(options);}, opts.requeueTimeout);
+					requeue = true;
+					return false; // break each loop
+				}
+				else {
+					log('could not determine size of image: '+this.src, this.cycleW, this.cycleH);
+				}
+			}
+		}
+		return true;
+	});
+
+	if (requeue)
+		return false;
+
+	opts.cssBefore = opts.cssBefore || {};
+	opts.cssAfter = opts.cssAfter || {};
+	opts.cssFirst = opts.cssFirst || {};
+	opts.animIn = opts.animIn || {};
+	opts.animOut = opts.animOut || {};
+
+	$slides.not(':eq('+first+')').css(opts.cssBefore);
+	$($slides[first]).css(opts.cssFirst);
+
+	if (opts.timeout) {
+		opts.timeout = parseInt(opts.timeout,10);
+		// ensure that timeout and speed settings are sane
+		if (opts.speed.constructor == String)
+			opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed,10);
+		if (!opts.sync)
+			opts.speed = opts.speed / 2;
+		
+		var buffer = opts.fx == 'none' ? 0 : opts.fx == 'shuffle' ? 500 : 250;
+		while((opts.timeout - opts.speed) < buffer) // sanitize timeout
+			opts.timeout += opts.speed;
+	}
+	if (opts.easing)
+		opts.easeIn = opts.easeOut = opts.easing;
+	if (!opts.speedIn)
+		opts.speedIn = opts.speed;
+	if (!opts.speedOut)
+		opts.speedOut = opts.speed;
+
+	opts.slideCount = els.length;
+	opts.currSlide = opts.lastSlide = first;
+	if (opts.random) {
+		if (++opts.randomIndex == els.length)
+			opts.randomIndex = 0;
+		opts.nextSlide = opts.randomMap[opts.randomIndex];
+	}
+	else if (opts.backwards)
+		opts.nextSlide = opts.startingSlide === 0 ? (els.length-1) : opts.startingSlide-1;
+	else
+		opts.nextSlide = opts.startingSlide >= (els.length-1) ? 0 : opts.startingSlide+1;
+
+	// run transition init fn
+	if (!opts.multiFx) {
+		var init = $.fn.cycle.transitions[opts.fx];
+		if ($.isFunction(init))
+			init($cont, $slides, opts);
+		else if (opts.fx != 'custom' && !opts.multiFx) {
+			log('unknown transition: ' + opts.fx,'; slideshow terminating');
+			return false;
+		}
+	}
+
+	// fire artificial events
+	var e0 = $slides[first];
+	if (!opts.skipInitializationCallbacks) {
+		if (opts.before.length)
+			opts.before[0].apply(e0, [e0, e0, opts, true]);
+		if (opts.after.length)
+			opts.after[0].apply(e0, [e0, e0, opts, true]);
+	}
+	if (opts.next)
+		$(opts.next).bind(opts.prevNextEvent,function(){return advance(opts,1);});
+	if (opts.prev)
+		$(opts.prev).bind(opts.prevNextEvent,function(){return advance(opts,0);});
+	if (opts.pager || opts.pagerAnchorBuilder)
+		buildPager(els,opts);
+
+	exposeAddSlide(opts, els);
+
+	return opts;
+}
+
+// save off original opts so we can restore after clearing state
+function saveOriginalOpts(opts) {
+	opts.original = { before: [], after: [] };
+	opts.original.cssBefore = $.extend({}, opts.cssBefore);
+	opts.original.cssAfter  = $.extend({}, opts.cssAfter);
+	opts.original.animIn	= $.extend({}, opts.animIn);
+	opts.original.animOut   = $.extend({}, opts.animOut);
+	$.each(opts.before, function() { opts.original.before.push(this); });
+	$.each(opts.after,  function() { opts.original.after.push(this); });
+}
+
+function supportMultiTransitions(opts) {
+	var i, tx, txs = $.fn.cycle.transitions;
+	// look for multiple effects
+	if (opts.fx.indexOf(',') > 0) {
+		opts.multiFx = true;
+		opts.fxs = opts.fx.replace(/\s*/g,'').split(',');
+		// discard any bogus effect names
+		for (i=0; i < opts.fxs.length; i++) {
+			var fx = opts.fxs[i];
+			tx = txs[fx];
+			if (!tx || !txs.hasOwnProperty(fx) || !$.isFunction(tx)) {
+				log('discarding unknown transition: ',fx);
+				opts.fxs.splice(i,1);
+				i--;
+			}
+		}
+		// if we have an empty list then we threw everything away!
+		if (!opts.fxs.length) {
+			log('No valid transitions named; slideshow terminating.');
+			return false;
+		}
+	}
+	else if (opts.fx == 'all') {  // auto-gen the list of transitions
+		opts.multiFx = true;
+		opts.fxs = [];
+		for (var p in txs) {
+			if (txs.hasOwnProperty(p)) {
+				tx = txs[p];
+				if (txs.hasOwnProperty(p) && $.isFunction(tx))
+					opts.fxs.push(p);
+			}
+		}
+	}
+	if (opts.multiFx && opts.randomizeEffects) {
+		// munge the fxs array to make effect selection random
+		var r1 = Math.floor(Math.random() * 20) + 30;
+		for (i = 0; i < r1; i++) {
+			var r2 = Math.floor(Math.random() * opts.fxs.length);
+			opts.fxs.push(opts.fxs.splice(r2,1)[0]);
+		}
+		debug('randomized fx sequence: ',opts.fxs);
+	}
+	return true;
+}
+
+// provide a mechanism for adding slides after the slideshow has started
+function exposeAddSlide(opts, els) {
+	opts.addSlide = function(newSlide, prepend) {
+		var $s = $(newSlide), s = $s[0];
+		if (!opts.autostopCount)
+			opts.countdown++;
+		els[prepend?'unshift':'push'](s);
+		if (opts.els)
+			opts.els[prepend?'unshift':'push'](s); // shuffle needs this
+		opts.slideCount = els.length;
+
+		// add the slide to the random map and resort
+		if (opts.random) {
+			opts.randomMap.push(opts.slideCount-1);
+			opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+		}
+
+		$s.css('position','absolute');
+		$s[prepend?'prependTo':'appendTo'](opts.$cont);
+
+		if (prepend) {
+			opts.currSlide++;
+			opts.nextSlide++;
+		}
+
+		if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
+			clearTypeFix($s);
+
+		if (opts.fit && opts.width)
+			$s.width(opts.width);
+		if (opts.fit && opts.height && opts.height != 'auto')
+			$s.height(opts.height);
+		s.cycleH = (opts.fit && opts.height) ? opts.height : $s.height();
+		s.cycleW = (opts.fit && opts.width) ? opts.width : $s.width();
+
+		$s.css(opts.cssBefore);
+
+		if (opts.pager || opts.pagerAnchorBuilder)
+			$.fn.cycle.createPagerAnchor(els.length-1, s, $(opts.pager), els, opts);
+
+		if ($.isFunction(opts.onAddSlide))
+			opts.onAddSlide($s);
+		else
+			$s.hide(); // default behavior
+	};
+}
+
+// reset internal state; we do this on every pass in order to support multiple effects
+$.fn.cycle.resetState = function(opts, fx) {
+	fx = fx || opts.fx;
+	opts.before = []; opts.after = [];
+	opts.cssBefore = $.extend({}, opts.original.cssBefore);
+	opts.cssAfter  = $.extend({}, opts.original.cssAfter);
+	opts.animIn	= $.extend({}, opts.original.animIn);
+	opts.animOut   = $.extend({}, opts.original.animOut);
+	opts.fxFn = null;
+	$.each(opts.original.before, function() { opts.before.push(this); });
+	$.each(opts.original.after,  function() { opts.after.push(this); });
+
+	// re-init
+	var init = $.fn.cycle.transitions[fx];
+	if ($.isFunction(init))
+		init(opts.$cont, $(opts.elements), opts);
+};
+
+// this is the main engine fn, it handles the timeouts, callbacks and slide index mgmt
+function go(els, opts, manual, fwd) {
+	var p = opts.$cont[0], curr = els[opts.currSlide], next = els[opts.nextSlide];
+
+	// opts.busy is true if we're in the middle of an animation
+	if (manual && opts.busy && opts.manualTrump) {
+		// let manual transitions requests trump active ones
+		debug('manualTrump in go(), stopping active transition');
+		$(els).stop(true,true);
+		opts.busy = 0;
+		clearTimeout(p.cycleTimeout);
+	}
+
+	// don't begin another timeout-based transition if there is one active
+	if (opts.busy) {
+		debug('transition active, ignoring new tx request');
+		return;
+	}
+
+
+	// stop cycling if we have an outstanding stop request
+	if (p.cycleStop != opts.stopCount || p.cycleTimeout === 0 && !manual)
+		return;
+
+	// check to see if we should stop cycling based on autostop options
+	if (!manual && !p.cyclePause && !opts.bounce &&
+		((opts.autostop && (--opts.countdown <= 0)) ||
+		(opts.nowrap && !opts.random && opts.nextSlide < opts.currSlide))) {
+		if (opts.end)
+			opts.end(opts);
+		return;
+	}
+
+	// if slideshow is paused, only transition on a manual trigger
+	var changed = false;
+	if ((manual || !p.cyclePause) && (opts.nextSlide != opts.currSlide)) {
+		changed = true;
+		var fx = opts.fx;
+		// keep trying to get the slide size if we don't have it yet
+		curr.cycleH = curr.cycleH || $(curr).height();
+		curr.cycleW = curr.cycleW || $(curr).width();
+		next.cycleH = next.cycleH || $(next).height();
+		next.cycleW = next.cycleW || $(next).width();
+
+		// support multiple transition types
+		if (opts.multiFx) {
+			if (fwd && (opts.lastFx === undefined || ++opts.lastFx >= opts.fxs.length))
+				opts.lastFx = 0;
+			else if (!fwd && (opts.lastFx === undefined || --opts.lastFx < 0))
+				opts.lastFx = opts.fxs.length - 1;
+			fx = opts.fxs[opts.lastFx];
+		}
+
+		// one-time fx overrides apply to:  $('div').cycle(3,'zoom');
+		if (opts.oneTimeFx) {
+			fx = opts.oneTimeFx;
+			opts.oneTimeFx = null;
+		}
+
+		$.fn.cycle.resetState(opts, fx);
+
+		// run the before callbacks
+		if (opts.before.length)
+			$.each(opts.before, function(i,o) {
+				if (p.cycleStop != opts.stopCount) return;
+				o.apply(next, [curr, next, opts, fwd]);
+			});
+
+		// stage the after callacks
+		var after = function() {
+			opts.busy = 0;
+			$.each(opts.after, function(i,o) {
+				if (p.cycleStop != opts.stopCount) return;
+				o.apply(next, [curr, next, opts, fwd]);
+			});
+			if (!p.cycleStop) {
+				// queue next transition
+				queueNext();
+			}
+		};
+
+		debug('tx firing('+fx+'); currSlide: ' + opts.currSlide + '; nextSlide: ' + opts.nextSlide);
+		
+		// get ready to perform the transition
+		opts.busy = 1;
+		if (opts.fxFn) // fx function provided?
+			opts.fxFn(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+		else if ($.isFunction($.fn.cycle[opts.fx])) // fx plugin ?
+			$.fn.cycle[opts.fx](curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+		else
+			$.fn.cycle.custom(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+	}
+	else {
+		queueNext();
+	}
+
+	if (changed || opts.nextSlide == opts.currSlide) {
+		// calculate the next slide
+		var roll;
+		opts.lastSlide = opts.currSlide;
+		if (opts.random) {
+			opts.currSlide = opts.nextSlide;
+			if (++opts.randomIndex == els.length) {
+				opts.randomIndex = 0;
+				opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+			}
+			opts.nextSlide = opts.randomMap[opts.randomIndex];
+			if (opts.nextSlide == opts.currSlide)
+				opts.nextSlide = (opts.currSlide == opts.slideCount - 1) ? 0 : opts.currSlide + 1;
+		}
+		else if (opts.backwards) {
+			roll = (opts.nextSlide - 1) < 0;
+			if (roll && opts.bounce) {
+				opts.backwards = !opts.backwards;
+				opts.nextSlide = 1;
+				opts.currSlide = 0;
+			}
+			else {
+				opts.nextSlide = roll ? (els.length-1) : opts.nextSlide-1;
+				opts.currSlide = roll ? 0 : opts.nextSlide+1;
+			}
+		}
+		else { // sequence
+			roll = (opts.nextSlide + 1) == els.length;
+			if (roll && opts.bounce) {
+				opts.backwards = !opts.backwards;
+				opts.nextSlide = els.length-2;
+				opts.currSlide = els.length-1;
+			}
+			else {
+				opts.nextSlide = roll ? 0 : opts.nextSlide+1;
+				opts.currSlide = roll ? els.length-1 : opts.nextSlide-1;
+			}
+		}
+	}
+	if (changed && opts.pager)
+		opts.updateActivePagerLink(opts.pager, opts.currSlide, opts.activePagerClass);
+	
+	function queueNext() {
+		// stage the next transition
+		var ms = 0, timeout = opts.timeout;
+		if (opts.timeout && !opts.continuous) {
+			ms = getTimeout(els[opts.currSlide], els[opts.nextSlide], opts, fwd);
+         if (opts.fx == 'shuffle')
+            ms -= opts.speedOut;
+      }
+		else if (opts.continuous && p.cyclePause) // continuous shows work off an after callback, not this timer logic
+			ms = 10;
+		if (ms > 0)
+			p.cycleTimeout = setTimeout(function(){ go(els, opts, 0, !opts.backwards); }, ms);
+	}
+}
+
+// invoked after transition
+$.fn.cycle.updateActivePagerLink = function(pager, currSlide, clsName) {
+   $(pager).each(function() {
+       $(this).children().removeClass(clsName).eq(currSlide).addClass(clsName);
+   });
+};
+
+// calculate timeout value for current transition
+function getTimeout(curr, next, opts, fwd) {
+	if (opts.timeoutFn) {
+		// call user provided calc fn
+		var t = opts.timeoutFn.call(curr,curr,next,opts,fwd);
+		while (opts.fx != 'none' && (t - opts.speed) < 250) // sanitize timeout
+			t += opts.speed;
+		debug('calculated timeout: ' + t + '; speed: ' + opts.speed);
+		if (t !== false)
+			return t;
+	}
+	return opts.timeout;
+}
+
+// expose next/prev function, caller must pass in state
+$.fn.cycle.next = function(opts) { advance(opts,1); };
+$.fn.cycle.prev = function(opts) { advance(opts,0);};
+
+// advance slide forward or back
+function advance(opts, moveForward) {
+	var val = moveForward ? 1 : -1;
+	var els = opts.elements;
+	var p = opts.$cont[0], timeout = p.cycleTimeout;
+	if (timeout) {
+		clearTimeout(timeout);
+		p.cycleTimeout = 0;
+	}
+	if (opts.random && val < 0) {
+		// move back to the previously display slide
+		opts.randomIndex--;
+		if (--opts.randomIndex == -2)
+			opts.randomIndex = els.length-2;
+		else if (opts.randomIndex == -1)
+			opts.randomIndex = els.length-1;
+		opts.nextSlide = opts.randomMap[opts.randomIndex];
+	}
+	else if (opts.random) {
+		opts.nextSlide = opts.randomMap[opts.randomIndex];
+	}
+	else {
+		opts.nextSlide = opts.currSlide + val;
+		if (opts.nextSlide < 0) {
+			if (opts.nowrap) return false;
+			opts.nextSlide = els.length - 1;
+		}
+		else if (opts.nextSlide >= els.length) {
+			if (opts.nowrap) return false;
+			opts.nextSlide = 0;
+		}
+	}
+
+	var cb = opts.onPrevNextEvent || opts.prevNextClick; // prevNextClick is deprecated
+	if ($.isFunction(cb))
+		cb(val > 0, opts.nextSlide, els[opts.nextSlide]);
+	go(els, opts, 1, moveForward);
+	return false;
+}
+
+function buildPager(els, opts) {
+	var $p = $(opts.pager);
+	$.each(els, function(i,o) {
+		$.fn.cycle.createPagerAnchor(i,o,$p,els,opts);
+	});
+	opts.updateActivePagerLink(opts.pager, opts.startingSlide, opts.activePagerClass);
+}
+
+$.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
+	var a;
+	if ($.isFunction(opts.pagerAnchorBuilder)) {
+		a = opts.pagerAnchorBuilder(i,el);
+		debug('pagerAnchorBuilder('+i+', el) returned: ' + a);
+	}
+	else
+		a = '<a href="#">'+(i+1)+'</a>';
+		
+	if (!a)
+		return;
+	var $a = $(a);
+	// don't reparent if anchor is in the dom
+	if ($a.parents('body').length === 0) {
+		var arr = [];
+		if ($p.length > 1) {
+			$p.each(function() {
+				var $clone = $a.clone(true);
+				$(this).append($clone);
+				arr.push($clone[0]);
+			});
+			$a = $(arr);
+		}
+		else {
+			$a.appendTo($p);
+		}
+	}
+
+	opts.pagerAnchors =  opts.pagerAnchors || [];
+	opts.pagerAnchors.push($a);
+	
+	var pagerFn = function(e) {
+		e.preventDefault();
+		opts.nextSlide = i;
+		var p = opts.$cont[0], timeout = p.cycleTimeout;
+		if (timeout) {
+			clearTimeout(timeout);
+			p.cycleTimeout = 0;
+		}
+		var cb = opts.onPagerEvent || opts.pagerClick; // pagerClick is deprecated
+		if ($.isFunction(cb))
+			cb(opts.nextSlide, els[opts.nextSlide]);
+		go(els,opts,1,opts.currSlide < i); // trigger the trans
+//		return false; // <== allow bubble
+	};
+	
+	if ( /mouseenter|mouseover/i.test(opts.pagerEvent) ) {
+		$a.hover(pagerFn, function(){/* no-op */} );
+	}
+	else {
+		$a.bind(opts.pagerEvent, pagerFn);
+	}
+	
+	if ( ! /^click/.test(opts.pagerEvent) && !opts.allowPagerClickBubble)
+		$a.bind('click.cycle', function(){return false;}); // suppress click
+	
+	var cont = opts.$cont[0];
+	var pauseFlag = false; // https://github.com/malsup/cycle/issues/44
+	if (opts.pauseOnPagerHover) {
+		$a.hover(
+			function() { 
+				pauseFlag = true;
+				cont.cyclePause++; 
+				triggerPause(cont,true,true);
+			}, function() { 
+				if (pauseFlag)
+					cont.cyclePause--; 
+				triggerPause(cont,true,true);
+			} 
+		);
+	}
+};
+
+// helper fn to calculate the number of slides between the current and the next
+$.fn.cycle.hopsFromLast = function(opts, fwd) {
+	var hops, l = opts.lastSlide, c = opts.currSlide;
+	if (fwd)
+		hops = c > l ? c - l : opts.slideCount - l;
+	else
+		hops = c < l ? l - c : l + opts.slideCount - c;
+	return hops;
+};
+
+// fix clearType problems in ie6 by setting an explicit bg color
+// (otherwise text slides look horrible during a fade transition)
+function clearTypeFix($slides) {
+	debug('applying clearType background-color hack');
+	function hex(s) {
+		s = parseInt(s,10).toString(16);
+		return s.length < 2 ? '0'+s : s;
+	}
+	function getBg(e) {
+		for ( ; e && e.nodeName.toLowerCase() != 'html'; e = e.parentNode) {
+			var v = $.css(e,'background-color');
+			if (v && v.indexOf('rgb') >= 0 ) {
+				var rgb = v.match(/\d+/g);
+				return '#'+ hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
+			}
+			if (v && v != 'transparent')
+				return v;
+		}
+		return '#ffffff';
+	}
+	$slides.each(function() { $(this).css('background-color', getBg(this)); });
+}
+
+// reset common props before the next transition
+$.fn.cycle.commonReset = function(curr,next,opts,w,h,rev) {
+	$(opts.elements).not(curr).hide();
+	if (typeof opts.cssBefore.opacity == 'undefined')
+		opts.cssBefore.opacity = 1;
+	opts.cssBefore.display = 'block';
+	if (opts.slideResize && w !== false && next.cycleW > 0)
+		opts.cssBefore.width = next.cycleW;
+	if (opts.slideResize && h !== false && next.cycleH > 0)
+		opts.cssBefore.height = next.cycleH;
+	opts.cssAfter = opts.cssAfter || {};
+	opts.cssAfter.display = 'none';
+	$(curr).css('zIndex',opts.slideCount + (rev === true ? 1 : 0));
+	$(next).css('zIndex',opts.slideCount + (rev === true ? 0 : 1));
+};
+
+// the actual fn for effecting a transition
+$.fn.cycle.custom = function(curr, next, opts, cb, fwd, speedOverride) {
+	var $l = $(curr), $n = $(next);
+	var speedIn = opts.speedIn, speedOut = opts.speedOut, easeIn = opts.easeIn, easeOut = opts.easeOut, animInDelay = opts.animInDelay, animOutDelay = opts.animOutDelay;
+	$n.css(opts.cssBefore);
+	if (speedOverride) {
+		if (typeof speedOverride == 'number')
+			speedIn = speedOut = speedOverride;
+		else
+			speedIn = speedOut = 1;
+		easeIn = easeOut = null;
+	}
+	var fn = function() {
+		$n.delay(animInDelay).animate(opts.animIn, speedIn, easeIn, function() {
+			cb();
+		});
+	};
+	$l.delay(animOutDelay).animate(opts.animOut, speedOut, easeOut, function() {
+		$l.css(opts.cssAfter);
+		if (!opts.sync) 
+			fn();
+	});
+	if (opts.sync) fn();
+};
+
+// transition definitions - only fade is defined here, transition pack defines the rest
+$.fn.cycle.transitions = {
+	fade: function($cont, $slides, opts) {
+		$slides.not(':eq('+opts.currSlide+')').css('opacity',0);
+		opts.before.push(function(curr,next,opts) {
+			$.fn.cycle.commonReset(curr,next,opts);
+			opts.cssBefore.opacity = 0;
+		});
+		opts.animIn	   = { opacity: 1 };
+		opts.animOut   = { opacity: 0 };
+		opts.cssBefore = { top: 0, left: 0 };
+	}
+};
+
+$.fn.cycle.ver = function() { return ver; };
+
+// override these globally if you like (they are all optional)
+$.fn.cycle.defaults = {
+    activePagerClass: 'activeSlide', // class name used for the active pager link
+    after:            null,     // transition callback (scope set to element that was shown):  function(currSlideElement, nextSlideElement, options, forwardFlag)
+    allowPagerClickBubble: false, // allows or prevents click event on pager anchors from bubbling
+    animIn:           null,     // properties that define how the slide animates in
+    animInDelay:      0,        // allows delay before next slide transitions in	
+    animOut:          null,     // properties that define how the slide animates out
+    animOutDelay:     0,        // allows delay before current slide transitions out
+    aspect:           false,    // preserve aspect ratio during fit resizing, cropping if necessary (must be used with fit option)
+    autostop:         0,        // true to end slideshow after X transitions (where X == slide count)
+    autostopCount:    0,        // number of transitions (optionally used with autostop to define X)
+    backwards:        false,    // true to start slideshow at last slide and move backwards through the stack
+    before:           null,     // transition callback (scope set to element to be shown):     function(currSlideElement, nextSlideElement, options, forwardFlag)
+    center:           null,     // set to true to have cycle add top/left margin to each slide (use with width and height options)
+    cleartype:        !$.support.opacity,  // true if clearType corrections should be applied (for IE)
+    cleartypeNoBg:    false,    // set to true to disable extra cleartype fixing (leave false to force background color setting on slides)
+    containerResize:  1,        // resize container to fit largest slide
+    containerResizeHeight:  0,  // resize containers height to fit the largest slide but leave the width dynamic
+    continuous:       0,        // true to start next transition immediately after current one completes
+    cssAfter:         null,     // properties that defined the state of the slide after transitioning out
+    cssBefore:        null,     // properties that define the initial state of the slide before transitioning in
+    delay:            0,        // additional delay (in ms) for first transition (hint: can be negative)
+    easeIn:           null,     // easing for "in" transition
+    easeOut:          null,     // easing for "out" transition
+    easing:           null,     // easing method for both in and out transitions
+    end:              null,     // callback invoked when the slideshow terminates (use with autostop or nowrap options): function(options)
+    fastOnEvent:      0,        // force fast transitions when triggered manually (via pager or prev/next); value == time in ms
+    fit:              0,        // force slides to fit container
+    fx:               'fade',   // name of transition effect (or comma separated names, ex: 'fade,scrollUp,shuffle')
+    fxFn:             null,     // function used to control the transition: function(currSlideElement, nextSlideElement, options, afterCalback, forwardFlag)
+    height:           'auto',   // container height (if the 'fit' option is true, the slides will be set to this height as well)
+    manualTrump:      true,     // causes manual transition to stop an active transition instead of being ignored
+    metaAttr:         'cycle',  // data- attribute that holds the option data for the slideshow
+    next:             null,     // element, jQuery object, or jQuery selector string for the element to use as event trigger for next slide
+    nowrap:           0,        // true to prevent slideshow from wrapping
+    onPagerEvent:     null,     // callback fn for pager events: function(zeroBasedSlideIndex, slideElement)
+    onPrevNextEvent:  null,     // callback fn for prev/next events: function(isNext, zeroBasedSlideIndex, slideElement)
+    pager:            null,     // element, jQuery object, or jQuery selector string for the element to use as pager container
+    pagerAnchorBuilder: null,   // callback fn for building anchor links:  function(index, DOMelement)
+    pagerEvent:       'click.cycle', // name of event which drives the pager navigation
+    pause:            0,        // true to enable "pause on hover"
+    pauseOnPagerHover: 0,       // true to pause when hovering over pager link
+    prev:             null,     // element, jQuery object, or jQuery selector string for the element to use as event trigger for previous slide
+    prevNextEvent:    'click.cycle',// event which drives the manual transition to the previous or next slide
+    random:           0,        // true for random, false for sequence (not applicable to shuffle fx)
+    randomizeEffects: 1,        // valid when multiple effects are used; true to make the effect sequence random
+    requeueOnImageNotLoaded: true, // requeue the slideshow if any image slides are not yet loaded
+    requeueTimeout:   250,      // ms delay for requeue
+    rev:              0,        // causes animations to transition in reverse (for effects that support it such as scrollHorz/scrollVert/shuffle)
+    shuffle:          null,     // coords for shuffle animation, ex: { top:15, left: 200 }
+    skipInitializationCallbacks: false, // set to true to disable the first before/after callback that occurs prior to any transition
+    slideExpr:        null,     // expression for selecting slides (if something other than all children is required)
+    slideResize:      1,        // force slide width/height to fixed size before every transition
+    speed:            1000,     // speed of the transition (any valid fx speed value)
+    speedIn:          null,     // speed of the 'in' transition
+    speedOut:         null,     // speed of the 'out' transition
+    startingSlide:    undefined,// zero-based index of the first slide to be displayed
+    sync:             1,        // true if in/out transitions should occur simultaneously
+    timeout:          4000,     // milliseconds between slide transitions (0 to disable auto advance)
+    timeoutFn:        null,     // callback for determining per-slide timeout value:  function(currSlideElement, nextSlideElement, options, forwardFlag)
+    updateActivePagerLink: null,// callback fn invoked to update the active pager link (adds/removes activePagerClass style)
+    width:            null      // container width (if the 'fit' option is true, the slides will be set to this width as well)
+};
+
+})(jQuery);
+
+
+/*!
+ * jQuery Cycle Plugin Transition Definitions
+ * This script is a plugin for the jQuery Cycle Plugin
+ * Examples and documentation at: http://malsup.com/jquery/cycle/
+ * Copyright (c) 2007-2010 M. Alsup
+ * Version:	 2.73
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ */
+(function($) {
+"use strict";
+
+//
+// These functions define slide initialization and properties for the named
+// transitions. To save file size feel free to remove any of these that you
+// don't need.
+//
+$.fn.cycle.transitions.none = function($cont, $slides, opts) {
+	opts.fxFn = function(curr,next,opts,after){
+		$(next).show();
+		$(curr).hide();
+		after();
+	};
+};
+
+// not a cross-fade, fadeout only fades out the top slide
+$.fn.cycle.transitions.fadeout = function($cont, $slides, opts) {
+	$slides.not(':eq('+opts.currSlide+')').css({ display: 'block', 'opacity': 1 });
+	opts.before.push(function(curr,next,opts,w,h,rev) {
+		$(curr).css('zIndex',opts.slideCount + (rev !== true ? 1 : 0));
+		$(next).css('zIndex',opts.slideCount + (rev !== true ? 0 : 1));
+	});
+	opts.animIn.opacity = 1;
+	opts.animOut.opacity = 0;
+	opts.cssBefore.opacity = 1;
+	opts.cssBefore.display = 'block';
+	opts.cssAfter.zIndex = 0;
+};
+
+// scrollUp/Down/Left/Right
+$.fn.cycle.transitions.scrollUp = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden');
+	opts.before.push($.fn.cycle.commonReset);
+	var h = $cont.height();
+	opts.cssBefore.top = h;
+	opts.cssBefore.left = 0;
+	opts.cssFirst.top = 0;
+	opts.animIn.top = 0;
+	opts.animOut.top = -h;
+};
+$.fn.cycle.transitions.scrollDown = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden');
+	opts.before.push($.fn.cycle.commonReset);
+	var h = $cont.height();
+	opts.cssFirst.top = 0;
+	opts.cssBefore.top = -h;
+	opts.cssBefore.left = 0;
+	opts.animIn.top = 0;
+	opts.animOut.top = h;
+};
+$.fn.cycle.transitions.scrollLeft = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden');
+	opts.before.push($.fn.cycle.commonReset);
+	var w = $cont.width();
+	opts.cssFirst.left = 0;
+	opts.cssBefore.left = w;
+	opts.cssBefore.top = 0;
+	opts.animIn.left = 0;
+	opts.animOut.left = 0-w;
+};
+$.fn.cycle.transitions.scrollRight = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden');
+	opts.before.push($.fn.cycle.commonReset);
+	var w = $cont.width();
+	opts.cssFirst.left = 0;
+	opts.cssBefore.left = -w;
+	opts.cssBefore.top = 0;
+	opts.animIn.left = 0;
+	opts.animOut.left = w;
+};
+$.fn.cycle.transitions.scrollHorz = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden').width();
+	opts.before.push(function(curr, next, opts, fwd) {
+		if (opts.rev)
+			fwd = !fwd;
+		$.fn.cycle.commonReset(curr,next,opts);
+		opts.cssBefore.left = fwd ? (next.cycleW-1) : (1-next.cycleW);
+		opts.animOut.left = fwd ? -curr.cycleW : curr.cycleW;
+	});
+	opts.cssFirst.left = 0;
+	opts.cssBefore.top = 0;
+	opts.animIn.left = 0;
+	opts.animOut.top = 0;
+};
+$.fn.cycle.transitions.scrollVert = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden');
+	opts.before.push(function(curr, next, opts, fwd) {
+		if (opts.rev)
+			fwd = !fwd;
+		$.fn.cycle.commonReset(curr,next,opts);
+		opts.cssBefore.top = fwd ? (1-next.cycleH) : (next.cycleH-1);
+		opts.animOut.top = fwd ? curr.cycleH : -curr.cycleH;
+	});
+	opts.cssFirst.top = 0;
+	opts.cssBefore.left = 0;
+	opts.animIn.top = 0;
+	opts.animOut.left = 0;
+};
+
+// slideX/slideY
+$.fn.cycle.transitions.slideX = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$(opts.elements).not(curr).hide();
+		$.fn.cycle.commonReset(curr,next,opts,false,true);
+		opts.animIn.width = next.cycleW;
+	});
+	opts.cssBefore.left = 0;
+	opts.cssBefore.top = 0;
+	opts.cssBefore.width = 0;
+	opts.animIn.width = 'show';
+	opts.animOut.width = 0;
+};
+$.fn.cycle.transitions.slideY = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$(opts.elements).not(curr).hide();
+		$.fn.cycle.commonReset(curr,next,opts,true,false);
+		opts.animIn.height = next.cycleH;
+	});
+	opts.cssBefore.left = 0;
+	opts.cssBefore.top = 0;
+	opts.cssBefore.height = 0;
+	opts.animIn.height = 'show';
+	opts.animOut.height = 0;
+};
+
+// shuffle
+$.fn.cycle.transitions.shuffle = function($cont, $slides, opts) {
+	var i, w = $cont.css('overflow', 'visible').width();
+	$slides.css({left: 0, top: 0});
+	opts.before.push(function(curr,next,opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,true,true);
+	});
+	// only adjust speed once!
+	if (!opts.speedAdjusted) {
+		opts.speed = opts.speed / 2; // shuffle has 2 transitions
+		opts.speedAdjusted = true;
+	}
+	opts.random = 0;
+	opts.shuffle = opts.shuffle || {left:-w, top:15};
+	opts.els = [];
+	for (i=0; i < $slides.length; i++)
+		opts.els.push($slides[i]);
+
+	for (i=0; i < opts.currSlide; i++)
+		opts.els.push(opts.els.shift());
+
+	// custom transition fn (hat tip to Benjamin Sterling for this bit of sweetness!)
+	opts.fxFn = function(curr, next, opts, cb, fwd) {
+		if (opts.rev)
+			fwd = !fwd;
+		var $el = fwd ? $(curr) : $(next);
+		$(next).css(opts.cssBefore);
+		var count = opts.slideCount;
+		$el.animate(opts.shuffle, opts.speedIn, opts.easeIn, function() {
+			var hops = $.fn.cycle.hopsFromLast(opts, fwd);
+			for (var k=0; k < hops; k++) {
+				if (fwd)
+					opts.els.push(opts.els.shift());
+				else
+					opts.els.unshift(opts.els.pop());
+			}
+			if (fwd) {
+				for (var i=0, len=opts.els.length; i < len; i++)
+					$(opts.els[i]).css('z-index', len-i+count);
+			}
+			else {
+				var z = $(curr).css('z-index');
+				$el.css('z-index', parseInt(z,10)+1+count);
+			}
+			$el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() {
+				$(fwd ? this : curr).hide();
+				if (cb) cb();
+			});
+		});
+	};
+	$.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
+};
+
+// turnUp/Down/Left/Right
+$.fn.cycle.transitions.turnUp = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,false);
+		opts.cssBefore.top = next.cycleH;
+		opts.animIn.height = next.cycleH;
+		opts.animOut.width = next.cycleW;
+	});
+	opts.cssFirst.top = 0;
+	opts.cssBefore.left = 0;
+	opts.cssBefore.height = 0;
+	opts.animIn.top = 0;
+	opts.animOut.height = 0;
+};
+$.fn.cycle.transitions.turnDown = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,false);
+		opts.animIn.height = next.cycleH;
+		opts.animOut.top   = curr.cycleH;
+	});
+	opts.cssFirst.top = 0;
+	opts.cssBefore.left = 0;
+	opts.cssBefore.top = 0;
+	opts.cssBefore.height = 0;
+	opts.animOut.height = 0;
+};
+$.fn.cycle.transitions.turnLeft = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,true);
+		opts.cssBefore.left = next.cycleW;
+		opts.animIn.width = next.cycleW;
+	});
+	opts.cssBefore.top = 0;
+	opts.cssBefore.width = 0;
+	opts.animIn.left = 0;
+	opts.animOut.width = 0;
+};
+$.fn.cycle.transitions.turnRight = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,true);
+		opts.animIn.width = next.cycleW;
+		opts.animOut.left = curr.cycleW;
+	});
+	$.extend(opts.cssBefore, { top: 0, left: 0, width: 0 });
+	opts.animIn.left = 0;
+	opts.animOut.width = 0;
+};
+
+// zoom
+$.fn.cycle.transitions.zoom = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,false,true);
+		opts.cssBefore.top = next.cycleH/2;
+		opts.cssBefore.left = next.cycleW/2;
+		$.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
+		$.extend(opts.animOut, { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 });
+	});
+	opts.cssFirst.top = 0;
+	opts.cssFirst.left = 0;
+	opts.cssBefore.width = 0;
+	opts.cssBefore.height = 0;
+};
+
+// fadeZoom
+$.fn.cycle.transitions.fadeZoom = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,false);
+		opts.cssBefore.left = next.cycleW/2;
+		opts.cssBefore.top = next.cycleH/2;
+		$.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
+	});
+	opts.cssBefore.width = 0;
+	opts.cssBefore.height = 0;
+	opts.animOut.opacity = 0;
+};
+
+// blindX
+$.fn.cycle.transitions.blindX = function($cont, $slides, opts) {
+	var w = $cont.css('overflow','hidden').width();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts);
+		opts.animIn.width = next.cycleW;
+		opts.animOut.left   = curr.cycleW;
+	});
+	opts.cssBefore.left = w;
+	opts.cssBefore.top = 0;
+	opts.animIn.left = 0;
+	opts.animOut.left = w;
+};
+// blindY
+$.fn.cycle.transitions.blindY = function($cont, $slides, opts) {
+	var h = $cont.css('overflow','hidden').height();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts);
+		opts.animIn.height = next.cycleH;
+		opts.animOut.top   = curr.cycleH;
+	});
+	opts.cssBefore.top = h;
+	opts.cssBefore.left = 0;
+	opts.animIn.top = 0;
+	opts.animOut.top = h;
+};
+// blindZ
+$.fn.cycle.transitions.blindZ = function($cont, $slides, opts) {
+	var h = $cont.css('overflow','hidden').height();
+	var w = $cont.width();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts);
+		opts.animIn.height = next.cycleH;
+		opts.animOut.top   = curr.cycleH;
+	});
+	opts.cssBefore.top = h;
+	opts.cssBefore.left = w;
+	opts.animIn.top = 0;
+	opts.animIn.left = 0;
+	opts.animOut.top = h;
+	opts.animOut.left = w;
+};
+
+// growX - grow horizontally from centered 0 width
+$.fn.cycle.transitions.growX = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,true);
+		opts.cssBefore.left = this.cycleW/2;
+		opts.animIn.left = 0;
+		opts.animIn.width = this.cycleW;
+		opts.animOut.left = 0;
+	});
+	opts.cssBefore.top = 0;
+	opts.cssBefore.width = 0;
+};
+// growY - grow vertically from centered 0 height
+$.fn.cycle.transitions.growY = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,false);
+		opts.cssBefore.top = this.cycleH/2;
+		opts.animIn.top = 0;
+		opts.animIn.height = this.cycleH;
+		opts.animOut.top = 0;
+	});
+	opts.cssBefore.height = 0;
+	opts.cssBefore.left = 0;
+};
+
+// curtainX - squeeze in both edges horizontally
+$.fn.cycle.transitions.curtainX = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,true,true);
+		opts.cssBefore.left = next.cycleW/2;
+		opts.animIn.left = 0;
+		opts.animIn.width = this.cycleW;
+		opts.animOut.left = curr.cycleW/2;
+		opts.animOut.width = 0;
+	});
+	opts.cssBefore.top = 0;
+	opts.cssBefore.width = 0;
+};
+// curtainY - squeeze in both edges vertically
+$.fn.cycle.transitions.curtainY = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,false,true);
+		opts.cssBefore.top = next.cycleH/2;
+		opts.animIn.top = 0;
+		opts.animIn.height = next.cycleH;
+		opts.animOut.top = curr.cycleH/2;
+		opts.animOut.height = 0;
+	});
+	opts.cssBefore.height = 0;
+	opts.cssBefore.left = 0;
+};
+
+// cover - curr slide covered by next slide
+$.fn.cycle.transitions.cover = function($cont, $slides, opts) {
+	var d = opts.direction || 'left';
+	var w = $cont.css('overflow','hidden').width();
+	var h = $cont.height();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts);
+		opts.cssAfter.display = '';
+		if (d == 'right')
+			opts.cssBefore.left = -w;
+		else if (d == 'up')
+			opts.cssBefore.top = h;
+		else if (d == 'down')
+			opts.cssBefore.top = -h;
+		else
+			opts.cssBefore.left = w;
+	});
+	opts.animIn.left = 0;
+	opts.animIn.top = 0;
+	opts.cssBefore.top = 0;
+	opts.cssBefore.left = 0;
+};
+
+// uncover - curr slide moves off next slide
+$.fn.cycle.transitions.uncover = function($cont, $slides, opts) {
+	var d = opts.direction || 'left';
+	var w = $cont.css('overflow','hidden').width();
+	var h = $cont.height();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,true,true);
+		if (d == 'right')
+			opts.animOut.left = w;
+		else if (d == 'up')
+			opts.animOut.top = -h;
+		else if (d == 'down')
+			opts.animOut.top = h;
+		else
+			opts.animOut.left = -w;
+	});
+	opts.animIn.left = 0;
+	opts.animIn.top = 0;
+	opts.cssBefore.top = 0;
+	opts.cssBefore.left = 0;
+};
+
+// toss - move top slide and fade away
+$.fn.cycle.transitions.toss = function($cont, $slides, opts) {
+	var w = $cont.css('overflow','visible').width();
+	var h = $cont.height();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,true,true);
+		// provide default toss settings if animOut not provided
+		if (!opts.animOut.left && !opts.animOut.top)
+			$.extend(opts.animOut, { left: w*2, top: -h/2, opacity: 0 });
+		else
+			opts.animOut.opacity = 0;
+	});
+	opts.cssBefore.left = 0;
+	opts.cssBefore.top = 0;
+	opts.animIn.left = 0;
+};
+
+// wipe - clip animation
+$.fn.cycle.transitions.wipe = function($cont, $slides, opts) {
+	var w = $cont.css('overflow','hidden').width();
+	var h = $cont.height();
+	opts.cssBefore = opts.cssBefore || {};
+	var clip;
+	if (opts.clip) {
+		if (/l2r/.test(opts.clip))
+			clip = 'rect(0px 0px '+h+'px 0px)';
+		else if (/r2l/.test(opts.clip))
+			clip = 'rect(0px '+w+'px '+h+'px '+w+'px)';
+		else if (/t2b/.test(opts.clip))
+			clip = 'rect(0px '+w+'px 0px 0px)';
+		else if (/b2t/.test(opts.clip))
+			clip = 'rect('+h+'px '+w+'px '+h+'px 0px)';
+		else if (/zoom/.test(opts.clip)) {
+			var top = parseInt(h/2,10);
+			var left = parseInt(w/2,10);
+			clip = 'rect('+top+'px '+left+'px '+top+'px '+left+'px)';
+		}
+	}
+
+	opts.cssBefore.clip = opts.cssBefore.clip || clip || 'rect(0px 0px 0px 0px)';
+
+	var d = opts.cssBefore.clip.match(/(\d+)/g);
+	var t = parseInt(d[0],10), r = parseInt(d[1],10), b = parseInt(d[2],10), l = parseInt(d[3],10);
+
+	opts.before.push(function(curr, next, opts) {
+		if (curr == next) return;
+		var $curr = $(curr), $next = $(next);
+		$.fn.cycle.commonReset(curr,next,opts,true,true,false);
+		opts.cssAfter.display = 'block';
+
+		var step = 1, count = parseInt((opts.speedIn / 13),10) - 1;
+		(function f() {
+			var tt = t ? t - parseInt(step * (t/count),10) : 0;
+			var ll = l ? l - parseInt(step * (l/count),10) : 0;
+			var bb = b < h ? b + parseInt(step * ((h-b)/count || 1),10) : h;
+			var rr = r < w ? r + parseInt(step * ((w-r)/count || 1),10) : w;
+			$next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' });
+			(step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none');
+		})();
+	});
+	$.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
+	opts.animIn	   = { left: 0 };
+	opts.animOut   = { left: 0 };
+};
+
+})(jQuery);
diff --git a/themes/greydragon/js/jquery.form.custom.js b/themes/greydragon/js/jquery.form.custom.js
new file mode 100644
index 0000000..796db12
--- /dev/null
+++ b/themes/greydragon/js/jquery.form.custom.js
@@ -0,0 +1,1076 @@
+/*!
+ * jQuery Form Plugin
+ * version: 3.09 (16-APR-2012)
+ * @requires jQuery v1.3.2 or later
+ *
+ * Examples and documentation at: http://malsup.com/jquery/form/
+ * Project repository: https://github.com/malsup/form
+ * Dual licensed under the MIT and GPL licenses:
+ *    http://malsup.github.com/mit-license.txt
+ *    http://malsup.github.com/gpl-license-v2.txt
+ */
+/*global ActiveXObject alert */
+;(function($) {
+"use strict";
+
+/*
+    Usage Note:
+    -----------
+    Do not use both ajaxSubmit and ajaxForm on the same form.  These
+    functions are mutually exclusive.  Use ajaxSubmit if you want
+    to bind your own submit handler to the form.  For example,
+
+    $(document).ready(function() {
+        $('#myForm').on('submit', function(e) {
+            e.preventDefault(); // <-- important
+            $(this).ajaxSubmit({
+                target: '#output'
+            });
+        });
+    });
+
+    Use ajaxForm when you want the plugin to manage all the event binding
+    for you.  For example,
+
+    $(document).ready(function() {
+        $('#myForm').ajaxForm({
+            target: '#output'
+        });
+    });
+    
+    You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
+    form does not have to exist when you invoke ajaxForm:
+
+    $('#myForm').ajaxForm({
+        delegation: true,
+        target: '#output'
+    });
+    
+    When using ajaxForm, the ajaxSubmit function will be invoked for you
+    at the appropriate time.
+*/
+
+/**
+ * Feature detection
+ */
+var feature = {};
+feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
+feature.formdata = window.FormData !== undefined;
+
+/**
+ * ajaxSubmit() provides a mechanism for immediately submitting
+ * an HTML form using AJAX.
+ */
+$.fn.ajaxSubmit = function(options) {
+    /*jshint scripturl:true */
+
+    // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
+    if (!this.length) {
+        log('ajaxSubmit: skipping submit process - no element selected');
+        return this;
+    }
+    
+    var method, action, url, $form = this;
+
+    if (typeof options == 'function') {
+        options = { success: options };
+    }
+
+    method = this.attr('method');
+    action = this.attr('action');
+    url = (typeof action === 'string') ? $.trim(action) : '';
+    url = url || window.location.href || '';
+    if (url) {
+        // clean url (don't include hash vaue)
+        url = (url.match(/^([^#]+)/)||[])[1];
+    }
+
+    options = $.extend(true, {
+        url:  url,
+        success: $.ajaxSettings.success,
+        type: method || 'GET',
+        iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
+    }, options);
+
+    // hook for manipulating the form data before it is extracted;
+    // convenient for use with rich editors like tinyMCE or FCKEditor
+    var veto = {};
+    this.trigger('form-pre-serialize', [this, options, veto]);
+    if (veto.veto) {
+        log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
+        return this;
+    }
+
+    // provide opportunity to alter form data before it is serialized
+    if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
+        log('ajaxSubmit: submit aborted via beforeSerialize callback');
+        return this;
+    }
+
+    var traditional = options.traditional;
+    if ( traditional === undefined ) {
+        traditional = $.ajaxSettings.traditional;
+    }
+    
+    var elements = [];
+    var qx, a = this.formToArray(options.semantic, elements);
+    if (options.data) {
+        options.extraData = options.data;
+        qx = $.param(options.data, traditional);
+    }
+
+    // give pre-submit callback an opportunity to abort the submit
+    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
+        log('ajaxSubmit: submit aborted via beforeSubmit callback');
+        return this;
+    }
+
+    // fire vetoable 'validate' event
+    this.trigger('form-submit-validate', [a, this, options, veto]);
+    if (veto.veto) {
+        log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
+        return this;
+    }
+
+    var q = $.param(a, traditional);
+    if (qx) {
+        q = ( q ? (q + '&' + qx) : qx );
+    }    
+    if (options.type.toUpperCase() == 'GET') {
+        options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
+        options.data = null;  // data is null for 'get'
+    }
+    else {
+        options.data = q; // data is the query string for 'post'
+    }
+
+    var callbacks = [];
+    if (options.resetForm) {
+        callbacks.push(function() { $form.resetForm(); });
+    }
+    if (options.clearForm) {
+        callbacks.push(function() { $form.clearForm(options.includeHidden); });
+    }
+
+    // perform a load on the target only if dataType is not provided
+    if (!options.dataType && options.target) {
+        var oldSuccess = options.success || function(){};
+        callbacks.push(function(data) {
+            var fn = options.replaceTarget ? 'replaceWith' : 'html';
+            $(options.target)[fn](data).each(oldSuccess, arguments);
+        });
+    }
+    else if (options.success) {
+        callbacks.push(options.success);
+    }
+
+    options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
+        var context = options.context || options;    // jQuery 1.4+ supports scope context 
+        for (var i=0, max=callbacks.length; i < max; i++) {
+            callbacks[i].apply(context, [data, status, xhr || $form, $form]);
+        }
+    };
+
+    // are there files to upload?
+    var fileInputs = $('input:file:enabled[value]', this); // [value] (issue #113)
+    var hasFileInputs = fileInputs.length > 0;
+    var mp = 'multipart/form-data';
+    var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
+
+    var fileAPI = feature.fileapi && feature.formdata;
+    log("fileAPI :" + fileAPI);
+    var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
+
+    // options.iframe allows user to force iframe mode
+    // 06-NOV-09: now defaulting to iframe mode if file input is detected
+    if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
+        // hack to fix Safari hang (thanks to Tim Molendijk for this)
+        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
+        if (options.closeKeepAlive) {
+            $.get(options.closeKeepAlive, function() {
+                fileUploadIframe(a);
+            });
+        }
+          else {
+            fileUploadIframe(a);
+          }
+    }
+    else if ((hasFileInputs || multipart) && fileAPI) {
+        fileUploadXhr(a);
+    }
+    else {
+        $.ajax(options);
+    }
+
+    // clear element array
+    for (var k=0; k < elements.length; k++)
+        elements[k] = null;
+
+    // fire 'notify' event
+    this.trigger('form-submit-notify', [this, options]);
+    return this;
+
+     // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
+    function fileUploadXhr(a) {
+        var formdata = new FormData();
+
+        for (var i=0; i < a.length; i++) {
+            formdata.append(a[i].name, a[i].value);
+        }
+
+        if (options.extraData) {
+            for (var p in options.extraData)
+                if (options.extraData.hasOwnProperty(p))
+                    formdata.append(p, options.extraData[p]);
+        }
+
+        options.data = null;
+
+        var s = $.extend(true, {}, $.ajaxSettings, options, {
+            contentType: false,
+            processData: false,
+            cache: false,
+            type: 'POST'
+        });
+        
+        if (options.uploadProgress) {
+            // workaround because jqXHR does not expose upload property
+            s.xhr = function() {
+                var xhr = jQuery.ajaxSettings.xhr();
+                if (xhr.upload) {
+                    xhr.upload.onprogress = function(event) {
+                        var percent = 0;
+                        var position = event.loaded || event.position; /*event.position is deprecated*/
+                        var total = event.total;
+                        if (event.lengthComputable) {
+                            percent = Math.ceil(position / total * 100);
+                        }
+                        options.uploadProgress(event, position, total, percent);
+                    };
+                }
+                return xhr;
+            };
+        }
+
+        s.data = null;
+          var beforeSend = s.beforeSend;
+          s.beforeSend = function(xhr, o) {
+              o.data = formdata;
+            if(beforeSend)
+                beforeSend.call(o, xhr, options);
+        };
+        $.ajax(s);
+    }
+
+    // private function for handling file uploads (hat tip to YAHOO!)
+    function fileUploadIframe(a) {
+        var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
+        var useProp = !!$.fn.prop;
+
+        if ($(':input[name=submit],:input[id=submit]', form).length) {
+            // if there is an input with a name or id of 'submit' then we won't be
+            // able to invoke the submit fn on the form (at least not x-browser)
+            alert('Error: Form elements must not have name or id of "submit".');
+            return;
+        }
+        
+        if (a) {
+            // ensure that every serialized input is still enabled
+            for (i=0; i < elements.length; i++) {
+                el = $(elements[i]);
+                if ( useProp )
+                    el.prop('disabled', false);
+                else
+                    el.removeAttr('disabled');
+            }
+        }
+
+        s = $.extend(true, {}, $.ajaxSettings, options);
+        s.context = s.context || s;
+        id = 'jqFormIO' + (new Date().getTime());
+        if (s.iframeTarget) {
+            $io = $(s.iframeTarget);
+            n = $io.attr('name');
+            if (!n)
+                 $io.attr('name', id);
+            else
+                id = n;
+        }
+        else {
+            $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
+            $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
+        }
+        io = $io[0];
+
+
+        xhr = { // mock object
+            aborted: 0,
+            responseText: null,
+            responseXML: null,
+            status: 0,
+            statusText: 'n/a',
+            getAllResponseHeaders: function() {},
+            getResponseHeader: function() {},
+            setRequestHeader: function() {},
+            abort: function(status) {
+                var e = (status === 'timeout' ? 'timeout' : 'aborted');
+                log('aborting upload... ' + e);
+                this.aborted = 1;
+                $io.attr('src', s.iframeSrc); // abort op in progress
+                xhr.error = e;
+                if (s.error)
+                    s.error.call(s.context, xhr, e, status);
+                if (g)
+                    $.event.trigger("ajaxError", [xhr, s, e]);
+                if (s.complete)
+                    s.complete.call(s.context, xhr, e);
+            }
+        };
+
+        g = s.global;
+        // trigger ajax global events so that activity/block indicators work like normal
+        if (g && 0 === $.active++) {
+            $.event.trigger("ajaxStart");
+        }
+        if (g) {
+            $.event.trigger("ajaxSend", [xhr, s]);
+        }
+
+        if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
+            if (s.global) {
+                $.active--;
+            }
+            return;
+        }
+        if (xhr.aborted) {
+            return;
+        }
+
+        // add submitting element to data if we know it
+        sub = form.clk;
+        if (sub) {
+            n = sub.name;
+            if (n && !sub.disabled) {
+                s.extraData = s.extraData || {};
+                s.extraData[n] = sub.value;
+                if (sub.type == "image") {
+                    s.extraData[n+'.x'] = form.clk_x;
+                    s.extraData[n+'.y'] = form.clk_y;
+                }
+            }
+        }
+        
+        var CLIENT_TIMEOUT_ABORT = 1;
+        var SERVER_ABORT = 2;
+
+        function getDoc(frame) {
+            var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
+            return doc;
+        }
+        
+        // Rails CSRF hack (thanks to Yvan Barthelemy)
+        var csrf_token = $('meta[name=csrf-token]').attr('content');
+        var csrf_param = $('meta[name=csrf-param]').attr('content');
+        if (csrf_param && csrf_token) {
+            s.extraData = s.extraData || {};
+            s.extraData[csrf_param] = csrf_token;
+        }
+
+        // take a breath so that pending repaints get some cpu time before the upload starts
+        function doSubmit() {
+            // make sure form attrs are set
+            var t = $form.attr('target'), a = $form.attr('action');
+
+            // update form attrs in IE friendly way
+            form.setAttribute('target',id);
+            if (!method) {
+                form.setAttribute('method', 'POST');
+            }
+            if (a != s.url) {
+                form.setAttribute('action', s.url);
+            }
+
+            // ie borks in some cases when setting encoding
+            if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
+                $form.attr({
+                    encoding: 'multipart/form-data',
+                    enctype:  'multipart/form-data'
+                });
+            }
+
+            // support timout
+            if (s.timeout) {
+                timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
+            }
+            
+            // look for server aborts
+            function checkState() {
+                try {
+                    var state = getDoc(io).readyState;
+                    log('state = ' + state);
+                    if (state && state.toLowerCase() == 'uninitialized')
+                        setTimeout(checkState,50);
+                }
+                catch(e) {
+                    log('Server abort: ' , e, ' (', e.name, ')');
+                    cb(SERVER_ABORT);
+                    if (timeoutHandle)
+                        clearTimeout(timeoutHandle);
+                    timeoutHandle = undefined;
+                }
+            }
+
+            // add "extra" data to form if provided in options
+            var extraInputs = [];
+            try {
+                if (s.extraData) {
+                    for (var n in s.extraData) {
+                        if (s.extraData.hasOwnProperty(n)) {
+                            extraInputs.push(
+                                $('<input type="hidden" name="'+n+'">').attr('value',s.extraData[n])
+                                    .appendTo(form)[0]);
+                        }
+                    }
+                }
+
+                if (!s.iframeTarget) {
+                    // add iframe to doc and submit the form
+                    $io.appendTo('body');
+                    if (io.attachEvent)
+                        io.attachEvent('onload', cb);
+                    else
+                        io.addEventListener('load', cb, false);
+                }
+                setTimeout(checkState,15);
+                form.submit();
+            }
+            finally {
+                // reset attrs and remove "extra" input elements
+                form.setAttribute('action',a);
+                if(t) {
+                    form.setAttribute('target', t);
+                } else {
+                    $form.removeAttr('target');
+                }
+                $(extraInputs).remove();
+            }
+        }
+
+        if (s.forceSync) {
+            doSubmit();
+        }
+        else {
+            setTimeout(doSubmit, 10); // this lets dom updates render
+        }
+
+        var data, doc, domCheckCount = 50, callbackProcessed;
+
+        function cb(e) {
+            if (xhr.aborted || callbackProcessed) {
+                return;
+            }
+            try {
+                doc = getDoc(io);
+            }
+            catch(ex) {
+                log('cannot access response document: ', ex);
+                e = SERVER_ABORT;
+            }
+            if (e === CLIENT_TIMEOUT_ABORT && xhr) {
+                xhr.abort('timeout');
+                return;
+            }
+            else if (e == SERVER_ABORT && xhr) {
+                xhr.abort('server abort');
+                return;
+            }
+
+            if (!doc || doc.location.href == s.iframeSrc) {
+                // response not received yet
+                if (!timedOut)
+                    return;
+            }
+            if (io.detachEvent)
+                io.detachEvent('onload', cb);
+            else    
+                io.removeEventListener('load', cb, false);
+
+            var status = 'success', errMsg;
+            try {
+                if (timedOut) {
+                    throw 'timeout';
+                }
+
+                var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
+                log('isXml='+isXml);
+                if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
+                    if (--domCheckCount) {
+                        // in some browsers (Opera) the iframe DOM is not always traversable when
+                        // the onload callback fires, so we loop a bit to accommodate
+                        log('requeing onLoad callback, DOM not available');
+                        setTimeout(cb, 250);
+                        return;
+                    }
+                    // let this fall through because server response could be an empty document
+                    //log('Could not access iframe DOM after mutiple tries.');
+                    //throw 'DOMException: not available';
+                }
+
+                //log('response detected');
+                var docRoot = doc.body ? doc.body : doc.documentElement;
+                xhr.responseText = docRoot ? docRoot.innerHTML : null;
+                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
+                if (isXml)
+                    s.dataType = 'xml';
+                xhr.getResponseHeader = function(header){
+                    var headers = {'content-type': s.dataType};
+                    return headers[header];
+                };
+                // support for XHR 'status' & 'statusText' emulation :
+                if (docRoot) {
+                    xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
+                    xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
+                }
+
+                var dt = (s.dataType || '').toLowerCase();
+                var scr = /(json|script|text)/.test(dt);
+                if (scr || s.textarea) {
+                    // see if user embedded response in textarea
+                    var ta = doc.getElementsByTagName('textarea')[0];
+                    if (ta) {
+                        xhr.responseText = ta.value;
+                        // support for XHR 'status' & 'statusText' emulation :
+                        xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
+                        xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
+                    }
+                    else if (scr) {
+                        // account for browsers injecting pre around json response
+                        var pre = doc.getElementsByTagName('pre')[0];
+                        var b = doc.getElementsByTagName('body')[0];
+                        if (pre) {
+                            xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
+                        }
+                        else if (b) {
+                            xhr.responseText = b.textContent ? b.textContent : b.innerText;
+                        }
+                    }
+                }
+                else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
+                    xhr.responseXML = toXml(xhr.responseText);
+                }
+
+                try {
+                    data = httpData(xhr, dt, s);
+                }
+                catch (e) {
+                    status = 'parsererror';
+                    xhr.error = errMsg = (e || status);
+                }
+            }
+            catch (e) {
+                log('error caught: ',e);
+                status = 'error';
+                xhr.error = errMsg = (e || status);
+            }
+
+            if (xhr.aborted) {
+                log('upload aborted');
+                status = null;
+            }
+
+            if (xhr.status) { // we've set xhr.status
+                status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
+            }
+
+            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
+            if (status === 'success') {
+                if (s.success)
+                    s.success.call(s.context, data, 'success', xhr);
+                if (g)
+                    $.event.trigger("ajaxSuccess", [xhr, s]);
+            }
+            else if (status) {
+                if (errMsg === undefined)
+                    errMsg = xhr.statusText;
+                if (s.error)
+                    s.error.call(s.context, xhr, status, errMsg);
+                if (g)
+                    $.event.trigger("ajaxError", [xhr, s, errMsg]);
+            }
+
+            if (g)
+                $.event.trigger("ajaxComplete", [xhr, s]);
+
+            if (g && ! --$.active) {
+                $.event.trigger("ajaxStop");
+            }
+
+            if (s.complete)
+                s.complete.call(s.context, xhr, status);
+
+            callbackProcessed = true;
+            if (s.timeout)
+                clearTimeout(timeoutHandle);
+
+            // clean up
+            setTimeout(function() {
+                if (!s.iframeTarget)
+                    $io.remove();
+                xhr.responseXML = null;
+            }, 100);
+        }
+
+        var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
+            if (window.ActiveXObject) {
+                doc = new ActiveXObject('Microsoft.XMLDOM');
+                doc.async = 'false';
+                doc.loadXML(s);
+            }
+            else {
+                doc = (new DOMParser()).parseFromString(s, 'text/xml');
+            }
+            return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
+        };
+        var parseJSON = $.parseJSON || function(s) {
+            /*jslint evil:true */
+            return window['eval']('(' + s + ')');
+        };
+
+        var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
+
+            var ct = xhr.getResponseHeader('content-type') || '',
+                xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
+                data = xml ? xhr.responseXML : xhr.responseText;
+
+            if (xml && data.documentElement.nodeName === 'parsererror') {
+                if ($.error)
+                    $.error('parsererror');
+            }
+            if (s && s.dataFilter) {
+                data = s.dataFilter(data, type);
+            }
+            if (typeof data === 'string') {
+                if (type === 'json' || !type && ct.indexOf('json') >= 0) {
+                    data = parseJSON(data);
+                } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
+                    $.globalEval(data);
+                }
+            }
+            return data;
+        };
+    }
+};
+
+/**
+ * ajaxForm() provides a mechanism for fully automating form submission.
+ *
+ * The advantages of using this method instead of ajaxSubmit() are:
+ *
+ * 1: This method will include coordinates for <input type="image" /> elements (if the element
+ *    is used to submit the form).
+ * 2. This method will include the submit element's name/value data (for the element that was
+ *    used to submit the form).
+ * 3. This method binds the submit() method to the form for you.
+ *
+ * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
+ * passes the options argument along after properly binding events for submit elements and
+ * the form itself.
+ */
+$.fn.ajaxForm = function(options) {
+    options = options || {};
+    options.delegation = options.delegation && $.isFunction($.fn.on);
+    
+    // in jQuery 1.3+ we can fix mistakes with the ready state
+    if (!options.delegation && this.length === 0) {
+        var o = { s: this.selector, c: this.context };
+        if (!$.isReady && o.s) {
+            log('DOM not ready, queuing ajaxForm');
+            $(function() {
+                $(o.s,o.c).ajaxForm(options);
+            });
+            return this;
+        }
+        // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
+        log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
+        return this;
+    }
+
+    if ( options.delegation ) {
+        $(document)
+            .off('submit.form-plugin', this.selector, doAjaxSubmit)
+            .off('click.form-plugin', this.selector, captureSubmittingElement)
+            .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
+            .on('click.form-plugin', this.selector, options, captureSubmittingElement);
+        return this;
+    }
+
+    return this.ajaxFormUnbind()
+        .bind('submit.form-plugin', options, doAjaxSubmit)
+        .bind('click.form-plugin', options, captureSubmittingElement);
+};
+
+// private event handlers    
+function doAjaxSubmit(e) {
+    /*jshint validthis:true */
+    var options = e.data;
+    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
+        e.preventDefault();
+        $(this).ajaxSubmit(options);
+    }
+}
+    
+function captureSubmittingElement(e) {
+    /*jshint validthis:true */
+    var target = e.target;
+    var $el = $(target);
+    if (!($el.is(":submit,input:image"))) {
+        // is this a child element of the submit el?  (ex: a span within a button)
+        var t = $el.closest(':submit');
+        if (t.length === 0) {
+            return;
+        }
+        target = t[0];
+    }
+    var form = this;
+    form.clk = target;
+    if (target.type == 'image') {
+        if (e.offsetX !== undefined) {
+            form.clk_x = e.offsetX;
+            form.clk_y = e.offsetY;
+        } else if (typeof $.fn.offset == 'function') {
+            var offset = $el.offset();
+            form.clk_x = e.pageX - offset.left;
+            form.clk_y = e.pageY - offset.top;
+        } else {
+            form.clk_x = e.pageX - target.offsetLeft;
+            form.clk_y = e.pageY - target.offsetTop;
+        }
+    }
+    // clear form vars
+    setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
+}
+
+
+// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
+$.fn.ajaxFormUnbind = function() {
+    return this.unbind('submit.form-plugin click.form-plugin');
+};
+
+/**
+ * formToArray() gathers form element data into an array of objects that can
+ * be passed to any of the following ajax functions: $.get, $.post, or load.
+ * Each object in the array has both a 'name' and 'value' property.  An example of
+ * an array for a simple login form might be:
+ *
+ * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
+ *
+ * It is this array that is passed to pre-submit callback functions provided to the
+ * ajaxSubmit() and ajaxForm() methods.
+ */
+$.fn.formToArray = function(semantic, elements) {
+    var a = [];
+    if (this.length === 0) {
+        return a;
+    }
+
+    var form = this[0];
+    var els = semantic ? form.getElementsByTagName('*') : form.elements;
+    if (!els) {
+        return a;
+    }
+
+    var i,j,n,v,el,max,jmax;
+    for(i=0, max=els.length; i < max; i++) {
+        el = els[i];
+        n = el.name;
+        if (!n) {
+            continue;
+        }
+
+        if (semantic && form.clk && el.type == "image") {
+            // handle image inputs on the fly when semantic == true
+            if(!el.disabled && form.clk == el) {
+                a.push({name: n, value: $(el).val(), type: el.type });
+                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+            }
+            continue;
+        }
+
+        v = $.fieldValue(el, true);
+        if (v && v.constructor == Array) {
+            if (elements) 
+                elements.push(el);
+            for(j=0, jmax=v.length; j < jmax; j++) {
+                a.push({name: n, value: v[j]});
+            }
+        }
+        else if (feature.fileapi && el.type == 'file' && !el.disabled) {
+            if (elements) 
+                elements.push(el);
+            var files = el.files;
+            if (files.length) {
+                for (j=0; j < files.length; j++) {
+                    a.push({name: n, value: files[j], type: el.type});
+                }
+            }
+            else {
+                // #180
+                a.push({ name: n, value: '', type: el.type });
+            }
+        }
+        else if (v !== null && typeof v != 'undefined') {
+            if (elements) 
+                elements.push(el);
+            a.push({name: n, value: v, type: el.type, required: el.required});
+        }
+    }
+
+    if (!semantic && form.clk) {
+        // input type=='image' are not found in elements array! handle it here
+        var $input = $(form.clk), input = $input[0];
+        n = input.name;
+        if (n && !input.disabled && input.type == 'image') {
+            a.push({name: n, value: $input.val()});
+            a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+        }
+    }
+    return a;
+};
+
+/**
+ * Serializes form data into a 'submittable' string. This method will return a string
+ * in the format: name1=value1&amp;name2=value2
+ */
+$.fn.formSerialize = function(semantic) {
+    //hand off to jQuery.param for proper encoding
+    return $.param(this.formToArray(semantic));
+};
+
+/**
+ * Serializes all field elements in the jQuery object into a query string.
+ * This method will return a string in the format: name1=value1&amp;name2=value2
+ */
+$.fn.fieldSerialize = function(successful) {
+    var a = [];
+    this.each(function() {
+        var n = this.name;
+        if (!n) {
+            return;
+        }
+        var v = $.fieldValue(this, successful);
+        if (v && v.constructor == Array) {
+            for (var i=0,max=v.length; i < max; i++) {
+                a.push({name: n, value: v[i]});
+            }
+        }
+        else if (v !== null && typeof v != 'undefined') {
+            a.push({name: this.name, value: v});
+        }
+    });
+    //hand off to jQuery.param for proper encoding
+    return $.param(a);
+};
+
+/**
+ * Returns the value(s) of the element in the matched set.  For example, consider the following form:
+ *
+ *  <form><fieldset>
+ *      <input name="A" type="text" />
+ *      <input name="A" type="text" />
+ *      <input name="B" type="checkbox" value="B1" />
+ *      <input name="B" type="checkbox" value="B2"/>
+ *      <input name="C" type="radio" value="C1" />
+ *      <input name="C" type="radio" value="C2" />
+ *  </fieldset></form>
+ *
+ *  var v = $(':text').fieldValue();
+ *  // if no values are entered into the text inputs
+ *  v == ['','']
+ *  // if values entered into the text inputs are 'foo' and 'bar'
+ *  v == ['foo','bar']
+ *
+ *  var v = $(':checkbox').fieldValue();
+ *  // if neither checkbox is checked
+ *  v === undefined
+ *  // if both checkboxes are checked
+ *  v == ['B1', 'B2']
+ *
+ *  var v = $(':radio').fieldValue();
+ *  // if neither radio is checked
+ *  v === undefined
+ *  // if first radio is checked
+ *  v == ['C1']
+ *
+ * The successful argument controls whether or not the field element must be 'successful'
+ * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
+ * The default value of the successful argument is true.  If this value is false the value(s)
+ * for each element is returned.
+ *
+ * Note: This method *always* returns an array.  If no valid value can be determined the
+ *    array will be empty, otherwise it will contain one or more values.
+ */
+$.fn.fieldValue = function(successful) {
+    for (var val=[], i=0, max=this.length; i < max; i++) {
+        var el = this[i];
+        var v = $.fieldValue(el, successful);
+        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
+            continue;
+        }
+        if (v.constructor == Array)
+            $.merge(val, v);
+        else
+            val.push(v);
+    }
+    return val;
+};
+
+/**
+ * Returns the value of the field element.
+ */
+$.fieldValue = function(el, successful) {
+    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
+    if (successful === undefined) {
+        successful = true;
+    }
+
+    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
+        (t == 'checkbox' || t == 'radio') && !el.checked ||
+        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
+        tag == 'select' && el.selectedIndex == -1)) {
+            return null;
+    }
+
+    if (tag == 'select') {
+        var index = el.selectedIndex;
+        if (index < 0) {
+            return null;
+        }
+        var a = [], ops = el.options;
+        var one = (t == 'select-one');
+        var max = (one ? index+1 : ops.length);
+        for(var i=(one ? index : 0); i < max; i++) {
+            var op = ops[i];
+            if (op.selected) {
+                var v = op.value;
+                if (!v) { // extra pain for IE...
+                    v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
+                }
+                if (one) {
+                    return v;
+                }
+                a.push(v);
+            }
+        }
+        return a;
+    }
+    return $(el).val();
+};
+
+/**
+ * Clears the form data.  Takes the following actions on the form's input fields:
+ *  - input text fields will have their 'value' property set to the empty string
+ *  - select elements will have their 'selectedIndex' property set to -1
+ *  - checkbox and radio inputs will have their 'checked' property set to false
+ *  - inputs of type submit, button, reset, and hidden will *not* be effected
+ *  - button elements will *not* be effected
+ */
+$.fn.clearForm = function(includeHidden) {
+    return this.each(function() {
+        $('input,select,textarea', this).clearFields(includeHidden);
+    });
+};
+
+/**
+ * Clears the selected form elements.
+ */
+$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
+    var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
+    return this.each(function() {
+        var t = this.type, tag = this.tagName.toLowerCase();
+        if (re.test(t) || tag == 'textarea') {
+            this.value = '';
+        }
+        else if (t == 'checkbox' || t == 'radio') {
+            this.checked = false;
+        }
+        else if (tag == 'select') {
+            this.selectedIndex = -1;
+        }
+        else if (includeHidden) {
+            // includeHidden can be the valud true, or it can be a selector string
+            // indicating a special test; for example:
+            //  $('#myForm').clearForm('.special:hidden')
+            // the above would clean hidden inputs that have the class of 'special'
+            if ( (includeHidden === true && /hidden/.test(t)) ||
+                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) )
+                this.value = '';
+        }
+    });
+};
+
+/**
+ * Resets the form data.  Causes all form elements to be reset to their original value.
+ */
+$.fn.resetForm = function() {
+    return this.each(function() {
+        // guard against an input with the name of 'reset'
+        // note that IE reports the reset function as an 'object'
+        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
+            this.reset();
+        }
+    });
+};
+
+/**
+ * Enables or disables any matching elements.
+ */
+$.fn.enable = function(b) {
+    if (b === undefined) {
+        b = true;
+    }
+    return this.each(function() {
+        this.disabled = !b;
+    });
+};
+
+/**
+ * Checks/unchecks any matching checkboxes or radio buttons and
+ * selects/deselects and matching option elements.
+ */
+$.fn.selected = function(select) {
+    if (select === undefined) {
+        select = true;
+    }
+    return this.each(function() {
+        var t = this.type;
+        if (t == 'checkbox' || t == 'radio') {
+            this.checked = select;
+        }
+        else if (this.tagName.toLowerCase() == 'option') {
+            var $sel = $(this).parent('select');
+            if (select && $sel[0] && $sel[0].type == 'select-one') {
+                // deselect all other options
+                $sel.find('option').selected(false);
+            }
+            this.selected = select;
+        }
+    });
+};
+
+// expose debug var
+$.fn.ajaxSubmit.debug = false;
+
+// helper fn for console logging
+function log() {
+    if (!$.fn.ajaxSubmit.debug) 
+        return;
+    var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
+    if (window.console && window.console.log) {
+        window.console.log(msg);
+    }
+    else if (window.opera && window.opera.postError) {
+        window.opera.postError(msg);
+    }
+}
+
+})(jQuery);
diff --git a/themes/greydragon/js/jquery.json.min.js b/themes/greydragon/js/jquery.json.min.js
new file mode 100644
index 0000000..bad4a0a
--- /dev/null
+++ b/themes/greydragon/js/jquery.json.min.js
@@ -0,0 +1,31 @@
+
+(function($){$.toJSON=function(o)
+{if(typeof(JSON)=='object'&&JSON.stringify)
+return JSON.stringify(o);var type=typeof(o);if(o===null)
+return"null";if(type=="undefined")
+return undefined;if(type=="number"||type=="boolean")
+return o+"";if(type=="string")
+return $.quoteString(o);if(type=='object')
+{if(typeof o.toJSON=="function")
+return $.toJSON(o.toJSON());if(o.constructor===Date)
+{var month=o.getUTCMonth()+1;if(month<10)month='0'+month;var day=o.getUTCDate();if(day<10)day='0'+day;var year=o.getUTCFullYear();var hours=o.getUTCHours();if(hours<10)hours='0'+hours;var minutes=o.getUTCMinutes();if(minutes<10)minutes='0'+minutes;var seconds=o.getUTCSeconds();if(seconds<10)seconds='0'+seconds;var milli=o.getUTCMilliseconds();if(milli<100)milli='0'+milli;if(milli<10)milli='0'+milli;return'"'+year+'-'+month+'-'+day+'T'+
+hours+':'+minutes+':'+seconds+'.'+milli+'Z"';}
+if(o.constructor===Array)
+{var ret=[];for(var i=0;i<o.length;i++)
+ret.push($.toJSON(o[i])||"null");return"["+ret.join(",")+"]";}
+var pairs=[];for(var k in o){var name;var type=typeof k;if(type=="number")
+name='"'+k+'"';else if(type=="string")
+name=$.quoteString(k);else
+continue;if(typeof o[k]=="function")
+continue;var val=$.toJSON(o[k]);pairs.push(name+":"+val);}
+return"{"+pairs.join(", ")+"}";}};$.evalJSON=function(src)
+{if(typeof(JSON)=='object'&&JSON.parse)
+return JSON.parse(src);return eval("("+src+")");};$.secureEvalJSON=function(src)
+{if(typeof(JSON)=='object'&&JSON.parse)
+return JSON.parse(src);var filtered=src;filtered=filtered.replace(/\\["\\\/bfnrtu]/g,'@');filtered=filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']');filtered=filtered.replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered))
+return eval("("+src+")");else
+throw new SyntaxError("Error parsing JSON, source is not valid.");};$.quoteString=function(string)
+{if(string.match(_escapeable))
+{return'"'+string.replace(_escapeable,function(a)
+{var c=_meta[a];if(typeof c==='string')return c;c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
+return'"'+string+'"';};var _escapeable=/["\\\x00-\x1f\x7f-\x9f]/g;var _meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};})(jQuery);
\ No newline at end of file
diff --git a/themes/greydragon/js/jquery.min.js b/themes/greydragon/js/jquery.min.js
new file mode 100644
index 0000000..73f33fb
--- /dev/null
+++ b/themes/greydragon/js/jquery.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.11.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m="1.11.0",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(l.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:k&&!k.call("\ufeff\xa0")?function(a){return null==a?"":k.call(a)}:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||n.guid++,e):void 0},now:function(){return+new Date},support:l}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="<select t=''><option selected=''></option></select>",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=jb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=kb(b);function nb(){}nb.prototype=d.filters=d.pseudos,d.setFilters=new nb;function ob(a,b){var c,e,f,g,h,i,j,k=x[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=Q.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?db.error(a):x(a,i).slice(0)}function pb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=a.document,A=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,B=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:A.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:z,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=z.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return y.find(a);this.length=1,this[0]=d}return this.context=z,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};B.prototype=n.fn,y=n(z);var C=/^(?:parents|prev(?:Until|All))/,D={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!n(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function E(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return E(a,"nextSibling")},prev:function(a){return E(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(D[a]||(e=n.unique(e)),C.test(a)&&(e=e.reverse())),this.pushStack(e)}});var F=/\S+/g,G={};function H(a){var b=G[a]={};return n.each(a.match(F)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?G[a]||H(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&n.each(arguments,function(a,c){var d;while((d=n.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){if(a===!0?!--n.readyWait:!n.isReady){if(!z.body)return setTimeout(n.ready);n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(z,[n]),n.fn.trigger&&n(z).trigger("ready").off("ready"))}}});function J(){z.addEventListener?(z.removeEventListener("DOMContentLoaded",K,!1),a.removeEventListener("load",K,!1)):(z.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(z.addEventListener||"load"===event.type||"complete"===z.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===z.readyState)setTimeout(n.ready);else if(z.addEventListener)z.addEventListener("DOMContentLoaded",K,!1),a.addEventListener("load",K,!1);else{z.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&z.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!n.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}J(),n.ready()}}()}return I.promise(b)};var L="undefined",M;for(M in n(l))break;l.ownLast="0"!==M,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c=z.getElementsByTagName("body")[0];c&&(a=z.createElement("div"),a.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",b=z.createElement("div"),c.appendChild(a).appendChild(b),typeof b.style.zoom!==L&&(b.style.cssText="border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1",(l.inlineBlockNeedsLayout=3===b.offsetWidth)&&(c.style.zoom=1)),c.removeChild(a),a=b=null)}),function(){var a=z.createElement("div");if(null==l.deleteExpando){l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}}a=null}(),n.acceptData=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(n.acceptData(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f
+}}function S(a,b,c){if(n.acceptData(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d]));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=n._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=["Top","Right","Bottom","Left"],V=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},W=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},X=/^(?:checkbox|radio)$/i;!function(){var a=z.createDocumentFragment(),b=z.createElement("div"),c=z.createElement("input");if(b.setAttribute("className","t"),b.innerHTML="  <link/><table></table><a href='/a'>a</a>",l.leadingWhitespace=3===b.firstChild.nodeType,l.tbody=!b.getElementsByTagName("tbody").length,l.htmlSerialize=!!b.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==z.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,a.appendChild(c),l.appendChecked=c.checked,b.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,a.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){l.noCloneEvent=!1}),b.cloneNode(!0).click()),null==l.deleteExpando){l.deleteExpando=!0;try{delete b.test}catch(d){l.deleteExpando=!1}}a=b=c=null}(),function(){var b,c,d=z.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),l[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var Y=/^(?:input|select|textarea)$/i,Z=/^key/,$=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,ab=/^([^.]*)(?:\.(.+)|)$/;function bb(){return!0}function cb(){return!1}function db(){try{return z.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof n===L||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(F)||[""],h=b.length;while(h--)f=ab.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(F)||[""],j=b.length;while(j--)if(h=ab.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,m,o=[d||z],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||z,3!==d.nodeType&&8!==d.nodeType&&!_.test(p+n.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[n.expando]?b:new n.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),k=n.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!n.isWindow(d)){for(i=k.delegateType||p,_.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||z)&&o.push(l.defaultView||l.parentWindow||a)}m=0;while((h=o[m++])&&!b.isPropagationStopped())b.type=m>1?i:k.bindType||p,f=(n._data(h,"events")||{})[b.type]&&n._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&n.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&n.acceptData(d)&&g&&d[p]&&!n.isWindow(d)){l=d[g],l&&(d[g]=null),n.event.triggered=p;try{d[p]()}catch(r){}n.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((n.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?n(c,this).index(i)>=0:n.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=$.test(e)?this.mouseHooks:Z.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||z),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||z,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==db()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===db()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=z.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===L&&(a[d]=null),a.detachEvent(d,c))},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&(a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault())?bb:cb):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:cb,isPropagationStopped:cb,isImmediatePropagationStopped:cb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=bb,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=bb,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),l.submitBubbles||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?b.form:void 0;c&&!n._data(c,"submitBubbles")&&(n.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),n._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.changeBubbles||(n.event.special.change={setup:function(){return Y.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),n.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),n.event.simulate("change",this,a,!0)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;Y.test(b.nodeName)&&!n._data(b,"changeBubbles")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a,!0)}),n._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!Y.test(this.nodeName)}}),l.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=n._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=cb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return n().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=cb),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});function eb(a){var b=fb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var fb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gb=/ jQuery\d+="(?:null|\d+)"/g,hb=new RegExp("<(?:"+fb+")[\\s/>]","i"),ib=/^\s+/,jb=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,kb=/<([\w:]+)/,lb=/<tbody/i,mb=/<|&#?\w+;/,nb=/<(?:script|style|link)/i,ob=/checked\s*(?:[^=]|=\s*.checked.)/i,pb=/^$|\/(?:java|ecma)script/i,qb=/^true\/(.*)/,rb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,sb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},tb=eb(z),ub=tb.appendChild(z.createElement("div"));sb.optgroup=sb.option,sb.tbody=sb.tfoot=sb.colgroup=sb.caption=sb.thead,sb.th=sb.td;function vb(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==L?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==L?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,vb(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function wb(a){X.test(a.type)&&(a.defaultChecked=a.checked)}function xb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function yb(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function zb(a){var b=qb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ab(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}function Bb(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Cb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(yb(b).text=a.text,zb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&X.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}n.extend({clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!hb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ub.innerHTML=a.outerHTML,ub.removeChild(f=ub.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=vb(f),h=vb(a),g=0;null!=(e=h[g]);++g)d[g]&&Cb(e,d[g]);if(b)if(c)for(h=h||vb(a),d=d||vb(f),g=0;null!=(e=h[g]);g++)Bb(e,d[g]);else Bb(a,f);return d=vb(f,"script"),d.length>0&&Ab(d,!i&&vb(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k,m=a.length,o=eb(b),p=[],q=0;m>q;q++)if(f=a[q],f||0===f)if("object"===n.type(f))n.merge(p,f.nodeType?[f]:f);else if(mb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(kb.exec(f)||["",""])[1].toLowerCase(),k=sb[i]||sb._default,h.innerHTML=k[1]+f.replace(jb,"<$1></$2>")+k[2],e=k[0];while(e--)h=h.lastChild;if(!l.leadingWhitespace&&ib.test(f)&&p.push(b.createTextNode(ib.exec(f)[0])),!l.tbody){f="table"!==i||lb.test(f)?"<table>"!==k[1]||lb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)n.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}n.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),l.appendChecked||n.grep(vb(p,"input"),wb),q=0;while(f=p[q++])if((!d||-1===n.inArray(f,d))&&(g=n.contains(f.ownerDocument,f),h=vb(o.appendChild(f),"script"),g&&Ab(h),c)){e=0;while(f=h[e++])pb.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.deleteExpando,m=n.event.special;null!=(d=a[h]);h++)if((b||n.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k?delete d[i]:typeof d.removeAttribute!==L?d.removeAttribute(i):d[i]=null,c.push(f))}}}),n.fn.extend({text:function(a){return W(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||z).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(vb(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&Ab(vb(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(vb(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return W(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(gb,""):void 0;if(!("string"!=typeof a||nb.test(a)||!l.htmlSerialize&&hb.test(a)||!l.leadingWhitespace&&ib.test(a)||sb[(kb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(jb,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(vb(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(vb(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,o=k-1,p=a[0],q=n.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&ob.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(i=n.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=n.map(vb(i,"script"),yb),f=g.length;k>j;j++)d=i,j!==o&&(d=n.clone(d,!0,!0),f&&n.merge(g,vb(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,n.map(g,zb),j=0;f>j;j++)d=g[j],pb.test(d.type||"")&&!n._data(d,"globalEval")&&n.contains(h,d)&&(d.src?n._evalUrl&&n._evalUrl(d.src):n.globalEval((d.text||d.textContent||d.innerHTML||"").replace(rb,"")));i=c=null}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],g=n(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Db,Eb={};function Fb(b,c){var d=n(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:n.css(d[0],"display");return d.detach(),e}function Gb(a){var b=z,c=Eb[a];return c||(c=Fb(a,b),"none"!==c&&c||(Db=(Db||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Db[0].contentWindow||Db[0].contentDocument).document,b.write(),b.close(),c=Fb(a,b),Db.detach()),Eb[a]=c),c}!function(){var a,b,c=z.createElement("div"),d="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;padding:0;margin:0;border:0";c.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],a.style.cssText="float:left;opacity:.5",l.opacity=/^0.5/.test(a.style.opacity),l.cssFloat=!!a.style.cssFloat,c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===c.style.backgroundClip,a=c=null,l.shrinkWrapBlocks=function(){var a,c,e,f;if(null==b){if(a=z.getElementsByTagName("body")[0],!a)return;f="border:0;width:0;height:0;position:absolute;top:0;left:-9999px",c=z.createElement("div"),e=z.createElement("div"),a.appendChild(c).appendChild(e),b=!1,typeof e.style.zoom!==L&&(e.style.cssText=d+";width:1px;padding:1px;zoom:1",e.innerHTML="<div></div>",e.firstChild.style.width="5px",b=3!==e.offsetWidth),a.removeChild(c),a=c=e=null}return b}}();var Hb=/^margin/,Ib=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Jb,Kb,Lb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Jb=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)},Kb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Jb(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),Ib.test(g)&&Hb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):z.documentElement.currentStyle&&(Jb=function(a){return a.currentStyle},Kb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Jb(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Ib.test(g)&&!Lb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Mb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h=z.createElement("div"),i="border:0;width:0;height:0;position:absolute;top:0;left:-9999px",j="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;padding:0;margin:0;border:0";h.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",b=h.getElementsByTagName("a")[0],b.style.cssText="float:left;opacity:.5",l.opacity=/^0.5/.test(b.style.opacity),l.cssFloat=!!b.style.cssFloat,h.style.backgroundClip="content-box",h.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===h.style.backgroundClip,b=h=null,n.extend(l,{reliableHiddenOffsets:function(){if(null!=c)return c;var a,b,d,e=z.createElement("div"),f=z.getElementsByTagName("body")[0];if(f)return e.setAttribute("className","t"),e.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=z.createElement("div"),a.style.cssText=i,f.appendChild(a).appendChild(e),e.innerHTML="<table><tr><td></td><td>t</td></tr></table>",b=e.getElementsByTagName("td"),b[0].style.cssText="padding:0;margin:0;border:0;display:none",d=0===b[0].offsetHeight,b[0].style.display="",b[1].style.display="none",c=d&&0===b[0].offsetHeight,f.removeChild(a),e=f=null,c},boxSizing:function(){return null==d&&k(),d},boxSizingReliable:function(){return null==e&&k(),e},pixelPosition:function(){return null==f&&k(),f},reliableMarginRight:function(){var b,c,d,e;if(null==g&&a.getComputedStyle){if(b=z.getElementsByTagName("body")[0],!b)return;c=z.createElement("div"),d=z.createElement("div"),c.style.cssText=i,b.appendChild(c).appendChild(d),e=d.appendChild(z.createElement("div")),e.style.cssText=d.style.cssText=j,e.style.marginRight=e.style.width="0",d.style.width="1px",g=!parseFloat((a.getComputedStyle(e,null)||{}).marginRight),b.removeChild(c)}return g}});function k(){var b,c,h=z.getElementsByTagName("body")[0];h&&(b=z.createElement("div"),c=z.createElement("div"),b.style.cssText=i,h.appendChild(b).appendChild(c),c.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;display:block;padding:1px;border:1px;width:4px;margin-top:1%;top:1%",n.swap(h,null!=h.style.zoom?{zoom:1}:{},function(){d=4===c.offsetWidth}),e=!0,f=!1,g=!0,a.getComputedStyle&&(f="1%"!==(a.getComputedStyle(c,null)||{}).top,e="4px"===(a.getComputedStyle(c,null)||{width:"4px"}).width),h.removeChild(b),c=h=null)}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Nb=/alpha\([^)]*\)/i,Ob=/opacity\s*=\s*([^)]*)/,Pb=/^(none|table(?!-c[ea]).+)/,Qb=new RegExp("^("+T+")(.*)$","i"),Rb=new RegExp("^([+-])=("+T+")","i"),Sb={position:"absolute",visibility:"hidden",display:"block"},Tb={letterSpacing:0,fontWeight:400},Ub=["Webkit","O","Moz","ms"];function Vb(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Ub.length;while(e--)if(b=Ub[e]+c,b in a)return b;return d}function Wb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&V(d)&&(f[g]=n._data(d,"olddisplay",Gb(d.nodeName)))):f[g]||(e=V(d),(c&&"none"!==c||!e)&&n._data(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Xb(a,b,c){var d=Qb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Yb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+U[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+U[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+U[f]+"Width",!0,e))):(g+=n.css(a,"padding"+U[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+U[f]+"Width",!0,e)));return g}function Zb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Jb(a),g=l.boxSizing()&&"border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Kb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Ib.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Yb(a,b,c||(g?"border":"content"),d,f)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Kb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":l.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;if(b=n.cssProps[h]||(n.cssProps[h]=Vb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Rb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]="",i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Vb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Kb(a,b,d)),"normal"===f&&b in Tb&&(f=Tb[b]),""===c||c?(e=parseFloat(f),c===!0||n.isNumeric(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?0===a.offsetWidth&&Pb.test(n.css(a,"display"))?n.swap(a,Sb,function(){return Zb(a,b,d)}):Zb(a,b,d):void 0},set:function(a,c,d){var e=d&&Jb(a);return Xb(a,c,d?Yb(a,b,d,l.boxSizing()&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Ob.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Nb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Nb.test(f)?f.replace(Nb,e):f+" "+e)}}),n.cssHooks.marginRight=Mb(l.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},Kb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+U[d]+b]=f[d]||f[d-2]||f[0];return e}},Hb.test(a)||(n.cssHooks[a+b].set=Xb)}),n.fn.extend({css:function(a,b){return W(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Jb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)
+},a,b,arguments.length>1)},show:function(){return Wb(this,!0)},hide:function(){return Wb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){V(this)?n(this).show():n(this).hide()})}});function $b(a,b,c,d,e){return new $b.prototype.init(a,b,c,d,e)}n.Tween=$b,$b.prototype={constructor:$b,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=$b.propHooks[this.prop];return a&&a.get?a.get(this):$b.propHooks._default.get(this)},run:function(a){var b,c=$b.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):$b.propHooks._default.set(this),this}},$b.prototype.init.prototype=$b.prototype,$b.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},$b.propHooks.scrollTop=$b.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=$b.prototype.init,n.fx.step={};var _b,ac,bc=/^(?:toggle|show|hide)$/,cc=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),dc=/queueHooks$/,ec=[jc],fc={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=cc.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&cc.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function gc(){return setTimeout(function(){_b=void 0}),_b=n.now()}function hc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=U[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function ic(a,b,c){for(var d,e=(fc[b]||[]).concat(fc["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function jc(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&V(a),r=n._data(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k=Gb(a.nodeName),"none"===j&&(j=k),"inline"===j&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==k?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],bc.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}if(!n.isEmptyObject(o)){r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=ic(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function kc(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function lc(a,b,c){var d,e,f=0,g=ec.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=_b||gc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:_b||gc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(kc(k,j.opts.specialEasing);g>f;f++)if(d=ec[f].call(j,a,k,j.opts))return d;return n.map(k,ic,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(lc,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],fc[c]=fc[c]||[],fc[c].unshift(b)},prefilter:function(a,b){b?ec.unshift(a):ec.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(V).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=lc(this,n.extend({},a),f);(e||n._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=n._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&dc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=n._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(hc(b,!0),a,d,e)}}),n.each({slideDown:hc("show"),slideUp:hc("hide"),slideToggle:hc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=n.timers,c=0;for(_b=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),_b=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){ac||(ac=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(ac),ac=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e=z.createElement("div");e.setAttribute("className","t"),e.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=e.getElementsByTagName("a")[0],c=z.createElement("select"),d=c.appendChild(z.createElement("option")),b=e.getElementsByTagName("input")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==e.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=d.selected,l.enctype=!!z.createElement("form").enctype,c.disabled=!0,l.optDisabled=!d.disabled,b=z.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value,a=b=c=d=e=null}();var mc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(mc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.text(a)}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(l.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var nc,oc,pc=n.expr.attrHandle,qc=/^(?:checked|selected)$/i,rc=l.getSetAttribute,sc=l.input;n.fn.extend({attr:function(a,b){return W(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===L?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?oc:nc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(F);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)?sc&&rc||!qc.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(rc?c:d)},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),oc={set:function(a,b,c){return b===!1?n.removeAttr(a,c):sc&&rc||!qc.test(c)?a.setAttribute(!rc&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=pc[b]||n.find.attr;pc[b]=sc&&rc||!qc.test(b)?function(a,b,d){var e,f;return d||(f=pc[b],pc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,pc[b]=f),e}:function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),sc&&rc||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):nc&&nc.set(a,b,c)}}),rc||(nc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},pc.id=pc.name=pc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:nc.set},n.attrHooks.contenteditable={set:function(a,b,c){nc.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var tc=/^(?:input|select|textarea|button|object)$/i,uc=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return W(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):tc.test(a.nodeName)||uc.test(a.nodeName)&&a.href?0:-1}}}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this}),l.enctype||(n.propFix.enctype="encoding");var vc=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(F)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(vc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(F)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(vc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(F)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===L||"boolean"===c)&&(this.className&&n._data(this,"__className__",this.className),this.className=this.className||a===!1?"":n._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(vc," ").indexOf(b)>=0)return!0;return!1}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var wc=n.now(),xc=/\?/,yc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(yc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var zc,Ac,Bc=/#.*$/,Cc=/([?&])_=[^&]*/,Dc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Ec=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Fc=/^(?:GET|HEAD)$/,Gc=/^\/\//,Hc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Ic={},Jc={},Kc="*/".concat("*");try{Ac=location.href}catch(Lc){Ac=z.createElement("a"),Ac.href="",Ac=Ac.href}zc=Hc.exec(Ac.toLowerCase())||[];function Mc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(F)||[];if(n.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Nc(a,b,c,d){var e={},f=a===Jc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Oc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Pc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Qc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ac,type:"GET",isLocal:Ec.test(zc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Kc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Oc(Oc(a,n.ajaxSettings),b):Oc(n.ajaxSettings,a)},ajaxPrefilter:Mc(Ic),ajaxTransport:Mc(Jc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Dc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||Ac)+"").replace(Bc,"").replace(Gc,zc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(F)||[""],null==k.crossDomain&&(c=Hc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===zc[1]&&c[2]===zc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(zc[3]||("http:"===zc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),Nc(Ic,k,b,v),2===t)return v;h=k.global,h&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Fc.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(xc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Cc.test(e)?e.replace(Cc,"$1_="+wc++):e+(xc.test(e)?"&":"?")+"_="+wc++)),k.ifModified&&(n.lastModified[e]&&v.setRequestHeader("If-Modified-Since",n.lastModified[e]),n.etag[e]&&v.setRequestHeader("If-None-Match",n.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Kc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Nc(Jc,k,b,v)){v.readyState=1,h&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Pc(k,v,c)),u=Qc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(n.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var b=n(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!l.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||n.css(a,"display"))},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var Rc=/%20/g,Sc=/\[\]$/,Tc=/\r?\n/g,Uc=/^(?:submit|button|image|reset|file)$/i,Vc=/^(?:input|select|textarea|keygen)/i;function Wc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||Sc.test(a)?d(a,e):Wc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Wc(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Wc(c,a[c],b,e);return d.join("&").replace(Rc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Vc.test(this.nodeName)&&!Uc.test(a)&&(this.checked||!X.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(Tc,"\r\n")}}):{name:b.name,value:c.replace(Tc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&$c()||_c()}:$c;var Xc=0,Yc={},Zc=n.ajaxSettings.xhr();a.ActiveXObject&&n(a).on("unload",function(){for(var a in Yc)Yc[a](void 0,!0)}),l.cors=!!Zc&&"withCredentials"in Zc,Zc=l.ajax=!!Zc,Zc&&n.ajaxTransport(function(a){if(!a.crossDomain||l.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Xc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Yc[g],b=void 0,f.onreadystatechange=n.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Yc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function $c(){try{return new a.XMLHttpRequest}catch(b){}}function _c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=z.head||n("head")[0]||z.documentElement;return{send:function(d,e){b=z.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var ad=[],bd=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=ad.pop()||n.expando+"_"+wc++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(bd.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&bd.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(bd,"$1"+e):b.jsonp!==!1&&(b.url+=(xc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,ad.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||z;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var cd=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&cd)return cd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=a.slice(h,a.length),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&n.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var dd=a.document.documentElement;function ed(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&n.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?(typeof e.getBoundingClientRect!==L&&(d=e.getBoundingClientRect()),c=ed(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||dd;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||dd})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return W(this,function(a,d,e){var f=ed(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Mb(l.pixelPosition,function(a,c){return c?(c=Kb(a,b),Ib.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return W(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var fd=a.jQuery,gd=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=gd),b&&a.jQuery===n&&(a.jQuery=fd),n},typeof b===L&&(a.jQuery=a.$=n),n});
diff --git a/themes/greydragon/js/ui.support.js b/themes/greydragon/js/ui.support.js
new file mode 100644
index 0000000..59fde3a
--- /dev/null
+++ b/themes/greydragon/js/ui.support.js
@@ -0,0 +1,80 @@
+/*
+* Grey Dragon Theme: JS support 
+* Copyright (c) 2007-2011 Serge Dosyukov
+* Dual licensed under the MIT and GPL licenses.
+*/
+
+jQuery.fn.extend({
+  scrollTo: function(a, b) { },
+
+  myAjaxLoginSubmit: function() {
+    $('form#g-login-form').one('submit', function() {
+      $(this).ajaxSubmit({
+        dataType: 'json', 
+        success: function(data) {
+          if (data.result == 'error') {
+            $('#g-login').html(data.form);
+            $().myAjaxLoginSubmit();
+          } else {
+            // object
+            alert(typeof(data));
+            Shadowbox.close(); 
+            window.location.reload(); 
+          }
+        }
+      }); 
+      return false;
+    });
+  },
+
+  myAjaxSubmit: function() {
+    $('form').one('submit', function() {
+      try {
+        $(this).ajaxSubmit({
+          success: function(data) {
+            // object
+            // alert(typeof(data));
+            if (data.result == 'error') {
+              $('#sb-content form').html(data.form);
+              $().myAjaxSubmit();
+            } else {
+              Shadowbox.close();
+              if (data.reload) {
+                window.location.reload();
+              }
+            }
+          }
+        });
+      } catch (e) { 
+        window.location.reload();
+      }
+
+      return false;
+    });
+  },
+
+  theme_ready: function() {
+    // Initialize dialogs
+    $(".g-dialog-link").gallery_dialog();
+
+    // Initialize short forms
+    $(".g-short-form").gallery_short_form();
+
+    try {
+      $(".g-message-block").fadeOut(10000);
+      $(".g-ajax-link").gallery_ajax();
+    } catch (e) { }
+
+    $("#g-site-menu>ul>li>ul").show();
+    $("#g-login-menu").show();
+    $(".g-context-menu").show();
+  }
+});
+
+function onMiniSlideShowReady() {
+  $("#g-rootpage-link").css("background-image", "none");
+}
+
+$(document).ready(function() {
+  $().theme_ready();
+});
diff --git a/themes/greydragon/libraries/MY_Theme_View.php b/themes/greydragon/libraries/MY_Theme_View.php
new file mode 100644
index 0000000..4b77ac6
--- /dev/null
+++ b/themes/greydragon/libraries/MY_Theme_View.php
@@ -0,0 +1,925 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+class Theme_View extends Theme_View_Core {
+
+  protected $viewmode = "default";
+  protected $toolbar_large = FALSE;
+  protected $paginator_album;
+  protected $paginator_photo;
+  protected $sidebarvisible;
+  protected $sidebarallowed;
+  protected $sidebar_hideguest = FALSE;
+  protected $logopath;
+  protected $favicon = "lib/images/favicon.ico";
+  protected $appletouchicon;
+  protected $album_descmode = "hide";
+  protected $disablephotopage = FALSE;
+  protected $hidecontextmenu = FALSE;
+  protected $thumb_ratio = "";
+  protected $thumb_descmode_a = "overlay";
+  protected $thumb_descmode = "overlay";
+  protected $photo_descmode = "overlay_top";
+  protected $thumb_imgalign = "top";
+  protected $thumb_metamode = "default";
+  protected $is_blockheader_visible = TRUE;
+  protected $is_photometa_visible = FALSE;
+  protected $disable_seosupport = FALSE;
+  protected $mainmenu_position = "bottom-left";
+  protected $breadcrumbs_position = "bottom-right";
+  protected $breadcrumbs_showinroot = FALSE;
+  protected $copyright = null;
+  protected $show_guest_menu = FALSE;
+  protected $loginmenu_position = "default";
+  protected $visible_title_length = 15;
+  protected $title_source = "default";
+  protected $desc_allowbbcode = FALSE;
+  protected $enable_pagecache = FALSE;
+  protected $flex_rows = FALSE;
+  protected $photo_popupbox = "default";
+  protected $custom_css_path = "";
+  protected $thumb_inpage = FALSE;
+  protected $thumb_random = FALSE;
+  protected $row_count = 3;
+  protected $column_count = 3;
+
+  protected $crop_factor = -1;
+  protected $crop_class = "";
+  protected $_thumb_size_x = 200;
+  protected $_thumb_size_y = 200;
+  protected $allow_root_page = FALSE;
+  protected $show_root_page = FALSE;
+  protected $show_root_desc = TRUE;
+  protected $root_feed = "gallery/latest";
+  protected $root_cyclemode = "fade";
+  protected $root_delay = 15;
+  protected $root_description;
+  protected $permalinks = array("enter" => "?root=no", "root" => "?root=yes");
+
+  protected $last_update = 0;
+
+  protected $colorpack = "greydragon";
+  protected $framepack = "greydragon";
+  protected $themename = "";
+  protected $themeversion = "";
+  protected $themecss = array();
+
+  protected $is_rtl = FALSE;
+
+  protected function ensurevalue($value, $default) {
+    if ((!isset($value)) or ($value == "")):
+      return $default;
+    else:
+      return $value;
+    endif;
+  }
+
+  protected function ensureoptionsvalue($key, $default) {
+    return ($this->ensurevalue(module::get_var("th_greydragon", $key), $default));
+  }
+
+  public function read_session_cmdparam($cmd, $cookie, $issession, $default) {
+    try {
+      $_cmd = $_GET[$cmd]; 
+    } catch (Exception $e) {
+    };
+
+    if (isset($_cmd)):
+      $_var = strtolower($_cmd);
+      $_from_cmd = TRUE;
+      if ($_var == "default"):
+        $_var = $default;
+      endif;
+    else:
+      $_from_cmd = FALSE;
+      if ($cookie):
+        try { 
+          $_var = $_COOKIE[$cookie];
+        } catch (Exception $e) {
+        };
+      endif;
+    endif;
+
+    if (!isset($_var)):
+      $_var = $default;
+    endif;
+
+    if ($issession):
+      if ($_from_cmd):
+        setcookie($cookie, $_var, 0);
+      endif;
+    else:
+      setcookie($cookie, $_var, time() + 31536000);
+    endif;
+
+    return $_var;
+  }
+
+  public function load_sessioninfo() {
+    // Sidebar position is kept for 360 days. Can be changed via url
+    $this->sidebarallowed = $this->ensureoptionsvalue("sidebar_allowed", "any");
+    $_sb_visible = $this->ensureoptionsvalue("sidebar_visible", "right");
+
+    if ($this->sidebarallowed == "default"):
+      $this->sidebarallowed = $_sb_visible;
+      $this->sidebarvisible = $_sb_visible;
+    else:
+      $this->sidebarvisible = $this->read_session_cmdparam("sb", "gd_sidebar_pos", FALSE, $_sb_visible);
+    endif;
+    $this->colorpack = $this->read_session_cmdparam("colorpack", "gd_colorpack", TRUE,  $this->ensureoptionsvalue("color_pack", "greydragon"));
+    $this->framepack = $this->read_session_cmdparam("framepack", "gd_framepack", TRUE, $this->ensureoptionsvalue("frame_pack", "greydragon"));
+    $this->viewmode  = $this->read_session_cmdparam("viewmode", "gd_viewmode",  TRUE, $this->ensureoptionsvalue("viewmode", "default"));
+    $this->is_rtl    = $this->read_session_cmdparam("is_rtl", "gd_rtl", TRUE, "no") == "yes";
+    $this->thumb_ratio = $this->read_session_cmdparam("ratio", "gd_ratio", TRUE, $this->ensureoptionsvalue("thumb_ratio", "photo"));
+
+    if ($this->ensureoptionsvalue("allow_root_page", FALSE)):
+      $_root = $this->read_session_cmdparam("root", "gd_rootpage", TRUE, "yes"); 
+
+      $this->show_root_page = ($_root == "yes");
+      $this->allow_root_page = TRUE;
+
+      if ($this->show_root_page):
+        $item = $this->item();
+        if (($item) && ($item->id == item::root()->id)):
+          if (($this->sidebarvisible == "left") or ($this->sidebarvisible == "right")):
+            $this->sidebarvisible = "bottom";
+          endif;
+        else:
+          $this->show_root_page = FALSE;
+          setcookie("gd_rootpage", "no", 0);
+        endif;
+
+        if ($this->ensureoptionsvalue("hide_root_sidebar", FALSE)):
+          $this->sidebarallowed = "none";
+          $this->sidebarvisible = "none";
+        endif;
+      endif;
+    endif;
+
+    $this->sidebarvisible = $this->ensurevalue($this->sidebarvisible, "right");
+
+    switch ($this->sidebarallowed):
+      case "default":
+        break;
+      case "right":
+        $this->sidebarvisible = "right";
+        break;
+      case "left": 
+        $this->sidebarvisible = "left";
+        break;
+      case "bottom": 
+        $this->sidebarvisible = "bottom";
+        break;
+      case "top": 
+        $this->sidebarvisible = "top";
+        break;
+    endswitch;
+
+    if ($this->item()):
+      if ($this->ensureoptionsvalue("sidebar_albumonly", FALSE)):
+        if (!$this->item()->is_album()):
+          $this->sidebarvisible = "none";
+          $this->sidebarallowed = "none";
+        endif;
+      endif;
+    endif;
+
+    $this->sidebar_hideguest = $this->ensureoptionsvalue("sidebar_hideguest", FALSE);
+    if ((identity::active_user()->guest) & ($this->sidebar_hideguest)):
+      $this->sidebarvisible = "none";
+      $this->sidebarallowed = "none";
+    endif;
+
+    if (($this->page_subtype == "login") || ($this->page_subtype == "reauthenticate") || ($this->page_subtype == "error")): 
+      $this->sidebarvisible = "none";
+      $this->sidebarallowed = "none";
+    endif;
+
+    $this->last_update = $this->ensureoptionsvalue("last_update", time());
+    $this->toolbar_large = $this->ensureoptionsvalue("toolbar_large", FALSE);
+    $this->row_count = $this->ensureoptionsvalue("row_count", 3);
+    $this->column_count = $this->ensureoptionsvalue("column_count", 3);
+    $this->logopath = $this->ensureoptionsvalue("logo_path", url::file("lib/images/logo.png"));
+    $this->favicon = $this->ensurevalue(module::get_var("gallery", "favicon_url"), url::file("lib/images/favicon.ico"));
+    $this->appletouchicon = module::get_var("gallery", "apple_touch_icon_url");
+    $this->horizontal_crop = $this->ensureoptionsvalue("horizontal_crop", FALSE);
+    $this->album_descmode = $this->ensureoptionsvalue("album_descmode", "hide");
+    $this->disablephotopage = $this->ensureoptionsvalue("disablephotopage", FALSE);
+    $this->hidecontextmenu = $this->ensureoptionsvalue("hidecontextmenu", FALSE);
+    $this->visible_title_length = module::get_var("gallery", "visible_title_length", 15);
+    $this->title_source = $this->ensureoptionsvalue("title_source", "default");
+    $this->thumb_descmode_a = $this->ensureoptionsvalue("thumb_descmode_a", "overlay");
+    $this->thumb_descmode = $this->ensureoptionsvalue("thumb_descmode", "overlay");
+    $this->photo_descmode = $this->ensureoptionsvalue("photo_descmode", "overlay_top");
+
+    $this->thumb_random = $this->ensureoptionsvalue("thumb_random", FALSE);
+    $this->thumb_imgalign = $this->ensureoptionsvalue("thumb_imgalign", "top");
+    if (module::is_active("info") || module::is_active("rwinfo")):
+      $this->thumb_metamode = $this->ensureoptionsvalue("thumb_metamode", "default");
+      $this->is_photometa_visible = (!$this->ensureoptionsvalue("hide_photometa", TRUE));
+    else:
+      $this->thumb_metamode = "hide";
+      $this->is_photometa_visible = FALSE;
+    endif;
+    $this->disable_seosupport = $this->ensureoptionsvalue("disable_seosupport", FALSE);
+    $this->is_blockheader_visible = (!$this->ensureoptionsvalue("hide_blockheader", FALSE));
+
+    $this->mainmenu_position = $this->ensureoptionsvalue("mainmenu_position", "default");
+    $this->show_guest_menu = $this->ensureoptionsvalue("show_guest_menu", FALSE);
+    $this->breadcrumbs_position = $this->ensureoptionsvalue("breadcrumbs_position", "default");
+    $this->breadcrumbs_showinroot = $this->ensureoptionsvalue("breadcrumbs_showinroot", FALSE);
+    $this->desc_allowbbcode = $this->ensureoptionsvalue("desc_allowbbcode", FALSE);
+
+    $this->loginmenu_position = $this->ensureoptionsvalue("loginmenu_position", "default");
+    $this->copyright = $this->ensureoptionsvalue("copyright", null);
+    $this->paginator_album = $this->ensureoptionsvalue("paginator_album", "top");
+    $this->paginator_photo = $this->ensureoptionsvalue("paginator_photo", "top");
+    $this->enable_pagecache = $this->ensureoptionsvalue("enable_pagecache", FALSE);
+    $this->flex_rows = $this->ensureoptionsvalue("flex_rows", FALSE);
+    $this->show_root_desc = !$this->ensureoptionsvalue("hide_root_desc", FALSE);
+    $this->root_feed = $this->ensureoptionsvalue("root_feed", "gallery/latest");
+    $this->root_cyclemode = $this->ensureoptionsvalue("root_cyclemode", "fade");
+    $this->root_delay = $this->ensureoptionsvalue("root_delay", "15");
+    $this->root_description = module::get_var("th_greydragon", "root_description");
+    if ($this->ensureoptionsvalue("use_permalinks", FALSE)):
+      $this->permalinks = array("enter" => "enter", "root" => "root");
+    endif;
+    if (((module::is_active("shadowbox")) and (module::info("shadowbox"))) 
+        or ((module::is_active("fancybox")) and (module::info("fancybox")))
+        or ((module::is_active("colorbox")) and (module::info("colorbox")))
+       ):
+      $this->photo_popupbox = $this->ensureoptionsvalue("photo_popupbox", "default");
+    else:
+      $this->photo_popupbox = "none";
+    endif;
+
+    try {
+      $theme_info = new ArrayObject(parse_ini_file(THEMEPATH . "greydragon/theme.info"), ArrayObject::ARRAY_AS_PROPS);
+      $this->themename = $theme_info->name;
+      $this->themeversion = $theme_info->version;
+    } catch (Exception $e) {
+      $this->themename = "Grey Dragon Theme";
+      $this->themeversion = "2.7.+";
+    }
+
+    $this->custom_css_path = $this->ensureoptionsvalue("custom_css_path", "");
+
+    switch ($this->thumb_ratio):
+      /* case "square":
+        $this->crop_factor = 1;
+        $this->thumb_type = 'g-thumbtype-sqr';
+        break;
+      */
+      case "digital":
+        $this->crop_factor = 4/3;
+        $this->thumb_type = 'g-thumbtype-dgt';
+        break;
+      case "digital_ex":
+        $this->crop_factor = 4/3;
+        $this->thumb_type = 'g-thumbtype-dgt';
+        $this->_thumb_size_x = 300;
+        break;
+      case "film":
+        $this->crop_factor = 3/2;
+        $this->thumb_type = 'g-thumbtype-flm';
+        break;
+      case "film_ex":
+        $this->crop_factor = 3/2;
+        $this->thumb_type = 'g-thumbtype-flm';
+        $this->_thumb_size_x = 300;
+        break;
+      case "wide":
+        $this->crop_factor = 16/9;
+        $this->thumb_type = 'g-thumbtype-wd';
+        break;
+      case "wide_ex":
+        $this->crop_factor = 16/9;
+        $this->thumb_type = 'g-thumbtype-wd';
+        $this->_thumb_size_x = 300;
+        break;
+      case "photo_ex":
+        $this->crop_factor = 1;
+        $this->thumb_type = 'g-thumbtype-sqr';
+        $this->_thumb_size_x = 300;
+        break;
+      case "photo":
+      default:
+        $this->crop_factor = 1;
+        $this->thumb_type = 'g-thumbtype-sqr';
+        break;
+    endswitch;
+
+    $this->_thumb_size_y = intval($this->_thumb_size_x / $this->crop_factor);
+
+    if (($this->sidebarvisible == "none") or ($this->sidebarvisible == "bottom") or ($this->sidebarvisible == "top") ):
+      $this->thumb_inpage = $this->ensureoptionsvalue("thumb_inpage", FALSE);
+    endif;                 
+  }
+
+  public function is_sidebarallowed($align) {
+    return (($this->sidebarallowed == "any") or ($this->sidebarallowed == $align));
+  }
+
+  public function custom_header() {
+    if (Kohana::find_file('views', "header.html", FALSE)):
+      return new View("header.html"); 
+    endif;
+  }
+
+  public function custom_footer() {
+    if (Kohana::find_file('views', "footer.html", FALSE)):
+      return new View("footer.html"); 
+    endif;
+  }
+
+  public function get_item_title($item, $allowbbcode = FALSE, $limit_title_length = 0) {
+    if (!$item)
+      return "";
+
+    if (method_exists($item, 'is_album') && ($item->is_album())):
+      $title = $item->title;
+    else:
+      switch ($this->title_source):
+        case "description":
+          $title = $item->description;
+          break;
+        case "no-filename":
+          $title = $item->title;
+          if (isset($item->name)):
+            $filename = $item->name;
+          else:
+            $filename = '';
+          endif;
+
+          if (strcasecmp($title, $filename) == 0):
+            $title = "";
+          else:
+            if (defined('PATHINFO_FILENAME')):
+              $filename = pathinfo($filename, PATHINFO_FILENAME);
+            elseif (strstr($item->filename, '.')):
+              $filename = substr($filename, 0, strrpos($filename, '.'));
+            endif; 
+
+            if (strcasecmp($title, $filename) == 0):
+              $title = "";
+            else:
+              $filename = item::convert_filename_to_title($filename); // Normalize filename to title format 
+              if (strcasecmp($title, $filename) == 0)
+                $title = "";
+            endif;
+          endif;
+          break;
+        default:
+          $title = $item->title;
+          break;
+      endswitch;
+    endif;
+
+    $title = html::purify($title);
+    $temp = $title;
+    if ($allowbbcode):
+      $title = $this->bb2html($title, 1);
+    else:
+      $title = $this->bb2html($title, 2);
+    endif;
+
+    if ($limit_title_length):
+      $title = text::limit_chars($title, $limit_title_length);
+    endif;
+
+    if ($title === "")
+      $title = t(ucfirst($item->type)) . " " . $item->id;
+
+    return $title;
+  }
+
+  public function breadcrumb_menu($breadcrumbs) {
+    $content = "";
+    if ($this->breadcrumbs_position == "hide"):
+    elseif (!empty($breadcrumbs) or (empty($breadcrumbs) and $this->breadcrumbs_showinroot)):
+      $content .= '<ul class="g-breadcrumbs g-' . $this->breadcrumbs_position . '">';
+      $i = 0;
+      if (!empty($breadcrumbs)):
+        foreach ($breadcrumbs as $breadcrumb):
+          $title = $this->get_item_title($breadcrumb, FALSE, $this->visible_title_length);
+          $title = trim($title);
+          if (!empty($title)):
+            $content .= '<li class="';
+            $content .= ($breadcrumb->last) ? 'g-active' : '';
+            $content .= ($breadcrumb->first) ? 'g-first' : '';
+            $content .= '">';
+            $content .= (!$breadcrumb->first) ? ' :: ' : '';
+            $content .= (!$breadcrumb->last) ? '<a href="' . $breadcrumb->url . '">' : '';
+            $content .= $title;
+            $content .= (!$breadcrumb->last) ? '</a>' : '';
+            $content .= '</li>';
+          endif;
+          $i++;
+        endforeach;
+      endif;
+      $content .= '</ul>';
+    endif;
+
+    return $content;
+  }
+
+  protected function sidebar_menu_item($type, $url, $caption, $css) {
+    if (!$this->is_sidebarallowed($type)):
+      return "";
+    endif;
+
+    $iscurrent = ($this->sidebarvisible == $type);
+    $content_menu = '<li>'; 
+    if (!$iscurrent):
+      $content_menu .= '<a title="' . $caption . '" href="' . $url . '?sb=' . $type . '" rel="nofollow">';
+    endif;
+    $content_menu .= '<span class="ui-icon g-sidebar-' . $css;
+    if ($iscurrent):
+      $content_menu .= ' g-current';
+    endif;
+    $content_menu .= '">' . $caption . '</span>';
+    if (!$iscurrent):
+      $content_menu .= '</a>';
+    endif;
+
+    return $content_menu . '</li>';
+  }
+
+  public function sidebar_menu($url) {
+    if ($this->sidebarallowed != "any"):
+      return "";
+    endif;
+    if ($this->page_subtype == "profile"):
+      return "";
+    endif;
+
+    $content_menu  = $this->sidebar_menu_item("left", $url, t("Sidebar Left"), "left");
+    $content_menu .= $this->sidebar_menu_item("top", $url, t("Sidebar Top"), "top");
+    $content_menu .= $this->sidebar_menu_item("none", $url, t("No Sidebar"), "full");
+    $content_menu .= $this->sidebar_menu_item("bottom", $url, t("Sidebar Bottom"), "bottom");
+    $content_menu .= $this->sidebar_menu_item("right", $url, t("Sidebar Right"), "right");
+    return '<ul id="g-viewformat">' . $content_menu . '</ul>';
+  }
+
+  public function add_paginator($position, $isalbum = TRUE) {
+    if ($isalbum):
+      $check = (($this->paginator_album == "both") or ($this->paginator_album == $position));
+    else:
+      $check = (($this->paginator_photo == "both") or ($this->paginator_photo == $position));
+    endif;
+
+    if ($check):
+      return ($this->paginator());
+    else:
+      return "";
+    endif;
+  }
+
+  public function get_bodyclass() {
+    $body_class = "";
+    if ($this->is_rtl):
+      $body_class = "rtl";
+    endif;
+    if ($this->toolbar_large):
+      $body_class .= " g-toolbar-large";
+    endif;
+    if ($this->viewmode == "mini"):
+      $body_class .= " viewmode-mini";
+    endif;
+    $body_class .= " g-sidebar-" . $this->sidebarvisible;
+
+    switch ($this->column_count):
+      case 5:    
+        $body_class .= " g-column-5";
+        break;
+      case 4:    
+        $body_class .= " g-column-4";
+        break;
+      case 2:
+        $body_class .= " g-column-2";
+        break;
+      case -1:
+        $body_class .= " g-column-flex";
+        break;
+      case 3:
+      default:
+        $body_class .= " g-column-3";
+        break;
+    endswitch;
+
+
+    switch ($this->thumb_ratio):
+      case "digital_ex":
+      case "film_ex":
+      case "wide_ex":
+      case "photo_ex":
+        $body_class .= ' g-extended';
+        break;
+      default:
+        break;
+    endswitch;
+
+    $body_class .= " g-" . $this->framepack;
+    return 'class="' . trim($body_class) . '"';
+  }
+
+  public function get_thumb_link($item) {
+    if ($item->is_album()):
+      return "";
+    endif;
+    if (item::viewable($item)):
+      if (access::can("view_full", $item)):
+        $direct_link = $item->file_url();
+      else:
+        $direct_link = $item->resize_url();
+      endif;
+      return '<a title="' . $this->get_item_title($item) . '" style="display: none;" class="g-sb-preview" rel="g-preview" href="' . $direct_link . '">&nbsp;</a>';
+    else:
+      return "";
+    endif;
+  }
+
+  public function get_thumb_element($item, $addcontext = FALSE, $linkonly = FALSE) {
+    $thumb_item = $item;
+    if ($this->thumb_random):
+      if ($item->is_album() && ($rnd = item::random_query()->where("parent_id", "=", $item->id)->find()) && $rnd->loaded()):
+        $thumb_item = $rnd;
+      endif;
+    endif;
+
+    if ($item->is_album()):
+      $item_class = "g-album";
+    elseif ($item->is_movie()):
+      $item_class = "g-movie";
+    else:
+      $item_class = "g-photo";
+    endif;
+    $content = '<li id="g-item-id-' . $item->id . '" class="g-item ' . $item_class . ' ' . $this->thumb_type;
+    if ($item->is_album()):
+      $_thumb_descmode = $this->thumb_descmode_a;
+    else:
+      $_thumb_descmode = $this->thumb_descmode;
+    endif;
+
+    $content .= ($_thumb_descmode == "bottom")? " g-expanded" : " g-default";
+
+    if ($thumb_item->has_thumb()):
+      $is_portrait = ($thumb_item->thumb_height > $thumb_item->thumb_width);
+      $_shift = "";
+      switch ($this->thumb_imgalign):
+        case "center":
+          if (($this->crop_factor == 1) and (!$is_portrait)): 
+            $_shift = 'style="margin-top: ' . intval(($this->_thumb_size_y - $thumb_item->thumb_height) / 2) . 'px;"';
+          elseif ($this->crop_factor > 0): 
+            $_shift = 'style="margin-top: -' . intval(($thumb_item->thumb_height - $this->_thumb_size_y) / 2) . 'px;"';
+          endif;
+          break;
+        case "bottom":
+          if (($this->crop_factor == 1) and (!$is_portrait)): 
+            $_shift = 'style="margin-top: ' . intval($this->_thumb_size_y - $thumb_item->thumb_height) . 'px;"';
+          elseif ($this->crop_factor > 0): 
+            $_shift = 'style="margin-top: -' . intval($thumb_item->thumb_height - $this->_thumb_size_y) . 'px;"';
+          endif;
+          break;
+        case "fit":
+          break;
+        case "top":
+        default:
+          break;
+      endswitch;
+    else:
+      $is_portrait = FALSE;
+      $_shift = 'style="margin-top: 0px;"';
+    endif;
+
+    $content .= ($is_portrait)? " g-portrait" : " g-landscape";
+    $content .= '">';
+
+    $content .= '<div class="g-thumbslide">';
+    $content .= $this->thumb_top($item);
+    $thumb_content = '<p class="g-thumbcrop">';
+
+    $use_direct_link = (($this->disablephotopage) && (!$item->is_album())); 
+    $class_name = "g-thumblink";
+    if ($use_direct_link):
+      $class_name .= ' g-sb-preview" rel="g-preview';
+      if (access::can("view_full", $item)):
+        $direct_link = $item->file_url();
+      else:
+        $direct_link = $item->resize_url();
+      endif;
+    else:
+      $direct_link = $item->url();
+    endif;
+
+    if ($use_direct_link && module::is_active("exif") && module::info("exif")): 
+      $thumb_content .= '<a class="g-meta-exif-link g-dialog-link" href="' . url::site("exif/show/{$item->id}") . '" title="' . t("Photo details")->for_html_attr() . '">&nbsp;</a>';
+    endif;
+
+    $thumb_content .= '<a title="' . $this->get_item_title($item) . '" '. $_shift . ' class="' . $class_name . '" href="' . $direct_link . '">';
+    if ($thumb_item->has_thumb()):
+      if (($this->crop_factor > 1) && ($this->thumb_imgalign == "fit")):
+        if ($thumb_item->thumb_height > $this->_thumb_size_y):
+          if ($is_portrait):
+            $_max = $this->_thumb_size_y;
+          else:
+            $_max = intval($this->_thumb_size_x * ($this->_thumb_size_y / $thumb_item->thumb_height));
+          endif;
+        else:
+          $_max = $this->_thumb_size_x;
+        endif;
+        $_max = min($thumb_item->thumb_width, $_max);
+        $thumb_content .= $thumb_item->thumb_img(array("class" => "g-thumbnail"), $_max);
+      else:
+        $thumb_content .= $thumb_item->thumb_img(array("class" => "g-thumbnail"));
+      endif;
+    else:
+      $thumb_content .= '<img title="No Image" alt="No Image" src="' . $this->url("images/missing-img.png") . '"/>';
+    endif;
+    $thumb_content .= '</a></p>';
+
+    if (($this->thumb_metamode != "hide") and ($_thumb_descmode == "overlay_bottom")):
+      $_thumb_metamode = "merged";
+    else:
+      $_thumb_metamode = $this->thumb_metamode;
+    endif;
+
+    if (($_thumb_descmode == "overlay") or ($_thumb_descmode == "overlay_top") or ($_thumb_descmode == "overlay_bottom")):
+      $thumb_content .= '<ul class="g-description ';
+      if ($_thumb_descmode == "overlay_top"):
+        $thumb_content .= 'g-overlay-top';
+      endif;
+      if ($_thumb_descmode == "overlay_bottom"):
+        $thumb_content .= 'g-overlay-bottom';
+      endif;
+      $thumb_content .= '"><li class="g-title">' . $this->get_item_title($item, FALSE, $this->visible_title_length) . '</li>';
+      if ($_thumb_metamode == "merged"):                                                    
+        $thumb_content .= $this->thumb_info($item);
+      endif;
+      $thumb_content .= '</ul>';
+    endif;
+
+    if (($_thumb_metamode == "default") and ($_thumb_descmode != "overlay_bottom")): 
+      $thumb_content .= '<ul class="g-metadata">' . $this->thumb_info($item) . '</ul>';
+    endif;
+
+    if ($_thumb_descmode == "bottom"):
+      $thumb_content .= '<ul class="g-description">';
+      $thumb_content .= '<li class="g-title">' . $this->get_item_title($item) . '</li>';
+      if ($_thumb_metamode == "merged"): 
+        $thumb_content .= $this->thumb_info($item);
+      endif;
+      $thumb_content .= '</ul>';
+    endif;
+
+    if ($addcontext):
+      $_text = $this->context_menu($item, "#g-item-id-{$item->id} .g-thumbnail");
+      $thumb_content .= (stripos($_text, '<li>'))? $_text : null;
+    endif;
+
+    try {
+      if (Kohana::find_file('views', "frame.html", FALSE)):
+        $view = new View("frame.html"); 
+        $view->thumb_content = $thumb_content;
+        $content .= $view;
+      else:
+        $content .= $thumb_content;
+      endif;
+    } catch (Exception $e) {
+      $content .= $thumb_content;
+    }
+
+    $content .= $this->thumb_bottom($item);
+    $content .= '</div>';
+    $content .= '</li>';
+
+    return $content;
+  }
+
+  public function get_block_html($module) {
+    $active = block_manager::get_active("site_sidebar");
+    $result = "";
+    foreach ($active as $id => $desc) {
+      if (($desc[0] == $module) and (method_exists("$desc[0]_block", "get"))) {
+        $block = call_user_func(array("$desc[0]_block", "get"), $desc[1], $this);
+        if (!empty($block)) {
+          $block->id = $id;
+          $block->css_id = $block->css_id . "-inline";
+          $result .= $block;
+        }
+      }
+    }
+    return $result;
+  }
+
+  public function css_link($file, $direct = FALSE) {
+    if (!$direct):
+      $file = $this->url("css/" . $file);
+    endif;
+    return "\n<link rel=\"stylesheet\" href=\"" . $file . "\" type=\"text/css\" media=\"screen,print,projection\" />\n";
+  }
+
+  public function custom_css_inject($direct) {
+    $_css = $this->custom_css_path;
+    if ($_css != ""):
+      $_fileonly = (stripos($_css, '/') === FALSE);
+
+      if ($_fileonly):
+        if (!$direct):
+          return $this->css($_css);
+        endif;
+      else:
+        if ($direct):
+          return $this->css_link($_css, TRUE);
+        endif;
+      endif;
+    else:
+      return "";
+    endif;
+  }
+
+  public function theme_js_inject() {
+    $js = "";
+    if ($this->show_root_page):
+      $js .= $this->script("jquery.cycle.js");
+    endif;
+//    $js .= $this->script("jquery.touchslider.js");
+    $js .= $this->script("ui.support.js");
+    return $js;
+  }
+
+  public function theme_css_inject() {
+    $css  = $this->css("screen.css");
+    $css .= $this->css("colors.css");
+    $css .= $this->css("frame.css");
+    $css .= $this->custom_css_inject(FALSE);
+    return $css;
+  }
+
+  public function credits() {
+    if (module::get_var("gallery", "show_credits")):
+      $version_string = SafeString::of_safe_html('Gallery ' . gallery::VERSION);
+      return '<ul id="g-credits">'
+        . '<li class="g-branding"><a id="g-gallery-logo" href="http://galleryproject.org" title="' . $version_string . '"></a>'
+        . '<a id="g-theme-logo" href="http://codex.galleryproject.org/Gallery3:Themes:greydragon" target="_blank" title="' . $this->themename . ' ' . $this->themeversion . ' (' . $this->colorpack . ')"></a></li>'
+        . gallery_theme::credits()
+        . '</ul>';
+    else:
+      return '';
+    endif;
+  }
+
+  // $mode: bit 1 - use mix mode ($mode in [1, 3]), bit 2 - strips bbcode ($mode in [2, 3])
+  public function bb2html($text, $mode) {
+    // Syntax Sample:
+    // --------------
+    // [img]http://elouai.com/images/star.gif[/img]
+    // [url="http://elouai.com"]eLouai[/url]
+    // [size="25"]HUGE[/size]
+    // [color="red"]RED[/color]
+    // [b]bold[/b]
+    // [i]italic[/i]
+    // [u]underline[/u]
+    // [list][*]item[*]item[*]item[/list]
+    // [code]value="123";[/code]
+    // [quote]John said yadda yadda yadda[/quote]
+  
+    static $bbcode_mappings = array(
+      "#\\[b\\](.*?)\\[/b\\]#" => "<strong>$1</strong>",
+      "#\\[i\\](.*?)\\[/i\\]#" => "<em>$1</em>",
+      "#\\[u\\](.*?)\\[/u\\]#" => "<u>$1</u>",
+      "#\\[s\\](.*?)\\[/s\\]#" => "<strike>$1</strike>",
+      "#\\[o\\](.*?)\\[/o\\]#" => "<overline>$1</overline>",
+      "#\\[url\\](.*?)\[/url\\]#" => "<a href=\"$1\">$1</a>",
+      "#\\[url=(.*?)\\](.*?)\[/url\\]#" => "<a href=\"$1\" target=\"_blank\">$2</a>",
+      "#\\[mail=(.*?)\\](.*?)\[/mail\\]#" => "<a href=\"mailto:$1\" target=\"_blank\">$2</a>",
+      "#\\[img\\](.*?)\\[/img\\]#" => "<img src=\"$1\" alt=\"\" />",
+      "#\\[img=(.*?)\\](.*?)\[/img\\]#" => "<img src=\"$1\" alt=\"$2\" />",
+      "#\\[quote\\](.*?)\\[/quote\\]#" => "<blockquote><p>$1</p></blockquote>",
+      "#\\[code\\](.*?)\\[/code\\]#" => "<pre>$1</pre>",
+      "#\\[size=([^\\[]*)\\]([^\\[]*)\\[/size\\]#" => "<span style=\"font-size: $1;\">$2</span>",
+      "#\\[color=([^\\[]*)\\]([^\\[]*)\\[/color\\]#" => "<span style=\"color: $1;\">$2</span>",
+      "#\\[class=([^\\[]*)\\]([^\\[]*)\\[/class\\]#" => "<span class=\"$1\">$2</span>",
+      "#\\[center\\](.*?)\\[/center\\]#" => "<div style=\"text-align: center;\">$1</div>",
+      "#\\[list\\](.*?)\\[/list\\]#" => "<ul>$1</ul>",
+      "#\\[ul\\](.*?)\\[/ul\\]#" => "<ul>$1</ul>",
+      "#\\[li\\](.*?)\\[/li\\]#" => "<li>$1</li>",
+    );
+  
+    static $bbcode_strip = '|[[\/\!]*?[^\[\]]*?]|si'; 
+
+    if (($mode == 1) or ($mode == 3)):
+      $newtext = str_replace("&lt;", "<", $text); 
+      $newtext = str_replace("&gt;", ">", $newtext); 
+      $newtext = str_replace("&quot;", "\"", $newtext); 
+    else:
+      // Replace any html brackets with HTML Entities to prevent executing HTML or script 
+      $newtext = str_replace("<", "&lt;", $text); 
+      $newtext = str_replace(">", "&gt;", $newtext); 
+      $newtext = str_replace("&amp;quot;", "&quot;", $newtext); 
+    endif;
+
+    // Convert new line chars to html <br /> tags 
+    $newtext = nl2br($newtext);  
+
+    if (strpos($text, "[") !== false):
+      if (($mode == 2) or ($mode == 3)):
+        $newtext = preg_replace($bbcode_strip, '', $newtext);
+      else:
+        $newtext = preg_replace(array_keys($bbcode_mappings), array_values($bbcode_mappings), $newtext);
+      endif;
+    endif;
+
+    return stripslashes($newtext);  //stops slashing, useful when pulling from db
+  }
+
+  function curl_get_file_contents($url) {
+    $curl = curl_init();
+    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+    curl_setopt($curl, CURLOPT_URL, $url);
+    $contents = curl_exec($curl);
+    curl_close($curl);
+ 
+    if ($contents):
+      return $contents;
+    else:
+      return FALSE;
+    endif;
+  }
+
+  function valid_url($str) {
+    return ( ! preg_match('/^(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i', $str)) ? FALSE : TRUE;
+  }
+
+  function get_slideshow_list($limit = 10) {
+    if( ! function_exists('simplexml_load_string'))
+      throw new Kohana_User_Exception('Feed Error', 'SimpleXML must be installed!');
+
+    $items = array();
+    $host = 'http://' . $_SERVER['SERVER_NAME'] . '/';
+
+    $feed_url = $this->root_feed;
+    if (!$this->valid_url($feed_url)):
+      $feed_url = $host . $feed_url;
+    endif;
+
+    $use_file_load = ($this->valid_url($feed_url)) || is_file($feed_url); 
+
+    $er = error_reporting(0);
+    // Try to get feed directly
+    try {
+      try {
+        if ($use_file_load):
+          $feed = simplexml_load_file($feed_url, 'SimpleXMLElement', LIBXML_NOCDATA);
+        else:
+          $feed = simplexml_load_string($feed_url, 'SimpleXMLElement', LIBXML_NOCDATA);
+        endif;
+      } catch (Exception $e) {
+      }
+    } catch (Exception $e) {
+    };
+
+    if (isset($feed) && ($feed)):
+      // Direct load worked fine
+    else:
+      // Direct load did not work, let's try CURL (URL file-access is disabled ?)
+      try {
+        $file = $this->curl_get_file_contents($feed_url);
+        if ($file):
+          $feed = simplexml_load_string($file, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
+        endif;
+      } catch (Exception $e) {
+      };
+    endif;
+    error_reporting($er);
+
+    if (isset($feed) && ($feed)):
+      $feed = isset($feed->channel) ? $feed->channel->xpath("//media:content[contains(@url, 'var/resizes')]") : array();
+      $i = 0;
+      foreach ($feed as $item):
+        if ($limit > 0 AND $i++ === $limit)
+          break;
+        $items[] = (array) $item;
+      endforeach;
+    endif;
+    return $items;
+  }
+}
+
+?>
diff --git a/themes/greydragon/theme.info b/themes/greydragon/theme.info
new file mode 100644
index 0000000..e8467c4
--- /dev/null
+++ b/themes/greydragon/theme.info
@@ -0,0 +1,10 @@
+name        = "Grey Dragon Theme"
+description = "A Crisp flexible theme with support of Color Packs and minimized on JS overhead"
+version     = 4.0.2
+author      = "2010-2014 Serguei Dosyukov"
+site        = 1
+admin       = 0
+author_name = "Serguei Dosyukov"
+author_url  = "http://blog.dragonsoft.us/gallery-3/"
+info_url    = "http://codex.galleryproject.org/Gallery3:Themes:greydragon";
+discuss_url = "http://galleryproject.org/forum_theme_greydragon"
diff --git a/themes/greydragon/thumbnail.png b/themes/greydragon/thumbnail.png
new file mode 100644
index 0000000..4b80eca
Binary files /dev/null and b/themes/greydragon/thumbnail.png differ
diff --git a/themes/greydragon/views/album.html.php b/themes/greydragon/views/album.html.php
new file mode 100644
index 0000000..ee3da0e
--- /dev/null
+++ b/themes/greydragon/views/album.html.php
@@ -0,0 +1,68 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<div id="g-album-header">
+  <?= $theme->album_top() ?>
+  <h1><?= $theme->get_item_title($item, TRUE) ?></h1>
+</div>
+
+<?= $theme->add_paginator("top"); ?>
+
+<? if (($theme->album_descmode == "top") and ($item->description)): ?>
+  <div id="g-info"><div class="g-description"><?= $theme->bb2html(html::purify($item->description), 1); ?></div></div>
+<? endif; ?>
+
+<div class="g-album-grid-container">
+<ul id="g-album-grid">
+<?
+  if (count($children)):
+    $siblings = $item->children();
+    if (($theme->disablephotopage) && (count($siblings) > count($children))):
+      $j = 0;
+      foreach ($siblings as $i => $sibling):
+        if ($sibling->rand_key == $children[$j]->rand_key):
+          echo $theme->get_thumb_element($sibling, !$theme->hidecontextmenu);
+          if ($j + 1 < count($children)):
+            $j++;
+          endif;
+        else:
+          echo $theme->get_thumb_link($sibling);
+        endif;
+      endforeach;
+    else:         
+      foreach ($children as $i => $child):
+        echo $theme->get_thumb_element($child, !$theme->hidecontextmenu);
+      endforeach;
+    endif;
+  else:
+    if ($user->admin || access::can("add", $item)):
+      $addurl = url::site("uploader/index/$item->id"); ?>
+      <li><?= t("There aren't any photos here yet! <a %attrs>Add some</a>.", array("attrs" => html::mark_clean("href=\"$addurl\" class=\"g-dialog-link\""))) ?></li>
+    <? else: ?>
+      <li><?= t("There aren't any photos here yet!") ?></li>
+    <? endif; ?>
+<? endif; ?>
+</ul>
+</div>
+
+<? if (($theme->album_descmode == "bottom") and ($item->description)): ?>
+  <div id="g-info"><div class="g-description"><?= $theme->bb2html(html::purify($item->description), 1) ?></div></div>
+<? endif; ?>
+<?= $theme->album_bottom() ?>
+
+<?= $theme->add_paginator("bottom"); ?>
diff --git a/themes/greydragon/views/block.html.php b/themes/greydragon/views/block.html.php
new file mode 100644
index 0000000..9dc2d60
--- /dev/null
+++ b/themes/greydragon/views/block.html.php
@@ -0,0 +1,29 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<? if ($anchor): ?>
+<a name="<?= $anchor ?>"></a>
+<? endif ?>
+<div id="<?= $css_id ?>" class="g-block">
+  <? if (isset($theme) and ($theme->is_blockheader_visible)): ?>
+  <h2><?= $title ?></h2>
+  <? endif ?>
+  <div class="g-block-content">
+    <?= $content ?>
+  </div>
+</div>
diff --git a/themes/greydragon/views/calpage.html.php b/themes/greydragon/views/calpage.html.php
new file mode 100644
index 0000000..3bcd0df
--- /dev/null
+++ b/themes/greydragon/views/calpage.html.php
@@ -0,0 +1,257 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<!DOCTYPE html >
+<? $theme->load_sessioninfo(); ?>
+<html <?= $theme->html_attributes() ?> xml:lang="en" lang="en" <?= ($theme->is_rtl)? "dir=rtl" : null; ?> >
+<?
+  $item = $theme->item();
+  if (($theme->enable_pagecache) and (isset($item))):
+    // Page will expire in 60 seconds
+    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 60).'GMT');  
+    header("Cache-Control: public");
+    header("Cache-Control: post-check=3600, pre-check=43200", false);
+    header("Content-Type: text/html; charset=UTF-8");
+    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
+  endif;
+?>
+<!-- <?= $theme->themename ?> v.<?= $theme->themeversion ?> (<?= $theme->colorpack ?> : <?= $theme->framepack ?>) - Copyright (c) 2009-2012 Serguei Dosyukov - All Rights Reserved -->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<? $theme->start_combining("script,css") ?>
+<? if ($page_title): ?>
+<?   $_title = $page_title ?> 
+<? else: ?>
+<?   if ($theme->item()): ?>
+<?     $_title = $theme->get_item_title($theme->item()); ?>
+<?   elseif ($theme->tag()): ?>
+<?     $_title = t("Photos tagged with %tag_title", array("tag_title" => $theme->bb2html($theme->tag()->name, 2))) ?>
+<?   else: /* Not an item, not a tag, no page_title specified.  Help! */ ?>
+<?     $_title = $theme->bb2html(item::root()->title, 2); ?>
+<?   endif ?>
+<? endif ?>
+<title><?= $_title ?></title>
+<? if ($theme->disable_seosupport): ?>
+<meta name="robots" content="noindex, nofollow, noarchive" />
+<meta name="googlebot" content="noindex, nofollow, noarchive, nosnippet, noodp, noimageindex, notranslate" />
+<meta name="slurp" content="noindex, nofollow, noarchive, nosnippet, noodp, noydir" />
+<meta name="msnbot" content="noindex, nofollow, noarchive, nosnippet, noodp" />
+<meta name="teoma" content="noindex, nofollow, noarchive" />
+<? endif; ?>
+<!-- Internet Explorer 9 Meta tags : Start -->
+<meta name="application-name" content="<?= $_title; ?>" />
+<meta name="msapplication-tooltip" content="<?= t("Start"); ?> <?= $_title; ?>" />
+<meta name="msapplication-starturl" content="<?= item::root()->url() ?>" />
+<? if ($theme->allow_root_page): ?>
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Page") ?>; action-uri=<?= item::root()->url(); ?><?= $theme->permalinks["root"]; ?>; icon-uri=favicon.ico" />
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Album") ?>; action-uri=<?= item::root()->url(); ?><?= $theme->permalinks["enter"]; ?>; icon-uri=favicon.ico" />
+<? else: ?>
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Album") ?>; action-uri=<?= item::root()->url(); ?>; icon-uri=favicon.ico" />
+<? endif; ?>
+<? if (identity::active_user()->admin): ?>
+<meta name="msapplication-task-separator" content="gallery3-greydragon" />
+<meta name="msapplication-task" content="name=<?= t("Admin") ?>: <?= t("Dashboard") ?>; action-uri=<?= url::site("admin"); ?>; icon-uri=favicon.ico" />
+<? endif; ?>
+<!-- Internet Explorer 9 Meta tags : End -->
+
+<link rel="shortcut icon" href="<?= $theme->favicon ?>" type="image/x-icon" />
+<? if ($theme->appletouchicon): ?>
+<link rel="apple-touch-icon" href="<?= $theme->appletouchicon; ?>"/>
+<? endif; ?>
+<?= $theme->script("json2-min.js") ?>
+<?= $theme->script("jquery.js") ?>
+<?= $theme->script("jquery.form.js") ?>
+<?= $theme->script("jquery-ui.js") ?>
+<?= $theme->script("gallery.common.js") ?>
+<? /* MSG_CANCEL is required by gallery.dialog.js */ ?>
+<script type="text/javascript">
+  var MSG_CANCEL = <?= t('Cancel')->for_js() ?>;
+</script>
+<?= $theme->script("gallery.ajax.js"); ?>
+<?= $theme->script("gallery.dialog.js"); ?>
+
+<? /* These are page specific but they get combined */ ?>
+<? if ($theme->page_subtype == "photo"): ?>
+<?=  $theme->script("jquery.scrollTo.js"); ?>
+<? elseif ($theme->page_subtype == "movie"): ?>
+<?=  $theme->script("flowplayer.js") ?>
+<? endif ?>
+
+<?= $theme->head() ?>
+
+<? // Theme specific CSS/JS goes last so that it can override module CSS/JS ?>
+<?= $theme->theme_js_inject(); ?>
+<?= $theme->theme_css_inject(); ?>
+<?= $theme->get_combined("css");          // LOOKING FOR YOUR CSS? It's all been combined into the link ?>
+<?= $theme->custom_css_inject(TRUE); ?>
+<?= $theme->get_combined("script")        // LOOKING FOR YOUR JAVASCRIPT? It's all been combined into the link ?>
+
+<? if ($theme->thumb_inpage): ?>
+<style type="text/css"> 
+  #g-column-bottom #g-thumbnav-block, #g-column-top #g-thumbnav-block { display: none; } 
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position == "bar")): ?>
+  html { margin-top: 30px !important; }
+<? endif; ?>
+</style>
+<? endif; ?>
+</head>
+<? if ($theme->item()):
+     $item = $theme->item();
+   else:
+     $item = item::root();
+   endif; ?>                             
+<body <?= $theme->body_attributes() ?><?= ($theme->show_root_page)? ' id="g-rootpage"' : null; ?> <?= $theme->get_bodyclass(); ?>>
+<?= $theme->page_top() ?>
+<?= $theme->site_status() ?>
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position == "bar")): ?>
+  <div id="g-site-menu" class="g-<?= $theme->mainmenu_position; ?>">
+  <?= $theme->site_menu($theme->item() ? "#g-item-id-{$theme->item()->id}" : "") ?>
+  </div>
+<? endif; ?>
+<div id="g-header">
+  <?= $theme->header_top() ?>
+<? if ($theme->viewmode != "mini"): ?>
+<? if ($header_text = module::get_var("gallery", "header_text")): ?>
+<span id="g-header-text"><?=  $theme->bb2html($header_text, 1) ?></span>
+<? else: ?>
+  <a id="g-logo" href="<?= item::root()->url() ?><?= ($theme->allow_root_page)? $theme->permalinks["root"] : null; ?>" title="<?= t("go back to the Gallery home")->for_html_attr() ?>">
+    <img alt="<?= t("Gallery logo: Your photos on your web site")->for_html_attr() ?>" src="<?= $theme->logopath ?>" />
+  </a>
+<?   endif; ?>
+<? endif; ?>
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position != "bar")): ?>
+  <div id="g-site-menu" class="g-<?= $theme->mainmenu_position; ?>">
+  <?= $theme->site_menu($theme->item() ? "#g-item-id-{$theme->item()->id}" : "") ?>
+  </div>
+<? endif ?>
+
+  <?= $theme->messages() ?>
+<?= $theme->header_bottom() ?>
+
+<? if ($theme->loginmenu_position == "header"): ?>
+  <?= $theme->user_menu() ?>
+<? endif ?>
+<? if (empty($parents)): ?>
+<?= $theme->breadcrumb_menu($theme, null); ?>
+<? else: ?>
+    <?= $theme->breadcrumb_menu($theme, $parents); ?>
+  <? endif; ?>
+<?= $theme->custom_header(); ?>
+</div>
+<? if (($theme->page_subtype != "login") and ($theme->page_subtype != "reauthenticate") and ($theme->sidebarvisible == "top")): ?>
+<div id="g-column-top">
+  <?= new View("sidebar.html") ?>
+</div>
+<? endif; ?>
+<div id="g-main">
+  <div id="g-main-in">
+    <? if (!$theme->show_root_page): ?>
+    <?= $theme->sidebar_menu($item->url()) ?>
+    <div id="g-view-menu" class="g-buttonset<?= ($theme->sidebarallowed!="any")? " g-buttonset-shift" : null; ?>">
+    <? if ($page_subtype == "album"):?>
+      <?= $theme->album_menu() ?>
+    <? elseif ($page_subtype == "photo") : ?>
+      <?= $theme->photo_menu() ?>
+    <? elseif ($page_subtype == "movie") : ?>
+      <?= $theme->movie_menu() ?>
+    <? elseif ($page_subtype == "tag") : ?>
+      <?= $theme->tag_menu() ?>
+    <? endif ?>
+    </div>
+    <? endif; ?>
+  <? switch ($theme->sidebarvisible):
+       case "left":
+         echo '<div id="g-column-left">';
+         $closediv = TRUE;
+         break;
+       case "none":
+     case "top":
+       case "bottom":
+         if (($theme->thumb_inpage) and ($page_subtype == "photo")):
+           echo '<div id="g-column-right">';
+           $closediv = TRUE;
+         else:
+           $closediv = FALSE;
+         endif;
+         break;
+       default:
+         echo '<div id="g-column-right">';
+         $closediv = TRUE;
+         break;
+   endswitch; ?>
+<? if (($theme->page_subtype != "login") and ($theme->page_subtype != "reauthenticate")): ?>
+<?   if (($theme->sidebarvisible == "none") or ($theme->sidebarvisible == "bottom") or ($theme->sidebarvisible == "top")): ?>
+<?     if (($theme->thumb_inpage) and ($page_subtype == "photo")): ?>
+<?=      '<div class="g-toolbar"><h1>&nbsp;</h1></div>'; ?>
+<?=      $theme->get_block_html("thumbnav"); ?>
+<?     endif; ?>
+<?   else: ?>
+<?=    new View("sidebar.html") ?>
+<?   endif; ?>
+<? endif ?>
+<?= ($closediv)? "</div>" : null; ?>
+
+<? switch ($theme->sidebarvisible):
+     case "left":
+       echo '<div id="g-column-centerright">';
+       break;
+     case "none":
+     case "top":
+     case "bottom":
+       if (($theme->thumb_inpage) and ($page_subtype == "photo")):
+         echo '<div id="g-column-centerleft">';
+       else:
+         echo '<div id="g-column-centerfull">';
+       endif;
+       break;
+     default:
+       echo '<div id="g-column-centerleft">';
+       break;
+   endswitch;
+
+   if ($theme->show_root_page):
+     echo new View("rootpage.html");
+   else:
+     echo $content;
+   endif; ?>
+    </div> 
+  </div>
+</div>
+<? if (($theme->page_subtype != "login") and ($theme->page_subtype != "reauthenticate") and ($theme->sidebarvisible == "bottom")): ?>
+<div id="g-column-bottom">
+  <?= new View("sidebar.html") ?>
+</div>
+<? endif; ?>
+<div id="g-footer">
+<? if ($theme->viewmode != "mini"): ?>
+<?= $theme->footer() ?>
+<? if ($footer_text = module::get_var("gallery", "footer_text")): ?>
+<span id="g-footer-text"><?=  $theme->bb2html($footer_text, 1) ?></span>
+<? endif ?>
+  <?= $theme->credits() ?>
+  <ul id="g-footer-rightside"><li><?= $theme->copyright ?></li></ul>
+<? if ($theme->loginmenu_position == "default"): ?>
+  <?= $theme->user_menu() ?>
+<?   endif; ?>
+<? endif; ?>
+<?= $theme->custom_footer(); ?>
+</div>
+<?= $theme->page_bottom() ?>
+</body>
+</html>
diff --git a/themes/greydragon/views/dynamic.html.php b/themes/greydragon/views/dynamic.html.php
new file mode 100644
index 0000000..4e328ef
--- /dev/null
+++ b/themes/greydragon/views/dynamic.html.php
@@ -0,0 +1,38 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<? if (!isset($title)):
+    $title = "";
+   endif;
+?>
+<div id="g-album-header">
+  <div id="g-album-header-buttons">
+    <?= $theme->dynamic_top() ?>
+  </div>
+  <h1><?= html::clean($title) ?></h1>
+</div>
+<?= $theme->add_paginator("top"); ?>
+<div class="g-album-grid-container">
+<ul id="g-album-grid">
+  <? foreach ($children as $i => $child): ?>
+    <?= $theme->get_thumb_element($child) ?>
+  <? endforeach ?>
+</ul>
+</div>
+<?= $theme->dynamic_bottom() ?>
+<?= $theme->add_paginator("bottom"); ?>
diff --git a/themes/greydragon/views/exif_sidebar.html.php b/themes/greydragon/views/exif_sidebar.html.php
new file mode 100644
index 0000000..5c84caf
--- /dev/null
+++ b/themes/greydragon/views/exif_sidebar.html.php
@@ -0,0 +1,18 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
diff --git a/themes/greydragon/views/info_block.html.php b/themes/greydragon/views/info_block.html.php
new file mode 100644
index 0000000..d323784
--- /dev/null
+++ b/themes/greydragon/views/info_block.html.php
@@ -0,0 +1,29 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<? if (array_key_exists("description", $metadata)): ?>
+<?   $metadata["description"]["value"] = $theme->bb2html($metadata["description"]["value"], 1) ?>
+<? endif; ?>
+
+<ul class="g-metadata">
+  <? foreach($metadata as $info): ?>
+  <li>
+    <strong class="caption"><?= $info["label"] ?></strong> <?= $info["value"] ?>
+  </li>
+  <? endforeach; ?>
+</ul>
diff --git a/themes/greydragon/views/login_ajax.html.php b/themes/greydragon/views/login_ajax.html.php
new file mode 100644
index 0000000..d62f31e
--- /dev/null
+++ b/themes/greydragon/views/login_ajax.html.php
@@ -0,0 +1,10 @@
+<div id="fam-login">
+  <p id="fam-login-header" style="background-image: url('<?= $theme->logopath ?>')"></p>
+  <?= $form; ?>
+</div>
+
+<script type="text/javascript">
+  $("#fam-login").ready(function() {
+    $("#g-username").focus();
+  });
+</script>
diff --git a/themes/greydragon/views/movie.html.php b/themes/greydragon/views/movie.html.php
new file mode 100644
index 0000000..92a6605
--- /dev/null
+++ b/themes/greydragon/views/movie.html.php
@@ -0,0 +1,38 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<div id="g-item">
+  <?= $theme->photo_top() ?>
+
+  <div id="g-info">
+    <h1><?= $theme->get_item_title($item, TRUE); ?></h1>
+    <div class="g-hideitem"><?= $theme->bb2html(html::purify($item->description), 1) ?></div>
+  </div>
+
+  <?= $theme->add_paginator("top", FALSE); ?>
+
+  <div id="g-movie">
+    <?= $theme->resize_top($item) ?>
+    <?=  $item->movie_img(array("class" => "g-movie", "id" => "g-item-id-{$item->id}")); ?>
+    <?= $theme->resize_bottom($item) ?>
+  </div>
+
+  <?= $theme->add_paginator("bottom", FALSE); ?>
+
+  <?= $theme->photo_bottom() ?>
+</div>
diff --git a/themes/greydragon/views/no_sidebar.html.php b/themes/greydragon/views/no_sidebar.html.php
new file mode 100644
index 0000000..751d8a4
--- /dev/null
+++ b/themes/greydragon/views/no_sidebar.html.php
@@ -0,0 +1,19 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<!-- No blocks -->
diff --git a/themes/greydragon/views/page.html.php b/themes/greydragon/views/page.html.php
new file mode 100644
index 0000000..a8949cb
--- /dev/null
+++ b/themes/greydragon/views/page.html.php
@@ -0,0 +1,267 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<!DOCTYPE html >
+<? $theme->load_sessioninfo(); ?>
+<html <?= $theme->html_attributes() ?> xml:lang="en" lang="en" <?= ($theme->is_rtl)? "dir=rtl" : null; ?> >
+<?
+  $item = $theme->item();
+  if (($theme->enable_pagecache) and (isset($item))):
+    // Page will expire in 60 seconds
+    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 60).'GMT');  
+    header("Cache-Control: public");
+    header("Cache-Control: post-check=3600, pre-check=43200", false);
+    header("Content-Type: text/html; charset=UTF-8");
+    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
+  endif;
+?>
+<!-- <?= $theme->themename ?> v.<?= $theme->themeversion ?> (<?= $theme->colorpack ?> : <?= $theme->framepack ?>) - Copyright (c) 2009-2014 Serguei Dosyukov - All Rights Reserved -->
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<? $theme->start_combining("script,css") ?>
+<? if ($page_title && $theme->page_subtype != "login"): ?>
+<?   $_title = $page_title ?> 
+<? else: ?>
+<?   if ($theme->item()): ?>
+<?     $_title = $theme->get_item_title($theme->item()); ?>
+<?   elseif ($theme->tag()): ?>
+<?     $_title = t("Photos tagged with %tag_title", array("tag_title" => $theme->bb2html($theme->tag()->name, 2))) ?>
+<?   else: /* Not an item, not a tag, no page_title specified.  Help! */ ?>
+<?     $_title = $theme->bb2html(item::root()->title, 2); ?>
+<?   endif ?>
+<? endif ?>
+<title><?= $_title ?></title>
+<meta name="title" content="<?= $_title ?>" /> 
+<? if ($theme->disable_seosupport): ?>
+<meta name="robots" content="noindex, nofollow, noarchive" />
+<meta name="googlebot" content="noindex, nofollow, noarchive, nosnippet, noodp, noimageindex, notranslate" />
+<meta name="slurp" content="noindex, nofollow, noarchive, nosnippet, noodp, noydir" />
+<meta name="teoma" content="noindex, nofollow, noarchive" />
+<? endif; ?>
+
+<!-- Internet Explorer 9 Meta tags : Start -->
+<meta name="application-name" content="<?= $_title; ?>" />
+<meta name="msapplication-tooltip" content="<?= t("Start"); ?> <?= $_title; ?>" />
+<meta name="msapplication-starturl" content="<?= item::root()->url() ?>" />                                                     
+<? if ($theme->allow_root_page): ?>
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Page") ?>; action-uri=<?= item::root()->url(); ?><?= $theme->permalinks["root"]; ?>; icon-uri=favicon.ico" />
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Album") ?>; action-uri=<?= item::root()->url(); ?><?= $theme->permalinks["enter"]; ?>; icon-uri=favicon.ico" />
+<? else: ?>
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Album") ?>; action-uri=<?= item::root()->url(); ?>; icon-uri=favicon.ico" />
+<? endif; ?>
+<? if (identity::active_user()->admin): ?>
+<meta name="msapplication-task-separator" content="gallery3-greydragon" />
+<meta name="msapplication-task" content="name=<?= t("Admin") ?>: <?= t("Dashboard") ?>; action-uri=<?= url::site("admin"); ?>; icon-uri=favicon.ico" />
+<? endif; ?>
+<!-- Internet Explorer 9 Meta tags : End -->
+<link rel="shortcut icon" href="<?= $theme->favicon ?>" type="image/x-icon" />
+<? if ($theme->appletouchicon): ?>
+<link rel="apple-touch-icon" href="<?= $theme->appletouchicon; ?>"/>
+<? endif; ?>
+
+<?= $theme->script("jquery.min.js"); ?>
+<?= $theme->script("jquery.json.min.js"); ?>
+<?= $theme->script("jquery.form.custom.js"); ?>
+<?= $theme->script("jquery-ui.min.js"); ?>
+
+<?= $theme->script("gallery.common.js") ?>
+<? /* MSG_CANCEL is required by gallery.dialog.js */ ?>
+<script type="text/javascript">
+  var MSG_CANCEL = <?= t('Cancel')->for_js() ?>;
+</script>
+
+<?= $theme->script("gallery.ajax.custom.js") ?>
+<?= $theme->script("gallery.dialog.custom.js"); ?>
+
+<? /* These are page specific but they get combined */ ?>
+<? if ($theme->page_subtype == "photo"): ?>
+<?=  $theme->script("jquery.scrollTo.js"); ?>
+<? elseif ($theme->page_subtype == "movie"): ?>
+<?=  $theme->script("flowplayer.js") ?>
+<? endif ?>
+
+<?= $theme->head() ?>
+
+<? // Theme specific CSS/JS goes last so that it can override module CSS/JS ?>
+<?= $theme->theme_js_inject(); ?>
+<?= $theme->theme_css_inject(); ?>
+<?= $theme->get_combined("css");          // LOOKING FOR YOUR CSS? It's all been combined into the link ?>
+<?= $theme->custom_css_inject(TRUE); ?>
+<?= $theme->get_combined("script")        // LOOKING FOR YOUR JAVASCRIPT? It's all been combined into the link ?>
+
+<? if ($theme->thumb_inpage): ?>
+<style type="text/css"> 
+  #g-column-bottom #g-thumbnav-block, #g-column-top #g-thumbnav-block { display: none; } 
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position == "bar")): ?>
+  html { margin-top: 30px !important; }
+<? endif; ?>
+</style>
+<? endif; ?>
+</head>
+<? if ($theme->item()):
+     $item = $theme->item();
+   else:
+     $item = item::root();
+   endif; ?>
+<? if ($theme->page_subtype != "login"): ?>
+<body>
+<? endif; ?>
+<? if ($theme->page_subtype != "login"): ?>
+<body <?= $theme->body_attributes() ?><?= ($theme->show_root_page)? ' id="g-rootpage"' : null; ?> <?= $theme->get_bodyclass(); ?>>
+<?= $theme->page_top() ?>                               
+<?= $theme->site_status() ?>
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position == "bar")): ?>
+  <div id="g-site-menu" class="g-<?= $theme->mainmenu_position; ?>">
+  <?= $theme->site_menu($theme->item() ? "#g-item-id-{$theme->item()->id}" : "") ?>
+  </div>
+<? endif; ?>
+<div id="g-header">
+<?= $theme->header_top() ?>
+<? if ($theme->viewmode != "mini"): ?>
+<?   if ($header_text = module::get_var("gallery", "header_text")): ?>
+<span id="g-header-text"><?=  $theme->bb2html($header_text, 1) ?></span>
+<?   else: ?>                                                                         
+  <a id="g-logo" href="<?= item::root()->url() ?><?= ($theme->allow_root_page)? $theme->permalinks["root"] : null; ?>" title="<?= t("go back to the Gallery home")->for_html_attr() ?>">
+    <img alt="<?= t("Gallery logo: Your photos on your web site")->for_html_attr() ?>" src="<?= $theme->logopath ?>" />
+  </a>
+<?   endif; ?>
+<? endif; ?>
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position != "bar")): ?>
+  <div id="g-site-menu" class="g-<?= $theme->mainmenu_position; ?>">
+  <?= $theme->site_menu($theme->item() ? "#g-item-id-{$theme->item()->id}" : "") ?>
+  </div>
+<? endif ?>
+
+<?= $theme->messages() ?>
+<?= $theme->header_bottom() ?>
+
+<? if ($theme->loginmenu_position == "header"): ?>
+<?=  $theme->user_menu() ?>
+<? endif; ?>
+<? if (empty($breadcrumbs)): ?>
+<?= $theme->breadcrumb_menu(null); ?>
+<? else: ?>
+<?= $theme->breadcrumb_menu($breadcrumbs); ?>
+<? endif; ?>
+<?= $theme->custom_header(); ?>
+</div>
+<? if (($theme->page_subtype != "login") and ($theme->page_subtype != "reauthenticate") and ($theme->sidebarvisible == "top")): ?>
+<div id="g-column-top">
+  <?= new View("sidebar.html") ?>
+</div>
+<? endif; ?>
+<div id="g-main">
+  <div id="g-main-in">
+<?  if (!$theme->show_root_page): ?>
+    <?= $theme->sidebar_menu($item->url()) ?>
+    <div id="g-view-menu" class="g-buttonset<?= ($theme->sidebarallowed != "any")? " g-buttonset-shift" : null; ?>">
+<?    if ($page_subtype == "album"): ?>
+      <?= $theme->album_menu() ?>
+<?    elseif ($page_subtype == "photo") : ?>
+      <?= $theme->photo_menu() ?>
+<?    elseif ($page_subtype == "movie") : ?>
+      <?= $theme->movie_menu() ?>
+<?    elseif ($page_subtype == "tag") : ?>
+      <?= $theme->tag_menu() ?>
+<?    endif ?>
+    </div>
+<?  endif; ?>
+<? switch ($theme->sidebarvisible):
+     case "left":
+       echo '<div id="g-column-left">';
+       $closediv = TRUE;
+       break;
+     case "none":
+     case "top":
+     case "bottom":
+       if (($theme->thumb_inpage) and ($page_subtype == "photo")):
+         echo '<div id="g-column-right">';
+         $closediv = TRUE;
+       else:
+         $closediv = FALSE;
+       endif;
+       break;
+     default:
+       echo '<div id="g-column-right">';
+       $closediv = TRUE;
+       break;
+   endswitch; ?>
+<? if (($theme->page_subtype != "login") && ($theme->page_subtype != "reauthenticate")): ?>
+<?   if (($theme->sidebarvisible == "none") || ($theme->sidebarvisible == "bottom") || ($theme->sidebarvisible == "top")): ?>
+<?     if (($theme->thumb_inpage) and ($page_subtype == "photo")): ?>
+<?=      '<div class="g-toolbar"><h1>&nbsp;</h1></div>'; ?>
+<?=      $theme->get_block_html("thumbnav"); ?>
+<?     endif; ?>
+<?   else: ?>
+<?=    new View("sidebar.html") ?>
+<?   endif; ?>
+<? endif ?>
+<?= ($closediv)? "</div>" : null; ?>
+
+<? switch ($theme->sidebarvisible):
+     case "left":
+       echo '<div id="g-column-centerright">';
+       break;
+     case "none":
+     case "top":
+     case "bottom":
+       if (($theme->thumb_inpage) and ($page_subtype == "photo")):
+         echo '<div id="g-column-centerleft">';
+       else:
+         echo '<div id="g-column-centerfull">';
+       endif;
+       break;
+     default:
+       echo '<div id="g-column-centerleft">';
+       break;
+   endswitch;
+
+   if ($theme->show_root_page):
+     echo new View("rootpage.html");
+   else:
+     echo $content;
+   endif; ?>
+    </div> 
+  </div>
+</div>
+<? if (($theme->page_subtype != "login") and ($theme->page_subtype != "reauthenticate") and ($theme->sidebarvisible == "bottom")): ?>
+<div id="g-column-bottom">
+  <?= new View("sidebar.html") ?>
+</div>
+<? endif; ?>
+<div id="g-footer">
+<? if ($theme->viewmode != "mini"): ?>
+<?=  $theme->footer() ?>
+<?   if ($footer_text = module::get_var("gallery", "footer_text")): ?>
+<span id="g-footer-text"><?=  $theme->bb2html($footer_text, 1) ?></span>
+<?   endif ?>
+  <?= $theme->credits() ?>
+  <ul id="g-footer-rightside"><li><?= $theme->copyright ?></li></ul>
+<?   if ($theme->loginmenu_position == "default"): ?>
+  <?= $theme->user_menu() ?>
+<?   endif; ?>
+<? endif; ?>
+<?= $theme->custom_footer(); ?>
+</div>
+<?= $theme->page_bottom() ?>
+<? else:
+  echo $content;
+  endif;
+?>
+</body>
+</html>
diff --git a/themes/greydragon/views/paginator.html.php b/themes/greydragon/views/paginator.html.php
new file mode 100644
index 0000000..912a537
--- /dev/null
+++ b/themes/greydragon/views/paginator.html.php
@@ -0,0 +1,216 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+// This is a generic paginator for album, photo and movie pages.  Depending on the page type,
+// there are different sets of variables available.  With this data, you can make a paginator
+// that lets you say "You're viewing photo 5 of 35", or "You're viewing photos 10 - 18 of 37"
+// for album views.
+//
+// Available variables for all page types:
+//   $page_type               - "collection", "item", or "other"
+//   $page_subtype            - "album", "movie", "photo", "tag", etc.
+//   $previous_page_url       - the url to the previous page, if there is one
+//   $next_page_url           - the url to the next page, if there is one
+//   $total                   - the total number of photos in this album
+//
+// Available for the "collection" page types:
+//   $page                    - what page number we're on
+//   $max_pages               - the maximum page number
+//   $page_size               - the page size
+//   $first_page_url          - the url to the first page, or null if we're on the first page
+//   $last_page_url           - the url to the last page, or null if we're on the last page
+//   $first_visible_position  - the position number of the first visible photo on this page
+//   $last_visible_position   - the position number of the last visible photo on this page
+//
+// Available for "item" page types:
+//   $position                - the position number of this photo
+//
+?>
+
+<?
+  $_pagelist = array();
+
+  // dynamic albums support - tag_albums module
+  if (isset($theme->dynamic_siblings)):
+    $current_page = $position;
+    $i = 1;
+    $total_pages = count($theme->dynamic_siblings);
+    foreach ($theme->dynamic_siblings as $one_sibling):
+      if ($page_type == "item"):
+        $_pagelist[$i] = url::site("tag_albums/show/" . $one_sibling->id . "/" . $tag_id . "/" . $album_id . "/" . urlencode($one_sibling->name));
+      endif;
+      $i++;
+    endforeach;
+  else:
+    switch ($page_type):
+      case "collection":
+        if (isset($item)):
+          $parent = $item->parent();
+        endif;
+        $current_page = $page;
+        $total_pages = $max_pages;
+        // Prepare page url list
+        for ($i = 1; $i <= $total_pages; $i++):
+          $_pagelist[$i] = url::site(url::merge(array("page" => $i)));
+        endfor;
+        break;
+      case "item":
+        if (isset($first_page_url)): // Good item collection
+          if (isset($item)):
+            $parent = $item->parent();
+          endif;
+  
+          if (isset($position)):
+            $current_page = $position; 
+          else:
+            $current_page = 1;
+          endif;
+
+          $total_pages = $total;
+          if (isset($parent)):
+            $siblings = $parent->children();
+            for ($i = 1; $i <= $total; $i++):
+              $sibling = $siblings[$i-1];
+              if (method_exists($sibling, 'url')):
+                $_pagelist[$i] = $sibling->url();
+              endif;
+            endfor;
+          endif;
+        else:   // "Bad" item collection - photo from tag based collection
+          $total_pages = 1;
+          $current_page = 1;
+        endif;
+        break;
+
+      default:
+        $current_page = 1;
+        $total_pages = 1;
+        $_pagelist[1] = url::site();
+        break;
+    endswitch;
+  endif;
+
+  if ($total_pages <= 1):
+    $pagination_msg = "&nbsp;";
+  else:
+    $pagination_msg = t("Page:") . ' ';
+    if ($total_pages < 13):
+      for ($i = 1; $i <= $total_pages; $i++):
+        if ($i == $current_page):
+          $pagination_msg .= '<span>' . t($i) . '</span>';
+        else:                                                                
+          $pagination_msg .= '<span><a href="' . $_pagelist[$i] . '" title="' . t("Page") . ' ' . t($i) . '">' . t($i) . '</a></span>';
+        endif;
+        if ($i < $total_pages):
+          $pagination_msg .= '&middot;'; 
+        endif;
+      endfor;
+    elseif ($current_page < 9):
+      for ($i = 1; $i <= 10; $i++):
+        if ($i == $current_page): 
+          $pagination_msg .= '<span>' . t($i) . '</span>';
+        else:
+          $pagination_msg .= '<span><a href="' . $_pagelist[$i] . '" title="' . t("Page") . ' ' . t($i) . '">' . t($i) . '</a></span>';
+        endif;
+        if ($i < 10):
+          $pagination_msg .= '&middot;'; 
+        endif;
+      endfor;
+      
+      $pagination_msg .= '&hellip;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[$total_pages - 1] . '" title="' . t("Page") . ' ' . t($total_pages - 1) . '">' . t($total_pages - 1) . '</a></span>';
+      $pagination_msg .= '&middot;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[$total_pages] . '" title="' . t("Page") . ' ' . t($total_pages) . '">' . t($total_pages) . '</a></span>';
+
+    elseif ($current_page > $total_pages - 8):
+      $pagination_msg .= '<span><a href="' . $_pagelist[1] . '" title="' . t("Page") . ' ' . t(1) . '">' . t(1) . '</a></span>';
+      $pagination_msg .= '&middot;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[2] . '" title="' . t("Page") . ' ' . t(2) . '">' . t(2) . '</a></span>';
+      $pagination_msg .= '&hellip;';
+
+      for ($i = $total_pages - 9; $i <= $total_pages; $i++):
+        if ($i == $current_page): 
+          $pagination_msg .= '<span>' . t($i) . '</span>';
+        else:
+          $pagination_msg .= '<span><a href="' . $_pagelist[$i] . '" title="' . t("Page") . ' ' . t($i) . '">' . t($i) . '</a></span>';
+        endif;
+        if ($i < $total_pages):
+          $pagination_msg .= '&middot;';
+        endif;
+      endfor;
+
+    else:
+      $pagination_msg .= '<span><a href="' . $_pagelist[1] . '" title="' . t("Page") . ' ' . t(1) . '">' . t(1) . '</a></span>';
+      $pagination_msg .= '&middot;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[2] . '" title="' . t("Page") . ' ' . t(2) . '">' . t(2) . '</a></span>';
+      $pagination_msg .= '&hellip;';
+
+      for ($i = $current_page - 5; $i <= $current_page + 5; $i++):
+        if ($i == $current_page): 
+          $pagination_msg .= '<span>' . t($i) . '</span>';
+        else:
+          $pagination_msg .= '<span><a href="' . $_pagelist[$i] . '" title="' . t("Page") . ' ' . t($i) . '">' . t($i) . '</a></span>';
+        endif;
+        if ($i < $current_page + 5):
+          $pagination_msg .= '&middot;';
+        endif;
+      endfor;
+
+      $pagination_msg .= '&hellip;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[$total_pages - 1] . '" title="' . t("Page") . ' ' . t($total_pages - 1) . '">' . t($total_pages - 1) . '</a></span>';
+      $pagination_msg .= '&middot;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[$total_pages] . '" title="' . t("Page") . ' ' . t($total_pages) . '">' . t($total_pages) . '</a></span>';
+    endif;
+  endif; 
+?>
+<ul class="g-paginator">
+  <li class="g-pagination"><?= $pagination_msg ?></li>   
+  <li class="g-navigation">
+  <? if ($current_page > 1): ?>
+    <a title="<?= t("first") ?>" id="g-navi-first" href="<?= $_pagelist[1] ?>"><span class="ui-icon ui-icon-first">&nbsp;</span></a>
+  <? else: ?>
+    <span class="ui-icon ui-icon-first-d">&nbsp;</span>
+  <? endif ?>
+
+  <? if (isset($previous_page_url)): ?>
+    <a title="<?= t("previous") ?>" id="g-navi-prev" href="<?= $previous_page_url ?>"><span class="ui-icon ui-icon-prev">&nbsp;</span></a>
+  <? else: ?>
+    <span class="ui-icon ui-icon-prev-d">&nbsp;</span>
+  <? endif ?>
+
+  <? if (count($theme->breadcrumbs) > 1): ?>
+    <? end($theme->breadcrumbs); ?>
+    <a title="<?= t("up") ?>" id="g-navi-parent" href="<?= prev($theme->breadcrumbs)->url; ?>"><span class="ui-icon ui-icon-parent">&nbsp;</span></a>
+  <? else: ?>
+    <span class="ui-icon ui-icon-parent-d">&nbsp;</span>
+  <? endif ?>
+
+  <? if (isset($next_page_url)): ?>
+    <a title="<?= t("next") ?>" class="ui-right" id="g-navi-next" href="<?= $next_page_url ?>"><span class="ui-icon ui-icon-next">&nbsp;</span></a>
+  <? else: ?>
+    <span class="ui-icon ui-icon-next-d">&nbsp;</span>
+  <? endif ?>
+
+  <? if ($current_page < $total_pages): ?>
+      <a title="<?= t("last") ?>" class="ui-right" id="g-navi-last" href="<?= $_pagelist[$total_pages] ?>"><span class="ui-icon ui-icon-last">&nbsp;</span></a>
+  <? else: ?>
+    <span class="ui-icon ui-icon-last-d">&nbsp;</span>
+  <? endif ?>
+  </li>
+</ul>
\ No newline at end of file
diff --git a/themes/greydragon/views/photo.html.php b/themes/greydragon/views/photo.html.php
new file mode 100644
index 0000000..1d2354e
--- /dev/null
+++ b/themes/greydragon/views/photo.html.php
@@ -0,0 +1,129 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+  if ($theme->desc_allowbbcode):
+    $_description = $theme->bb2html($item->description, 1);
+  else:
+    $_description = nl2br(html::purify($item->description));
+  endif;
+
+  if ($theme->is_photometa_visible):
+    $_description .= '<ul class="g-metadata">' . $theme->thumb_info($item) . '</ul>';
+  endif;
+
+  switch ($theme->photo_popupbox):
+    case "preview":
+      $include_list = FALSE;
+      $include_single = TRUE;
+      break;
+    case "none":
+      $include_list = FALSE;
+      $include_single = FALSE;
+      break;
+    default:
+      $include_list = TRUE;
+      $include_single = TRUE;
+      break;
+  endswitch;
+?>  
+
+<div id="g-item">
+  <? $_title = $theme->get_item_title($item, TRUE); ?>
+  <div id="g-info">
+    <h1><?= $_title ?></h1>
+  </div>
+  <?= $theme->add_paginator("top", FALSE); ?>
+  <?= $theme->photo_top() ?>
+  <? if (($theme->photo_descmode == "top") and ($_description)): ?>
+    <div id="g-info"><div class="g-description"><?= $_description ?></div></div>
+  <? endif; ?>
+  <div id="g-photo">
+    <?= $theme->resize_top($item) ?>
+    <? $_resizewidth = $item->resize_width;
+       if (isset($theme->dynamic_siblings)) {
+         $siblings = $theme->dynamic_siblings;
+       } else {
+         $siblings = $item->parent()->children(); 
+       }
+    ?>
+    <div class="g-resize" style="margin-left: -<?= intval($_resizewidth / 2); ?>px; ">
+    <? $script  = "<script type=\"text/javascript\">\n";
+       $script .= "$(document).ready(function() {\n";
+       $script .= "  if (document.images) {\n";
+       for ($i = 0; ($i <= count($siblings) - 1); $i++):
+         if ($siblings[$i]->rand_key == $item->rand_key): ?>
+           <a style="<?= ($siblings[$i]->rand_key == $item->rand_key)? "display: static;" : "display: none;"; ?>" title="<?= $theme->get_item_title($item); ?>" <?= ($include_single)? "class=\"g-sb-preview\"" : "target=_blank;"; ?> <?= ($include_list)? "rel=\"g-preview\"" : null; ?> href="<?= (access::can("view_full", $item))? $item->file_url() : $item->resize_url(); ?>">
+           <?= $item->resize_img(array("id" => "g-item-id-{$item->id}", "class" => "g-resize", "alt" => $_title)) ?>
+           </a>
+      <?  if (($i < count($siblings) - 1) && (!$siblings[$i+1]->is_album())):
+            $script  .= "    var image_preload_n = new Image();\n    image_preload_n.src = \"" . $siblings[$i+1]->resize_url() . "\";\n"; 
+          endif;
+          if (($i > 0) && (!$siblings[$i-1]->is_album())):
+            $script  .= "    var image_preload_p = new Image();\n    image_preload_p.src = \"" . $siblings[$i-1]->resize_url() . "\";\n"; 
+          endif;
+        else:
+        if ($include_list): ?>
+          <? if (!$siblings[$i]->is_album()): ?>
+          <a title="<?= $theme->get_item_title($siblings[$i]); ?>" class="g-sb-preview g-hide" rel="g-preview" href="<?= (access::can("view_full", $siblings[$i]))? $siblings[$i]->file_url() : $siblings[$i]->resize_url(); ?>">&nbsp;</a>
+          <? endif; ?>  
+        <? endif; ?>
+      <? endif; ?>
+    <? endfor; ?>
+    <? $script  .= "  }\n});\n</script>\n"; ?>
+    <? $_align = "";
+       $_more = FALSE;
+       if ($_description):
+         switch ($theme->photo_descmode):
+           case "overlay_top":
+             $_align = "g-align-top";
+             $_more = TRUE;
+             break;
+           case "overlay_bottom":
+             $_align = "g-align-bottom";
+             $_more = TRUE;
+             break;
+           case "overlay_top_s":
+             $_align = "g-align-top g-align-static";
+             break;
+           case "overlay_bottom_s":
+             $_align = "g-align-bottom g-align-static";
+             break;
+           default:
+             break;
+         endswitch;
+       endif; ?>
+  <?  if ($_align): ?>
+    <?  if ($_more): ?>
+      <span class="g-more <?= $_align ?>"><?= t("More") ?></span>
+    <? endif ?>
+      <div class="g-description <?= $_align; ?>" style="width: <?= $_resizewidth - 20; ?>px;" >
+        <strong><?= $_title ?></strong>
+        <?= $_description ?>
+      </div>
+    <? endif ?>
+    </div>
+    <?= $theme->resize_bottom($item) ?>
+  </div>
+  <? if (($theme->photo_descmode == "bottom") and ($_description)): ?>
+    <div id="g-info"><div class="g-description"><?= $_description ?></div></div>
+  <? endif; ?>
+  <?= $theme->add_paginator("bottom", FALSE); ?>
+  <?= $theme->photo_bottom() ?>
+</div>
+<?= $script ?>
\ No newline at end of file
diff --git a/themes/greydragon/views/rootpage.html.php b/themes/greydragon/views/rootpage.html.php
new file mode 100644
index 0000000..c474ac7
--- /dev/null
+++ b/themes/greydragon/views/rootpage.html.php
@@ -0,0 +1,59 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<? 
+  $link_url = item::root()->url();
+  if ($theme->allow_root_page):            
+    $link_url .= $theme->permalinks["enter"];
+  endif;
+  if ($theme->show_root_desc):
+    if ($theme->root_description):
+      $root_text = $theme->root_description;
+    elseif (isset($item)):
+      $root_text = $item->description;
+    endif;
+    if ($root_text): 
+      ?><div id="g-rootpage-quote"><?= $theme->bb2html($root_text, 1); ?></div><?
+    endif; 
+  endif;
+
+  $slideshow_list = $theme->get_slideshow_list();
+  $first = TRUE;
+?>
+<div id="g-rootpage-roll"<?= ($root_text)? null : ' class="g-full"'; ?>>
+  <span><a href="<?= $link_url ?>"><?= t("Click to Enter") ?></a></span>
+  <div id="g-rootpage-slideshow">
+    <? foreach ($slideshow_list as $entry): ?>
+      <? $attr = $entry["@attributes"]; ?>
+    <div class="slider-item" style="width: <?= $attr['width']; ?>px; height: <?= $attr["height"]; ?>px; display: <?= ($first)? "block" : "none"; ?>; position: absolute; z-index: 10; opacity: <?= ($first)? "1" : "0"; ?>;">
+      <a href="<?= $link_url; ?>"><img width="<?= $attr["width"]; ?>" height="<?= $attr["height"]; ?>" alt="" src="<?= $attr["url"]; ?>" /></a>
+    </div>
+      <? $first = FALSE; ?>
+    <? endforeach ?>
+  </div>  
+</div>
+<? if (count($slideshow_list) > 0): ?>
+<script type="text/javascript">
+  $(document).ready(function() {
+    $('#g-rootpage-slideshow').cycle({
+        fx: '<?= $theme->root_cyclemode; ?>'
+      , timeout: <?= $theme->root_delay * 1000; ?>
+    });
+  });
+</script>
+<? endif; ?>
\ No newline at end of file
diff --git a/themes/greydragon/views/rootpage.html.php_fix b/themes/greydragon/views/rootpage.html.php_fix
new file mode 100644
index 0000000..4d082a5
--- /dev/null
+++ b/themes/greydragon/views/rootpage.html.php_fix
@@ -0,0 +1,46 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<? 
+  $link_url = item::root()->url();
+  if ($theme->allow_root_page):
+    $link_url .= $theme->permalinks["enter"];
+  endif;
+  if ($theme->show_root_desc):
+    if ($theme->root_description):
+      $root_text = $theme->root_description;
+    elseif (isset($item)):
+      $root_text = $item->description;
+    endif;
+    if ($root_text): 
+      ?><div id="g-rootpage-quote"><?= $theme->bb2html($root_text, 1); ?></div><?
+    endif; 
+  endif;
+?>
+<div id="g-rootpage-roll"<?= ($root_text)? null : ' class="g-full"'; ?>>
+<object type="application/x-shockwave-flash" data="<?= url::file("modules/imageblockex/player/minislideshow.swf"); ?>" width="100%" height="100%">
+<param name="movie" value="<?= url::file("modules/imageblockex/player/minislideshow.swf"); ?>" />
+<param name="FlashVars" value="xmlUrl=<?= $theme->root_feed; ?>&amp;delay=<?= $theme->root_delay; ?>&amp;showControls=false&amp;altLink=<?= $link_url ?>&amp;showDropShadow=true&amp;useResizes=true&amp;useFull=true&amp;showLoader=false" />
+<param name="bgcolor" value="#1c242e" />
+<param name="wmode" value="transparent" />
+<param name="menu" value="false" />
+<param name="quality" value="high" />
+</object>
+<div id="g-rootpage-link" onclick="javascript:location='<?= $link_url ?>'" ></div>
+<span><a href="<?= $link_url ?>"><?= t("Click to Enter") ?></a></span>
+</div>
diff --git a/themes/greydragon/views/rss_block.html.php b/themes/greydragon/views/rss_block.html.php
new file mode 100644
index 0000000..85f3111
--- /dev/null
+++ b/themes/greydragon/views/rss_block.html.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<ul id="g-feeds">
+<? foreach($feeds as $url => $title): ?>
+  <li style="clear: both;">
+    <span class="ui-icon-left">
+    <a href="<?= rss::url($url) ?>">
+      <span class="ui-icon ui-icon-signal-diag">&nbsp;</span>
+      <?= html::purify($title) ?>
+    </a>
+    </span>
+  </li>
+<? endforeach ?>
+</ul>
diff --git a/themes/greydragon/views/search.html.php b/themes/greydragon/views/search.html.php
new file mode 100644
index 0000000..3d82379
--- /dev/null
+++ b/themes/greydragon/views/search.html.php
@@ -0,0 +1,35 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<div id="g-search-results">
+  <h1><?= t("Search Results for \"%term\"", array("term" => $q)) ?> </h1>
+
+  <?= $theme->add_paginator("top"); ?>
+  <div class="g-album-grid-container">
+  <ul id="g-album-grid">
+<? if (count($items)): ?>
+    <? foreach ($items as $item): ?>
+      <?= $theme->get_thumb_element($item) ?>
+    <? endforeach ?>
+<? else: ?>
+  <li><?= t("No results found for <b>%term</b>", array("term" => $q)) ?></li>
+<? endif; ?>
+  </ul>
+  </div>
+  <?= $theme->add_paginator("bottom"); ?>
+</div>
\ No newline at end of file
diff --git a/themes/greydragon/views/sidebar.html.php b/themes/greydragon/views/sidebar.html.php
new file mode 100644
index 0000000..635fbd5
--- /dev/null
+++ b/themes/greydragon/views/sidebar.html.php
@@ -0,0 +1,27 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2014 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?= $theme->sidebar_top() ?>
+<div class="g-toolbar"><h1>&nbsp;</h1></div>
+<? if ((!$user->guest) || (!$theme->sidebar_hideguest)):
+     try { echo $theme->sidebar_blocks(); } catch (Exception $e) { } 
+   else:
+     echo "";
+   endif;
+?>
+<?= $theme->sidebar_bottom() ?>
diff --git a/themes/greydragon/views/user_profile.html.php b/themes/greydragon/views/user_profile.html.php
new file mode 100644
index 0000000..587eec2
--- /dev/null
+++ b/themes/greydragon/views/user_profile.html.php
@@ -0,0 +1,44 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  $(document).ready(function() {
+    $("#g-profile-return").click(function(event) {
+      history.go(-1);
+      return false;
+    })
+  });
+</script>
+
+<div id="g-user-profile">
+  <h1><?= t("User profile: %name", array("name" => $user->display_name())) ?></h1>
+  <div id="g-user-profile-operations">
+    <a id="g-profile-return" class="g-button ui-state-default ui-corner-all" href="#">
+      <?= t("Return") ?>
+    </a>
+<? if ($editable): ?>
+    <a class="g-button ui-state-default ui-corner-all g-dialog-link" href="<?= url::site("form/edit/users/{$user->id}") ?>">
+      <?= t("Edit") ?>
+    </a>
+    <a class="g-button ui-state-default ui-corner-all g-dialog-link" href="<?= url::site("users/form_change_email/{$user->id}") ?>">
+      <?= t("Change email") ?>
+    </a>
+    <a class="g-button ui-state-default ui-corner-all g-dialog-link" href="<?= url::site("users/form_change_password/{$user->id}") ?>">
+      <?= t("Change password") ?>
+    </a>
+<? endif ?>
+<? if ($contactable): ?>
+    <a class="g-button ui-state-default ui-corner-all g-dialog-link"
+       href="<?= url::site("user_profile/contact/{$user->id}") ?>">
+      <?= t("Contact") ?>
+    </a>
+<? endif ?>
+  </div>
+  <img src="<?= $user->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>"
+     alt="<?= html::clean_attribute($user->display_name()) ?>"
+     class="g-avatar g-left" width="40" height="40" />
+<? foreach ($info_parts as $info): ?>
+  <div class="g-block">
+    <h2><?= html::purify($info->title) ?></h2>
+    <div class="g-block-content"><?= $info->view ?></div>
+  </div>
+<? endforeach ?>
+</div>
diff --git a/themes/greydragon_old/admin/controllers/admin_theme_options.php b/themes/greydragon_old/admin/controllers/admin_theme_options.php
new file mode 100644
index 0000000..c72cd62
--- /dev/null
+++ b/themes/greydragon_old/admin/controllers/admin_theme_options.php
@@ -0,0 +1,866 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?    
+class Admin_Theme_Options_Controller extends Admin_Controller {
+
+  protected $min_gallery_ver = 49;
+
+  private function load_theme_info() {
+    $file = THEMEPATH . "greydragon/theme.info";
+    $theme_info = new ArrayObject(parse_ini_file($file), ArrayObject::ARRAY_AS_PROPS);
+    return $theme_info;
+  }
+
+  private function get_theme_version() {
+    $theme_info = $this->load_theme_info();
+    return ($theme_info->version);
+  }
+
+  private function get_theme_name() {
+    $theme_info = $this->load_theme_info();
+    return ($theme_info->name);
+  }
+
+  private function get_packlist($type, $filename) {
+    $packlist = array();
+    $packroot = THEMEPATH . 'greydragon/css/' . $type . '/';
+
+    foreach (scandir($packroot) as $pack_name):
+      if (file_exists($packroot . "$pack_name/css/" . $filename . ".css")):
+        if ($pack_name[0] == "."):
+          continue;
+        endif;
+
+        $packlist[$pack_name] = t($pack_name);
+      endif;
+    endforeach;
+    return $packlist;
+  }
+
+  private function get_colorpacks() {
+    return $this->get_packlist('colorpacks', 'colors');
+  }
+
+  private function get_framepacks() {
+    return $this->get_packlist('framepacks', 'frame');
+  }
+
+  private function prerequisite_check($group, $id, $is_ok, $caption, $caption_ok, $caption_failed, $iswarning, $msg_error) {
+    $confirmation_caption = ($is_ok)? $caption_ok : $caption_failed;
+    $checkbox = $group->checkbox($id)
+      ->label($caption . " " . $confirmation_caption)
+      ->checked($is_ok)
+      ->disabled(true);
+    if ($is_ok):
+      $checkbox->class("g-success");
+    elseif ($iswarning):
+      $checkbox->class("g-prerequisite g-warning")->error_messages("failed", $msg_error)->add_error("failed", 1);
+    else:
+      $checkbox->class("g-error")->error_messages("failed", $msg_error)->add_error("failed", 1);
+    endif;
+  }
+
+  /* Convert old values ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+  protected function upgrade_settings() {
+    if (module::get_var("th_greydragon", "hide_thumbmeta")):
+      module::set_var("th_greydragon", "thumb_metamode", "hide");
+      module::clear_var("th_greydragon", "hide_thumbmeta");
+    endif;
+
+    if (module::get_var("gallery", "appletouchicon_url")):
+      $temp = module::get_var("gallery", "appletouchicon_url");
+      module::set_var("gallery", "apple_touch_icon_url", $temp);
+      module::clear_var("gallery", "appletouchicon_url");
+    endif;
+
+    if (module::get_var("th_greydragon", "flex_rows", FALSE)):
+      module::set_var("th_greydragon", "column_count", -1);
+      module::clear_var("th_greydragon", "flex_rows");
+    endif;
+
+    if (module::get_var("th_greydragon", "thumb_descmode") == "overlay_static"):
+      module::set_var("th_greydragon", "thumb_descmode", "overlay_top");
+    endif;
+
+    if (module::get_var("th_greydragon", "mainmenu_position") == "1"):
+      module::set_var("th_greydragon", "mainmenu_position", "top");
+    endif;
+
+    if (module::get_var("th_greydragon", "hide_breadcrumbs")):
+      module::set_var("th_greydragon", "breadcrumbs_position", "hide");
+      module::clear_var("th_greydragon", "hide_breadcrumbs");
+    endif;
+
+    if (module::get_var("th_greydragon", "photonav_position")):
+      $temp = module::get_var("th_greydragon", "photonav_position");
+      module::set_var("th_greydragon", "paginator_album", $temp);
+      module::set_var("th_greydragon", "paginator_photo", $temp);
+      module::clear_var("th_greydragon", "photonav_position");
+    endif;
+
+    if (module::get_var("th_greydragon", "sidebar_allowed") == "none"):
+      module::set_var("th_greydragon", "sidebar_allowed", "default");
+    endif;
+
+    if (module::get_var("th_greydragon", "thumb_topalign")):
+      module::set_var("th_greydragon", "thumb_imgalign", "top");
+      module::clear_var("th_greydragon", "thumb_topalign");
+    elseif ((module::get_var("th_greydragon", "thumb_ratio") == "photo") && (!module::get_var("th_greydragon", "thumb_imgalign"))):
+      module::set_var("th_greydragon", "thumb_imgalign", "center");
+    endif;
+  }
+
+  protected function isCurlInstalled() {
+  	if (in_array('curl', get_loaded_extensions())) {
+  		return true;
+  	}	else {
+  		return false;
+  	}
+  } 
+
+  protected function get_edit_form_admin() {
+    $this->upgrade_settings();
+
+    $form = new Forge("admin/theme_options/save/", "", null, array("id" =>"g-theme-options-form"));
+
+    $rssmodulecheck = (module::is_active("rss") && module::info("rss"));
+
+    /* Prerequisites ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("requirements")->label(t("Prerequisites"));
+    $gallery_ver = module::get_version("gallery");
+    $this->prerequisite_check($group, "vercheck", $gallery_ver >= $this->min_gallery_ver, 
+      t("Gallery 3 Core v.") . $this->min_gallery_ver . "+", t("Installed"), t("Required"), FALSE, sprintf(t("Check Failed. Minimum Required Version is %s. Found %s."), $this->min_gallery_ver, $gallery_ver));
+    if (module::get_var("th_greydragon", "allow_root_page")):
+      $this->prerequisite_check($group, "rsscheck", $rssmodulecheck, 
+        t("RSS Module"), t("Found"), t("not Found"), TRUE, t("Install RSS module to Enable Root Page Support"));
+    endif;
+    $this->prerequisite_check($group, "curlcheck", ($this->isCurlInstalled()), 
+      t("PHP CURL Support is"), t("Enabled"), t("Disabled"), TRUE, t("Please make sure CURL support is enabled in PHP"));
+
+    /* Suggested Modules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("recommended")->label(t("Suggested Modules"));
+
+    $check_infos = array();
+    if (!module::get_var("th_greydragon", "hide_thumbmeta")):
+      $this->prerequisite_check($group, "info", (module::is_active("info") and module::info("info")), 
+        t("Info Module"), t("Found"), t("Required"), FALSE, t("Check Failed. Module is required to display Thumb metadata."));
+    endif;
+
+    if (module::is_active("fancybox") && module::info("fancybox")):
+      $check_infos[] = array("module" => "fancybox",  "module_name" => "Fancybox",  "link" => '<a href="http://codex.gallery2.org/Gallery3:Modules:fancybox" target="_blank">');
+    endif;
+    if (module::is_active("colorbox") && module::info("colorbox")):
+      $check_infos[] = array("module" => "colorbox",  "module_name" => "Colorbox",  "link" => '<a href="http://codex.gallery2.org/Gallery3:Modules:colorbox" target="_blank">');
+    endif;
+    if (module::is_active("shadowbox") && module::info("shadowbox")):
+      $check_infos[] = array("module" => "shadowbox", "module_name" => "Shadowbox", "link" => '<a href="http://codex.gallery2.org/Gallery3:Modules:shadowbox" target="_blank">');
+    endif;
+
+    switch (count($check_infos)):
+      case 0:
+        $check_infos[] = array("module" => "fancybox",  "module_name" => "Fancybox",  "link" => '<a href="http://codex.gallery2.org/Gallery3:Modules:fancybox" target="_blank">');
+        $this->prerequisite_check($group, "fancybox", FALSE, 
+          t("Fancybox/Colorbox/Shadowbox") . " " . t("Module"), t("Found"), t("not Found"), TRUE, sprintf(t("Install %smodule%s to Enable %s Support"), '<a href="http://codex.gallery2.org/Gallery3:Modules:fancybox" target="_blank">', '</a>', t("Fancybox")));
+        break;
+      case 1:
+        $check_info = $check_infos[0];
+        $this->prerequisite_check($group, $check_info["module"], TRUE, 
+          t($check_info["module_name"]) . " " . t("Module"), t("Found"), t("not Found"), TRUE, sprintf(t("Install %smodule%s to Enable %s Support"), $check_info["link"], '</a>', t($check_info["module_name"])));
+        break;
+      default:
+        $list = "";
+        $first = TRUE;
+        foreach ($check_infos as $key => $check_info):
+          if ($first):
+            $list .= $check_infos[$key]["module_name"];
+            $first = FALSE;
+          else:
+            $list .= ", " . $check_infos[$key]["module_name"];
+          endif;
+        endforeach;
+  
+        $this->prerequisite_check($group, "fancybox", FALSE, 
+            t($list . " Modules are Active"),
+            "",
+            "",
+            TRUE,
+            t("Slideshow feature would not work correctly. Please activate just one of these modules."));
+
+        break;
+    endswitch;
+
+    $check_info = $check_infos[0];
+    $thumbnavcheck = module::is_active("thumbnav") and module::info("thumbnav");
+
+    $this->prerequisite_check($group, "kbdnavcheck", ((module::is_active("kbd_nav")) and (module::info("kbd_nav"))), 
+      t("Kbd Navigation Module"), t("Found"), t("not Found"), TRUE, sprintf(t("Install %smodule%s to Enable Keyboard Navigation Support"), '<a href="http://codex.gallery2.org/Gallery3:Modules:kbd_nav" target="_blank">', '</a>'));
+    $this->prerequisite_check($group, "thumbnavcheck", $thumbnavcheck, 
+      t("ThumbNav Module"), t("Found"), t("not Found"), TRUE, sprintf(t("Install %smodule%s to Enable Thumb Navigation Support"), '<a href="http://codex.gallery2.org/Gallery3:Modules:thumbnav" target="_blank">', '</a>'));
+
+    $thumb_ratio = module::get_var("th_greydragon", "thumb_ratio", "photo");
+    $thumb_ratio_ex = FALSE;
+    switch ($thumb_ratio):
+      case "photo_ex":
+        $thumb_ratio = "photo";
+        $thumb_ratio_ex = TRUE;
+        break;
+      case "film_ex":
+        $thumb_ratio = "film";
+        $thumb_ratio_ex = TRUE;
+        break;
+      case "digital_ex":
+        $thumb_ratio = "digital";
+        $thumb_ratio_ex = TRUE;
+        break;
+      case "wide_ex":
+        $thumb_ratio = "wide";
+        $thumb_ratio_ex = TRUE;
+        break;
+      default:
+        break;
+    endswitch;
+
+    /* General Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $sidebar_allowed = module::get_var("th_greydragon", "sidebar_allowed");
+    $sidebar_visible = module::get_var("th_greydragon", "sidebar_visible");
+
+    $group = $form->group("edit_theme")->label(t("General Settings"));
+    $group->hidden("g_auto_delay")
+    	->value(module::get_var("th_greydragon", "auto_delay", 30));
+    $group->input("row_count")
+      ->label(t("Rows per Album Page"))
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("th_greydragon", "row_count", 3));
+    $group->dropdown("column_count")
+      ->label(t("Columns per Album Page"))
+      ->options(array("2" => t("2 columns"), "3" => t("3 columns"), "4" => t("4 columns"), "5" => t("5 columns"), "-1" => t("Flexible (3 x Number of Rows)")))
+      ->selected(module::get_var("th_greydragon", "column_count", 3));
+    $group->input("resize_size")
+      ->label(t("Resized Image Size (in pixels)"))
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("gallery", "resize_size"));
+    $group->input("logo_path")
+      ->label(t("Alternate Logo Image"))
+      ->value(module::get_var("th_greydragon", "logo_path"));
+    $group->input("favicon")
+      ->label(t("URL (or relative path) to your favicon.ico"))
+      ->value(module::get_var("gallery", "favicon_url"));
+    $group->input("appletouchicon")
+      ->label(t("URL (or relative path) to your Apple Touch icon"))
+      ->value(module::get_var("gallery", "apple_touch_icon_url"));
+    $group->input("header_text")
+      ->label(t("Header Text"))
+      ->value(module::get_var("gallery", "header_text"));
+    $group->input("footer_text")
+      ->label(t("Footer Text"))
+      ->value(module::get_var("gallery", "footer_text"));
+    $group->input("copyright")
+      ->label(t("Copyright Message"))
+      ->value(module::get_var("th_greydragon", "copyright"));
+    $group->dropdown("colorpack")
+      ->label(t("Color Pack/Site theme"))
+      ->options(self::get_colorpacks())
+      ->selected(module::get_var("th_greydragon", "color_pack", "greydragon"));
+    $group->dropdown("framepack")
+      ->label(t("Thumb Frame Pack"))
+      ->options(self::get_framepacks())
+      ->selected(module::get_var("th_greydragon", "frame_pack", "greydragon"));
+
+    /* Advanced Options - General ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_adv_main")->label(t("Advanced Options - General"));
+    $group->dropdown("viewmode")
+      ->label(t("Theme View Mode"))
+      ->options(array("default" => t("Full Mode (Default)"), "mini" => t("Mini Mode")))
+      ->selected(module::get_var("th_greydragon", "viewmode", "default"));
+    $group->dropdown("mainmenu_position")
+      ->label(t("Main Menu Position"))
+      ->options(array("default" => t("Bottom-Left (Default)"), "top" => t("Top-Left"), "bar" => t("Top Bar")))
+      ->selected(module::get_var("th_greydragon", "mainmenu_position"));
+    $group->dropdown("loginmenu_position")
+      ->label(t("Login Menu Position"))
+      ->options(array("header" => t("Header"), "default" => t("Footer (Default)"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "loginmenu_position", "default"));
+    $group->dropdown("breadcrumbs_position")
+      ->label(t("Breadcrumbs Position"))
+      ->options(array("default" => t("Bottom-Right (Default)"), "bottom-left" => t("Bottom-Left"), "top-right" => t("Top-Right"), "top-left" => t("Top-Left"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "breadcrumbs_position"));
+    $group->dropdown("title_source")
+      ->label(t("Title Source"))
+      ->options(array("default" => t("Title (Default)"), "no-filename" => t("Title/Suppress File Name"), "description" => t("Description")))
+      ->selected(module::get_var("th_greydragon", "title_source", "default"));
+    $group->input("custom_css_path")
+      ->label(t("File Name of custom.css or equivalent"))
+      ->value(module::get_var("th_greydragon", "custom_css_path"));
+    $group->input("thumb_quality")
+      ->label(t("Thumb Image Quallity (in %)"))
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("th_greydragon", "thumb_quality", 100));
+    $group->input("resize_quality")
+      ->label(t("Resized Image Quallity (in %)"))
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("th_greydragon", "resize_quality", 100));
+    $group->input("visible_title_length")
+      ->label(t("Visible Title Length"))
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("gallery", "visible_title_length", 15));
+
+    $group->checkbox("show_guest_menu")
+      ->label(t("Show Main Menu for Guest Users"))
+      ->checked(module::get_var("th_greydragon", "show_guest_menu"));
+    $group->checkbox("toolbar_large")
+      ->label(t("Use Large Toolbar Buttons"))
+      ->checked(module::get_var("th_greydragon", "toolbar_large"));
+    $group->checkbox("show_credits")
+      ->label(t("Show Site Credits"))
+      ->checked(module::get_var("gallery", "show_credits"));
+    $group->checkbox("breadcrumbs_showinroot")
+      ->label(t("Show Breadcrumbs in root album/root page"))
+      ->checked(module::get_var("th_greydragon", "breadcrumbs_showinroot"));
+    $group->checkbox("disable_seosupport")
+      ->label(t("Disallow Search Engine Indexing (No Bots)"))
+      ->checked(module::get_var("th_greydragon", "disable_seosupport"));
+    $group->checkbox("desc_allowbbcode")
+      ->label(t("Allow BBCode/HTML in Descriptions"))
+      ->checked(module::get_var("th_greydragon", "desc_allowbbcode"));
+    $group->checkbox("use_permalinks")
+      ->label(t("Use Permalinks for Navigation"))
+      ->checked(module::get_var("th_greydragon", "use_permalinks"));
+
+    /* Advanced Options - Album page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_adv_album")->label(t("Advanced Options - Album Page"));
+    $group->dropdown("paginator_album")
+      ->label(t("Paginator Position"))
+      ->options(array("top" => t("Top"), "bottom" => t("Bottom"), "both" => t("Both"), "none" => t("None")))
+      ->selected(module::get_var("th_greydragon", "paginator_album"));
+    $group->dropdown("album_descmode")
+      ->label(t("Description Display Mode"))
+      ->options(array("hide" => t("Hide"), "top" => t("Top"), "bottom" => t("Bottom")))
+      ->selected(module::get_var("th_greydragon", "album_descmode"));
+    $group->checkbox("disablephotopage")
+      ->label(t("Disable Photo Page (use Slideshow Mode)"))
+      ->checked(module::get_var("th_greydragon", "disablephotopage"));
+    $group->checkbox("hidecontextmenu")
+      ->label(t("Hide Context Menu"))
+      ->checked(module::get_var("th_greydragon", "hidecontextmenu"));
+
+    /* Advanced Options - Album page - Thumbs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_adv_thumb")->label(t("Advanced Options - Album page - Thumbs"));
+    $group->dropdown("thumb_ratio")
+      ->label(t("Aspect Ratio"))
+      ->options(array("photo" => t("Actual"), "film" => t("Film/Full Frame 3:2"), "digital" => t("Digital 4:3"), "wide" => t("Wide/HDTV 16:9")))
+      ->selected($thumb_ratio);
+    $group->checkbox("thumb_ratio_ex")
+      ->label(t("Expanded Aspect Ratio (300px wide)"))
+      ->checked($thumb_ratio_ex);
+    $group->dropdown("thumb_imgalign")
+      ->label(t("Thumb Image Align"))
+      ->options(array("top" => t("Top"), "center" => t("Center"), "bottom" => t("Bottom"), "fit" => t("Fit")))
+      ->selected(module::get_var("th_greydragon", "thumb_imgalign"));
+
+    $group->dropdown("thumb_descmode_a")
+      ->label(t("Title Display Mode (Album)"))
+      ->options(array("overlay" => t("Overlay Top"), "overlay_top" => t("Overlay Top (Static)"), 
+          "overlay_bottom" => t("Overlay Bottom (Static)"), "bottom" => t("Bottom"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "thumb_descmode_a"));
+    $group->dropdown("thumb_descmode")
+      ->label(t("Title Display Mode (Photo)"))
+      ->options(array("overlay" => t("Overlay Top"), "overlay_top" => t("Overlay Top (Static)"), 
+          "overlay_bottom" => t("Overlay Bottom (Static)"), "bottom" => t("Bottom"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "thumb_descmode"));
+    $group->dropdown("thumb_metamode")
+      ->label(t("Meta Data Display Mode"))
+      ->options(array("default" => t("Overlay (Default)"), "merged" => t("Merge with Title"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "thumb_metamode", "default"));
+    $group->checkbox("thumb_random")
+      ->label(t("Randomize Thumb Image"))
+      ->checked(module::get_var("th_greydragon", "thumb_random"));
+
+    /* Advanced Options - Photo page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_adv_photo")->label(t("Advanced Options - Photo Page"));
+    $group->dropdown("paginator_photo")
+      ->label(t("Paginator Position"))
+      ->options(array("top" => t("Top"), "bottom" => t("Bottom"), "both" => t("Both"), "none" => t("None")))
+      ->selected(module::get_var("th_greydragon", "paginator_photo"));
+    $group->dropdown("photo_descmode")
+      ->label(t("Description Display Mode"))
+      ->options(array("overlay_top" => t("Overlay Top"), "overlay_bottom" => t("Overlay Bottom"), "overlay_top_s" => t("Overlay Top (Static)"),
+         "overlay_bottom_s" => t("Overlay Bottom (Static)"), "bottom" => t("Bottom"), "top" => t("Top"), "hide" => t("Hide")))
+      ->selected(module::get_var("th_greydragon", "photo_descmode"));
+    $group->dropdown("photo_popupbox")
+      ->label(t($check_info["module_name"]) . " " . t("Mode"))
+      ->options(array("default" => t("Default (Slideshow/Preview)"), "preview" => t("Preview Only"), "none" => t("Disable")))
+      ->selected(module::get_var("th_greydragon", "photo_popupbox"));
+    $group->checkbox("thumb_inpage")
+      ->label(t("Keep Thumb Nav Block on the side"))
+      ->checked(module::get_var("th_greydragon", "thumb_inpage"));
+    if (!$thumbnavcheck):
+      $group->thumb_inpage->disabled(true);
+    endif;
+    $group->checkbox("hide_photometa")
+      ->label(t("Hide Item Meta Data"))
+      ->checked(module::get_var("th_greydragon", "hide_photometa", TRUE));
+
+    /* Advanced Options - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_adv_root")->label(t("Advanced Options - Root Page"));
+    $group->checkbox("allow_root_page")
+      ->label(t("Allow root page"))
+      ->checked(module::get_var("th_greydragon", "allow_root_page"));
+    $group->checkbox("show_root_desc")
+      ->label(t("Show Gallery Description"))
+      ->checked(!module::get_var("th_greydragon", "hide_root_desc"));
+    $group->input("root_feed")
+      ->label(t("Slideshow RSS Feed URL"))
+      ->value(module::get_var("th_greydragon", "root_feed", "/gallery3/index.php/rss/feed/gallery/latest"));
+    $group->dropdown("root_cyclemode")
+      ->label(t("Cycle Effect (Default: Fade)"))
+      ->options(array("fade" => t("Fade"), "fadeZoom" => t("Fade Zoom"), "blindX" => t("Blind X"), "blindY" => t("Blind Y"), 
+          "blindZ" => t("Blind Z"), "cover" => t("Cover"), "curtainX" => t("Curtain X"), "curtainY" => t("Curtain Y"),
+          "growX" => t("Grow X"), "growY" => t("Grow Y"), "none" => t("None"), "scrollUp" => t("Scroll Up"),
+          "scrollDown" => t("Scroll Down"), "scrollLeft" => t("Scroll Left"), "scrollRight" => t("Scroll Right"), 
+          "scrollHorz" => t("Scroll Horz"), "scrollVert" => t("Scroll Vert"), "shuffle" => t("Shuffle"), 
+          "slideX" => t("Slide X"), "slideY" => t("Slide Y"), "toss" => t("Toss"), "turnUp" => t("Turn Up"), 
+          "turnDown" => t("Turn Down"), "turnLeft" => t("Turn Left"), "turnRight" => t("Turn Right"), "uncover" => t("Uncover"),
+          "wipe" => t("Wipe"), "zoom" => t("Zoom")))
+      ->selected(module::get_var("th_greydragon", "root_cyclemode"));
+    $group->input("root_delay")
+      ->label(t("Slideshow Delay (Default: 15)"))
+      ->rules("required|valid_digit")
+      ->error_messages("required", t("You must enter a number"))
+      ->error_messages("valid_digit", t("You must enter a number"))
+      ->value(module::get_var("th_greydragon", "root_delay", "15"));
+    $group->checkbox("hide_root_sidebar")
+      ->label(t("Hide Sidebar"))
+      ->checked(module::get_var("th_greydragon", "hide_root_sidebar"));
+    $group->textarea("root_description")
+      ->label(t("Alternative Description (optional)"))
+      ->value(module::get_var("th_greydragon", "root_description"));
+
+    /* Sidebar Options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("edit_theme_side")->label(t("Sidebar Options"));
+    $group->checkbox("hide_blockheader")
+      ->label(t("Hide Block Header"))
+      ->checked(module::get_var("th_greydragon", "hide_blockheader"));
+    $group->checkbox("sidebar_albumonly")
+      ->label(t("Show Sidebar for Albums Only"))
+      ->checked(module::get_var("th_greydragon", "sidebar_albumonly"));
+    $group->checkbox("sidebar_hideguest")
+      ->label(t("Show Sidebar for Guest Users"))
+      ->checked(!module::get_var("th_greydragon", "sidebar_hideguest"));
+    $group->dropdown("sidebar_allowed")
+      ->label(t("Allowed Sidebar Positions"))
+      ->options(array("any" => t("Any"), "left" => t("Left"), "right" => t("Right"), "bottom" => t("Bottom"), "top" => t("Top"), "default" => t("Default Only")))
+      ->selected($sidebar_allowed);
+    $group->dropdown("sidebar_visible")
+      ->label(t("Default Sidebar Position"))
+      ->options(array("right" => t("Right"), "left" => t("Left"), "bottom" => t("Bottom"), "top" => t("Top"), "none" => t("No sidebar")))
+      ->selected($sidebar_visible);
+
+    /* Maintenance ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+    $group = $form->group("maintenance")->label(t("Maintenance"));
+    $group->checkbox("build_thumbs")->label(t("Mark all Thumbnails for Rebuild"))->checked(false);
+    $group->checkbox("build_resize")->label(t("Mark all Image Resizes for Rebuild"))->checked(false);
+    $group->checkbox("build_exif")->label(t("Mark Exif Info data for reload"))->checked(false);
+    $group->checkbox("purge_cache")->label(t("Purge cache data"))->checked(false);
+    $group->checkbox("reset_theme")->label(t("Reset Theme to a Default State"))->checked(false);
+
+    module::event("theme_edit_form", $form);
+
+    $form->submit("g-theme-options-save")->value(t("Save Changes"));
+    
+    return $form;
+  }
+
+  protected function get_edit_form_help() {
+    $help = '<fieldset>';
+    $help .= '<legend>' . t("Help") . '</legend><ul>';
+    $help .= '<li><h3>' . t("Prerequisites") . '</h3>
+      <p><b>' . t("REQUIREMENTS NEED TO BE MET FOR THE THEME TO FUNCTION PROPERLY.") . '</b><br />
+      	' . t("Please refer to the section on the left.") . '
+      </li>';
+
+    $help .= '<li><h3>' . t("General Settings") . '</h3>
+      ' . t("<p>Theme is designed to display thumbnails as a table.
+        You can choose different number of <b>Rows/Columns per Album Page</b> or can use <b>Flexible Columns</b>.
+      <p>Default G3 logo can be replaced with your own by providing <b>Alternate Logo Image</b>. Recommended logo size
+        is within 300x80px. If you need bigger space for your logo, CSS would have to be adjusted. Otherwise, Logo could be
+        suppressed altogether by providing <b>Header Text</b> to replace it. <b>Footer Text</b> would be simply placed next
+        to Site\'s credits.
+      <p><b>Copyright Message</b> can be placed in the right top corner of the footer.
+      <p>Important feature of the theme is a support for Color Packs which is managed by <b>Selected Color Pack</b> Option.
+      <b>Color Pack</b> allows changing colors, styles, theme for the pages. By default 6 color packs are included,
+        but it could be easily extended. Visit Theme\'s Download page for additional information.
+      <b>Frame Pack</b> allows change Frames used for Thumbs in album pages.") . '
+      </li>';
+
+    $help .= '<li><h3>' . t("Advanced Options - General") . '</h3>
+      ' . t("<p>In order to allow easier integration of Gallery 3 within other site infrastructure, Theme supports Special <b>View Mode</b>
+        - when <i>Mini Mode</i> is selected, attempt would be made to minimize space associated with Header/Footer by trimming of
+        the some information. Use with caution. Theme supports CMD parameter to override this selection - add 
+        \"?viewmode=default|full|mini\" to site URL in order to trigger a switch for specific browser session. When browser session
+        is restarted, view mode would revert back to default set in Admin Panel.
+      <p>Show your appreciation for our hard work by allowing <b>Show Site Credits</b> or contributing to our Coffee Fund.
+      <p>If main menu has functionality intended for guest users you can use <b>Show Main Menu for Guest Users</b> to keep it
+        visible.
+      <br />You can go even further and move main menu to the top of the header with breadcrumbs taking it place by selecting
+        <b>Alternate Header Layout</b>. <br />Then if you prefer breadcrumbs not being used, simply hide it with <b>Hide
+        Breadcrumbs</b> option.
+      <br />Then you can decide if you want to <b>Show Breadcrumbs</b> in the root album/root page.
+      <p>If you like to add some cool effects while navigating between pages,
+        enable <b>Blend Page Transition</b>.
+      <p><b>Paginator Position</b> could be changed to display it above and/or below the main content. 
+      <p>You can further fine tune theme using custom CSS file by providing file name (file need to be located in <b>themes/custom</b>
+        folder) or more specific location in form of <b>your_path/your_file_name.css</b> if different.
+      <p>Block web crawlers from indexing your Gallery with <b>Disallow Search Engine Indexing</b> Option.") . '
+      </li>';
+    $help .= '<li><h3>' . t("Advanced Options - Album page - Thumbs") . '</h3>
+      ' . t("<p>Options in this section adjust how Photo\'s Thumb images are displayed.
+      <p><b>Aspect Ratio</b> specifies layout/size of the thumb. Setting should be used with understanding that some
+        information may be out of visible area (crop). When switching to/from <b>Actual Size</b>, it is recommended to rebuild
+        thumbs so that proper settings are used for thumb resize logic (see Maintenance section below). Combined with
+        <b>Expanded Aspect Ratio (300px wide)</b> you can switch between 200px and 300px wide thumb images.
+      <p><b>Title Display Mode</b> and <b>Meta Data Display Mode</b> allows changing how Item\'s caption and Meta Data is
+        displayed. And selecting <b>Merge with Title</b> would place meta data with the Title.
+      <p>Randomize your thumbs by enabling <b>Randomize Thumb Image</b> (Please use with caution as it does introduce extra
+        load for database.).") . '
+      </li>';
+    $help .= '<li><h3>' . t("Advanced Options - Photo Page") . '</h3>
+      ' . t("<p>Options in this section adjust how individual Photo are presented to the viewer.
+      <p>With <b>ShadowBox Mode</b>, theme\'s logic could be adjusted in how Slideshow module is integrated.
+      <br />As with Title in Photo Thumbs, <b>Description Display Mode</b> changes how Photo Description is displayed.
+      <br />You can choose to <b>Keep Thumb Nav Block on the side</b> of the Photo when Page is displayed with bottom aligned
+        or hidden Sidebar.
+      <br />And if metadata (owner/clicks/etc.) is unnecessary, it could be removed with <b>Hide Item Meta Data</b>.
+      <p>Theme allows use of BBCode/HTML in item\'s descriptions, to enable it select <b>Allow BBCode/HTML in Descriptions</b>.") . '
+      </li>';
+    $help .= '<li><h3>' . t("Advanced Options - Root Page") . '</h3>
+      ' . t("<p>Special option which allows adding special root/landing page with slideshow utilizing specified <b>Slideshow RSS Feed
+        URL</b> (Default: /gallery3/index.php/rss/feed/gallery/latest).
+      <p>To enable it, select <b>Allow root page</b>.
+      <p>Add small description on the side of the slideshow with <b>Show Gallery Description</b>.
+      <br />Adjust rotation delay with <b>Slideshow Delay</b>.
+      <br />If Sidebar is not desired in the Root Page it could be hidden with <b>Hide Sidebar</b> option.
+      <br />By default, description content is populated from description of the root album, but by providing <b>Alternative
+        Description</b> you can overwrite it.") . '
+      </li>';
+    $help .= '<li><h3>' . t("Sidebar Options") . '</h3>
+      ' . t("<p>If Block\'s header is not desired, it could be removed using <b>Hide Block Header</b>.
+      <p>Sidebar visibility could be limited to individual Photo pages with
+      <b>Show Sidebar for Albums Only</b>.
+      <p>When sidebar is visible it can be placed on the left or right of the 
+        screen or removed altogether using <b>Allowed Sidebar Positions</b>.
+        If more than one position is allowed, <b>Default Sidebar Position</b>
+        would indicate default state, but visitor would able change it later.") . '
+      </li>';
+    $help .= '<li><h3>' . t("Maintenance") . '</h3>
+      ' . t("<p>Without changing image size, you can <b>Mark all Resizes for Rebuild</b>.
+      Then you need to visit Admin\Maintenance to initiate the process.
+      <p>Same can be done for image thumbs with <b>Mark all Thumbnails for Rebuild</b>.
+      <p><b>Mark Exif/IPTC Info for reload</b> would mark all Exif or IPTC records as \"Dirty\" allowing it to be repopulated.
+      <p>And just in case you think that something is not right, you can always <b>Reset Theme to a Default State</b>.") . '
+      </li>';
+    $help .= '</ul></fieldset>';
+    return $help;
+  }
+
+  private function save_item_state($statename, $state, $value) {
+    if ($state):
+      module::set_var("th_greydragon", $statename, $value);
+    else:
+      module::clear_var("th_greydragon", $statename);
+    endif;
+  }
+
+  protected function legacy() {
+    module::clear_var("th_greydragon", "photonav_top");
+    module::clear_var("th_greydragon", "photonav_bottom");
+    module::clear_var("th_greydragon", "hide_sidebar_photo");
+    module::clear_var("th_greydragon", "hide_thumbdesc");
+    module::clear_var("th_greydragon", "use_detailview");
+    module::clear_var("th_greydragon", "horizontal_crop");
+    module::clear_var("th_greydragon", "photo_shadowbox");
+    module::clear_var("th_greydragon", "root_text");
+    module::clear_var("th_greydragon", "enable_pagecache");
+
+    module::clear_var("th_greydragon", "navigator_album");
+    module::clear_var("th_greydragon", "navigator_photo");
+
+    module::clear_var("th_greydragon", "blendpagetrans");
+    module::clear_var("th_greydragon", "last_update");
+  }
+
+  protected function reset_theme() {
+    // Default core theme settings
+    module::set_var("gallery", "page_size", 9);
+    module::set_var("gallery", "resize_size", 640);
+    module::set_var("gallery", "thumb_size", 200);
+    module::set_var("gallery", "header_text", "");
+    module::set_var("gallery", "footer_text", "");
+    module::set_var("gallery", "show_credits", FALSE);
+
+    module::clear_all_vars("th_greydragon");
+  }
+
+  public function save() {
+    site_status::clear("gd_init_configuration");
+    access::verify_csrf();
+
+    $form = self::get_edit_form_admin();
+
+    if ($form->validate()):
+      $this->legacy();
+
+      if ($form->maintenance->reset_theme->value):
+        $this->reset_theme();
+        module::event("theme_edit_form_completed", $form);
+        message::success(t("Theme details are reset"));
+      else:
+        // * General Settings ****************************************************
+
+        $resize_size  = $form->edit_theme->resize_size->value;
+
+        $build_resize = $form->maintenance->build_resize->value;
+        $build_thumbs = $form->maintenance->build_thumbs->value;
+        $build_exif   = $form->maintenance->build_exif->value;
+        if (module::is_active("iptc") and module::info("iptc")):
+          $build_iptc   = $form->maintenance->build_iptc->value;
+        else:
+          $build_iptc = FALSE;
+        endif;
+        $purge_cache  = $form->maintenance->purge_cache->value;
+
+        $color_pack = $form->edit_theme->colorpack->value;
+        $frame_pack = $form->edit_theme->framepack->value;
+        $thumb_imgalign = $form->edit_theme_adv_thumb->thumb_imgalign->value;
+        $thumb_descmode_a = $form->edit_theme_adv_thumb->thumb_descmode_a->value;
+        $thumb_descmode = $form->edit_theme_adv_thumb->thumb_descmode->value;
+        $thumb_metamode = $form->edit_theme_adv_thumb->thumb_metamode->value;
+        $photo_descmode = $form->edit_theme_adv_photo->photo_descmode->value;
+        $photo_popupbox = $form->edit_theme_adv_photo->photo_popupbox->value;
+        $resize_quality = $form->edit_theme_adv_main->resize_quality->value;
+        $thumb_quality  = $form->edit_theme_adv_main->thumb_quality->value;
+
+        if ($build_resize):
+          graphics::remove_rule("gallery", "resize", "gallery_graphics::resize");
+          graphics::add_rule("gallery", "resize", "gallery_graphics::resize",
+            array("width" => $resize_size, "height" => $resize_size, "master" => Image::AUTO), $resize_quality);
+        endif;
+
+        if (module::get_var("gallery", "resize_size") != $resize_size):
+          module::set_var("gallery", "resize_size", $resize_size);
+        endif;
+
+        $_priorratio = module::get_var("th_greydragon", "thumb_ratio", "photo");
+        $thumb_ratio = $form->edit_theme_adv_thumb->thumb_ratio->value;
+        $thumb_ratio_ex = $form->edit_theme_adv_thumb->thumb_ratio_ex->value;
+        if ($thumb_ratio_ex):
+          $thumb_ratio .= "_ex";
+        endif;
+
+        if ($thumb_ratio_ex):
+          $thumb_size   = 300;  
+        else:
+          $thumb_size   = 200;
+        endif;
+
+        if ($thumb_ratio == "photo"):
+          $rule = Image::AUTO;
+        else:
+          $rule = Image::WIDTH;
+        endif;
+
+        if ($build_thumbs):
+          graphics::remove_rule("gallery", "thumb", "gallery_graphics::resize");
+          graphics::add_rule("gallery", "thumb", "gallery_graphics::resize",
+            array("width" => $thumb_size, "height" => $thumb_size, "master" => $rule), $thumb_quality);
+        endif;
+
+        if (module::get_var("gallery", "thumb_size") != $thumb_size):
+          module::set_var("gallery", "thumb_size", $thumb_size);
+        endif;
+
+        $row_count    = $form->edit_theme->row_count->value;
+        $column_count = $form->edit_theme->column_count->value;
+        $this->save_item_state("row_count", 3, $row_count);
+        $this->save_item_state("column_count", 3, $column_count);
+        if ($column_count == -1):
+          $column_count = 3;
+        endif;
+        module::set_var("gallery", "page_size", $row_count * $column_count);
+        module::set_var("gallery", "header_text", $form->edit_theme->header_text->value);
+        module::set_var("gallery", "footer_text", $form->edit_theme->footer_text->value);
+        module::set_var("gallery", "favicon_url", $form->edit_theme->favicon->value);
+        module::set_var("gallery", "apple_touch_icon_url", $form->edit_theme->appletouchicon->value);
+
+        $this->save_item_state("copyright", $form->edit_theme->copyright->value, $form->edit_theme->copyright->value);
+        $this->save_item_state("logo_path", $form->edit_theme->logo_path->value, $form->edit_theme->logo_path->value);
+        $this->save_item_state("color_pack", (($color_pack) and ($color_pack != "greydragon")), $color_pack);
+        $this->save_item_state("frame_pack", (($frame_pack) and ($frame_pack != "greydragon")), $frame_pack);
+
+        $auto_delay = $form->edit_theme->g_auto_delay->value;
+        $this->save_item_state("auto_delay", $auto_delay != 30, $auto_delay);
+
+        // * Advanced Options - General ******************************************
+
+        $this->save_item_state("viewmode",              $form->edit_theme_adv_main->viewmode->value != "default", $form->edit_theme_adv_main->viewmode->value);
+        $this->save_item_state("toolbar_large",         $form->edit_theme_adv_main->toolbar_large->value, TRUE);
+        module::set_var("gallery", "show_credits",      $form->edit_theme_adv_main->show_credits->value);
+        $this->save_item_state("show_guest_menu",       $form->edit_theme_adv_main->show_guest_menu->value, TRUE);
+        $this->save_item_state("loginmenu_position",    $form->edit_theme_adv_main->loginmenu_position->value != "default", $form->edit_theme_adv_main->loginmenu_position->value);
+        $this->save_item_state("mainmenu_position",     $form->edit_theme_adv_main->mainmenu_position->value != "default", $form->edit_theme_adv_main->mainmenu_position->value);
+        $this->save_item_state("breadcrumbs_position",  $form->edit_theme_adv_main->breadcrumbs_position->value != "default", $form->edit_theme_adv_main->breadcrumbs_position->value);
+        $this->save_item_state("breadcrumbs_showinroot",$form->edit_theme_adv_main->breadcrumbs_showinroot->value, TRUE);
+        $this->save_item_state("custom_css_path",       $form->edit_theme_adv_main->custom_css_path->value != "", $form->edit_theme_adv_main->custom_css_path->value);
+        $this->save_item_state("disable_seosupport",    $form->edit_theme_adv_main->disable_seosupport->value, TRUE);
+        $this->save_item_state("desc_allowbbcode", 			$form->edit_theme_adv_main->desc_allowbbcode->value, TRUE);
+        $this->save_item_state("resize_quality",        $resize_quality != 100, $resize_quality);
+        $this->save_item_state("thumb_quality",         $thumb_quality != 100,  $thumb_quality);
+        module::set_var("gallery", "visible_title_length", $form->edit_theme_adv_main->visible_title_length->value);
+        $this->save_item_state("title_source",          $form->edit_theme_adv_main->title_source->value != "default", $form->edit_theme_adv_main->title_source->value);
+        $this->save_item_state("use_permalinks",        $form->edit_theme_adv_main->use_permalinks->value, TRUE);
+
+        // * Advanced Options - Album page ***************************************
+
+        $this->save_item_state("album_descmode",    $form->edit_theme_adv_album->album_descmode->value != "hide", $form->edit_theme_adv_album->album_descmode->value);
+        $this->save_item_state("paginator_album",   $form->edit_theme_adv_album->paginator_album->value != "top", $form->edit_theme_adv_album->paginator_album->value);
+        $this->save_item_state("disablephotopage",  $form->edit_theme_adv_album->disablephotopage->value, TRUE);
+        $this->save_item_state("hidecontextmenu",   $form->edit_theme_adv_album->hidecontextmenu->value, TRUE);
+
+        // * Advanced Options - Album page - Thumbs ******************************
+
+        $this->save_item_state("thumb_ratio",       $thumb_ratio != "photo", $thumb_ratio);
+        $this->save_item_state("thumb_imgalign",    $thumb_imgalign != "top", $thumb_imgalign);
+        $this->save_item_state("thumb_descmode_a",  $thumb_descmode_a != "overlay", $thumb_descmode_a);
+        $this->save_item_state("thumb_descmode",    $thumb_descmode != "overlay", $thumb_descmode);
+        $this->save_item_state("thumb_metamode",    $thumb_metamode != "default", $thumb_metamode);
+        $this->save_item_state("thumb_random",      $form->edit_theme_adv_thumb->thumb_random->value, TRUE);
+
+        // * Advanced Options - Photo page ***************************************
+
+        $this->save_item_state("paginator_photo",  $form->edit_theme_adv_photo->paginator_photo->value != "top", $form->edit_theme_adv_photo->paginator_photo->value);
+        $this->save_item_state("photo_descmode",   $photo_descmode != "overlay_top", $photo_descmode);
+        $this->save_item_state("photo_popupbox",   $photo_popupbox != "default", $photo_popupbox);
+        $this->save_item_state("thumb_inpage",     $form->edit_theme_adv_photo->thumb_inpage->value, TRUE);
+        $this->save_item_state("hide_photometa",   !$form->edit_theme_adv_photo->hide_photometa->value, FALSE);
+
+        // * Advanced Options - Root page ****************************************
+
+        $rssmodulecheck = module::is_active("rss") and module::info("rss");
+
+        $root_feed = $form->edit_theme_adv_root->root_feed->value;
+        $root_cyclemode = $form->edit_theme_adv_root->root_cyclemode->value;
+        $root_delay = $form->edit_theme_adv_root->root_delay->value;
+        $root_description = $form->edit_theme_adv_root->root_description->value;
+
+        $this->save_item_state("allow_root_page", $form->edit_theme_adv_root->allow_root_page->value, TRUE);
+        $this->save_item_state("hide_root_desc",  !$form->edit_theme_adv_root->show_root_desc->value, TRUE);
+        $this->save_item_state("root_feed", $root_feed != "gallery/latest", $root_feed);
+        $this->save_item_state("root_cyclemode", $root_cyclemode != "fade", $root_cyclemode);
+        $this->save_item_state("root_delay", $root_delay != "15", $root_delay);
+        $this->save_item_state("hide_root_sidebar", $form->edit_theme_adv_root->hide_root_sidebar->value, TRUE);
+        $this->save_item_state("root_description", $root_description, $root_description);
+
+        // * Sidebar Options *****************************************************
+
+        $sidebar_allowed = $form->edit_theme_side->sidebar_allowed->value;
+        $sidebar_visible = $form->edit_theme_side->sidebar_visible->value;    
+
+        if ($sidebar_allowed == "right"):
+          $sidebar_visible = "right";
+        endif;
+        if ($sidebar_allowed == "left"):
+          $sidebar_visible = "left";
+        endif;
+
+        $this->save_item_state("hide_blockheader",  $form->edit_theme_side->hide_blockheader->value, TRUE);
+        $this->save_item_state("sidebar_albumonly", $form->edit_theme_side->sidebar_albumonly->value, TRUE);
+        $this->save_item_state("sidebar_hideguest", !$form->edit_theme_side->sidebar_hideguest->value, TRUE);
+        $this->save_item_state("sidebar_allowed",   $sidebar_allowed != "any",   $sidebar_allowed);
+        $this->save_item_state("sidebar_visible",   $sidebar_visible != "right", $sidebar_visible);
+
+        $this->save_item_state("last_update",   		TRUE, time());
+
+        module::event("theme_edit_form_completed", $form);
+
+        if ($_priorratio != $thumb_ratio):
+          message::warning(t("Thumb aspect ratio has been changed. Consider rebuilding thumbs if needed."));
+        endif;
+
+        message::success(t("Updated theme details"));
+
+        if ($build_exif):
+          db::update('exif_records')
+            ->set(array('dirty'=>'1'))
+            ->execute();
+        endif;
+
+        if ($build_iptc):
+          db::update('iptc_records')
+            ->set(array('dirty'=>'1'))
+            ->execute();
+        endif;
+
+        if ($purge_cache):
+          db::build()
+            ->delete("caches")
+            ->execute();
+        endif;
+      endif;
+      url::redirect("admin/theme_options");
+    else:
+      print $this->get_admin_view();
+    endif;
+  }
+
+  protected function get_admin_view() {
+    $view = new Admin_View("admin.html");
+    $view->page_title = t("Grey Dragon Theme");
+    $view->content = new View("admin_theme_options.html");
+    $view->content->name = self::get_theme_name();
+    $view->content->version = self::get_theme_version();
+    $view->content->form = self::get_edit_form_admin();
+    $view->content->help = self::get_edit_form_help();
+    return $view;
+  }
+
+  public function index() {
+    site_status::clear("gd_init_configuration");
+    print $this->get_admin_view();
+  }
+}
+?>
\ No newline at end of file
diff --git a/themes/greydragon_old/admin/views/admin_theme_options.html.php b/themes/greydragon_old/admin/views/admin_theme_options.html.php
new file mode 100644
index 0000000..0e9f404
--- /dev/null
+++ b/themes/greydragon_old/admin/views/admin_theme_options.html.php
@@ -0,0 +1,38 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+  $gd_shared_installed = (module::is_active("greydragon") && module::info("greydragon"));
+  if ($gd_shared_installed):
+    $view = new View("gd_admin_include.html");
+    $view->is_module = FALSE;
+    $view->downloadid = 1;
+    $view->name = "greydragon";
+    $view->form = $form;
+    $view->help = $help;
+  else:
+    $view  = '<div id="g-greydragon-admin" class="g-block">';
+    $view .= "<h1>" . t("Prerequisite") . "</h1><hr>";
+    $view .= "<p>" . t("This theme requires GreyDragon shared module to be installed and actived first.") . "</p>";
+    $view .= "<p>" . t("Please download it") . ' <a href="http://codex.gallery2.org/Gallery3:Modules:greydragon" target="_blank">' . t("here") . "</a> " . t("and install. Make sure it is activated.") . "</p>";
+    $view .= "</div>";
+  endif;
+
+  print $view;
+?>   
+
diff --git a/themes/greydragon_old/changelog.txt b/themes/greydragon_old/changelog.txt
new file mode 100644
index 0000000..3d234da
--- /dev/null
+++ b/themes/greydragon_old/changelog.txt
@@ -0,0 +1,616 @@
+=== Grey Dragon Theme ===
+Grey Dragon Theme - a custom theme for Gallery 3
+
+This theme was designed and built by Serguei Dosyukov, whose blog you will find
+at http://blog.dragonsoft.us/
+Copyright (C) 2009-2012 Serguei Dosyukov
+
+Tested up to: G3 3.0.3 build 55
+Minimum requirement: G3 3.0.2 build 49
+
+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 for more
+details. You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street Fifth Floor, Boston, MA  02110-1301, USA.
+
+=== Open issues ===
+- RTL layout support
+                            
+=== Changelog ===
+version 3.2.2
+- CSS: Fixes a phenomenon where dialog content not aligning properly under some conditions
+- CSS: Fixes a phenomenon where login dialog for error/login and reauthenticate pages were not in sync
+- Movie thumb and Photo IDs are adjusted to comply with 3.0.3 notation
+- Photo page image precache javascript moved into .ready to speed up the page load
+- CP: Roundrobin styles improvements - top login positioning adjusted, removed padding for root page when sidebar is used
+- ADMIN: Added prerequisite check for CURL support in PHP
+
+version 3.2.1
+- Logic to process command line parameters changed to prevent unhandled exception on some LAMP instances
+
+version 3.2.0
+- Theme is now HTML 5 
+- CSS: Dropped support for IE 6
+- IMPORTANT: .g-extended class moved from .g-item level into a <body> to allow layout manipulation based on thumb formats. Styles are affected.
+- Added class marker to page's <body> element to indicate current sidebar mode - g-sidebar-xxxxxxxx
+- CSS: Min width of the gallery is now enforced based on number of columns and sidebar visibility - extended thumbs 3/4 columns
+- CSS:   Decrease size of the column for 3 column layout to 31% to prevent wrapping in some browser modes
+- ADMIN: Logic added to inform site owner about new versions of the theme
+- ADMIN: Admin page layout is now based on shared GreyDragon module which is now required 
+- ADMIN: "Visible Title Length" option - access to G3 title length setting. 
+- ADMIN: Use Permalinks for navigation - allows /root, /enter be used for root page access. 
+  Requires the following rules added in .htaccess <mod_rewrite.c> section
+
+  ########## Enable /root url ################
+  #
+  RewriteRule ^root ?root=yes [NC]
+  RewriteRule ^enter ?root=no [NC]
+  #
+  ############################################
+
+- Visible Title Length is now taken in consideration when displaying Photo Titles in thumbs, breadcrumbs, etc.
+- Improved file name detection for Title Source
+- CP: new color pack - Round Robin     \
+- FP: new frame pack - Round Corners   / combined would give look of Clean Canvas theme
+- FP: Book frame pack : removed right padding to prevent wrapping on smaller resolutions
+- FP: Wall frame pack : min width decreased to all proper alignment of tiles
+- jquery.cycle.js updated to v.2.9999.4
+- Synchronize Calendar page with page.html.php
+- CSS: forms.css - fixed two misspelled rules
+- Added code protection from Camel case in CMD parameters
+- Fixed issue with missing status icons for some colorpacks in Upload dialog
+- Added code protection in Root page to detect situation when roller is empty and then do not initialize the cycle plugin
+- Added translation support for default thumb caption (Photo #, Movie #, etc)
+                                                                                                       
+version 3.1.4
+- ADMIN: Option to specify image quality level for Photo resizes and Thumbs
+- ADMIN: Additional Description Display Mode for Photo page : Overlay Top (Static), Overlay Bottom (Static)
+- ADMIN: Title Source - manage what thumb/image title is based on : Title | Title/Suppress Filename | Description
+- Added support for normalize.css - see http://necolas.github.com/normalize.css/ for more details
+- Added rel=nofollow for sidebar mode switch links to prevent indexing
+- Fix: module check failing in admin section when none of colorbox, shadowbox or fancybox is intalled
+- Fix: CSS: Added missing rule for size of the thumb in Wall frame pack for "Actual" aspect ratio
+- Fix: CSS: Fixed "Forgot password" misalignment in Login dialog
+- G3 version requirement increased to 3.0.2
+
+version 3.1.3
+- Removed validation for ImageBlockEx preventing use of RootPage option
+- Removed JS code - attempt to have fadeIn effect
+ 
+version 3.1.2
+- CSS: Fixed issue with breadcrumbs divider in colorpacks
+- CSS: Fixed issue with thumb description positioning
+
+version 3.1.1
+- Removed some redundant code in page.html.php
+- Fixed issue with fixed Columns style not being applied
+- Added code protection for situation when $position is not defined in paginator.html.php
+- CSS: Fixed issues with popup menu positioning
+
+version 3.1.0
+- CSS: !!! Folder Structure Change !!! colors.css and frame.css added to aggregated CSS.
+- ADMIN: Root Page is now iPad/Mac compatible - Flash player has been replaced with jquery.cycle - option added to manage
+	rotation mode. ImageBlockEx module is no longer required.	For hosts where there is a block accessing local RSS feed, 
+	rootpage.html.php_fix can be used (old style) by renaming it and placing into /themes/custom/views folder
+- ADMIN: New option - Hide Context Menu for thumbs
+- ADMIN: New option - Disable photo page - open FancyBox style slideshow directly from album page
+- ADMIN: New option - Show Sidebar for Guest Users
+- ADMIN: Option for Thumb alignment extended to Top/Center/Bottom/Fit
+- ADMIN: Option's order change in Advanced Options - General
+- ADMIN: Large toolbar buttons
+- ADMIN: "Blend Page Transitions" is replaced with JS version
+- ADMIN: Corrected setting for Apple Touch Fav Icon to use G3 default setting
+- ADMIN: "Login Menu Position" expanded to allow login to be hidden. Admin can access Admin area using http://site_url/admin URL
+- CP: New color pack - White Hawk
+- FP: New frame pack - Wall
+- FP: Support for custom frame content added - frame.html.php
+- Core: Current framepack is now referenced by the page
+- Core: Body class logic moved into theme's library class
+- Core: "Up" navigation button now would take you to item's associated page rather then to first page of the album
+- Core: Fixed issue of Sidebar position setting not being picked up under some conditions
+- Core: Improved detection for root page - if root album id <> 1
+- Core: Framepack and viewmode URL parameter value is now retained for duration of the session
+- Core: In "Disable photo page" mode, if EXIF module is disabled, thumb would include clickable reference to EXIF dialog
+- Core: Breadcrumbs are now using :: as divider instead of image
+- CSS: Column/Colorpack classes (ex: g-column-3, g-wall) moved one level up from ul#g-album-grid to div.g-album-grid-container
+- CSS: Fixed issue with meta data alignment in Simple frame pack
+- CSS: Fixed issue with permission dialog's breadcrumbs alignment
+- CSS: removed left padding for navigator thumbs which was causing image "jumps"
+- CSS: Some images were changed
+- JS: Shadowbox settings moved out of the theme into module itself.
+
+version 3.0.8
+- Fixed issue with allowed sidebar position not properly recognized when used as Default 
+- Fix issue with missing quotes in Admin module
+- Fixed issue with uninitialized variable in admin page
+- Fixed background for view-calendar.png for some color packs
+- CSS: Center content of ThumbNav module. If non default thumb size is used for module, setting may need to be adjusted.
+- CSS: Added new style sheet for iPad support
+
+version 3.0.7
+- ADMIN: Added support for View Mode - Full/Mini (ex: ?viewmode=mini | ?viewmode=full | ?viewmode=default )
+- ADMIN: Paginator position now can be set independently for Album and Photo pages
+- ADMIN: Added Colorbox slideshow detection
+- Theme.info adjusted to match new guidelines
+- CSS: GreyDragon Color Pack - fixed thumb background color issue with GreyDragon Frame Pack
+- CSS: changes to improve Basket Module integration
+- CSS: #g-album-grid element now references framepack used for better interaction between frame and color packs (ex: class="g-slateblue")
+- Fix issue with sidebar not properly displayed in Root Page
+- Fix issue with missing thumb image not being aligned properly in "Actual Aspect Ratio" mode
+
+version 3.0.6
+- Fix: Using Top aligned sidebar causes problem
+
+version 3.0.5
+- ADMIN: Allow hiding sidebar for root pages -> Advanced Options\Root Page\Hide Sidebar
+- ADMIN: Allow breadcrumbs in root page/root album -> Advanced Options\General\Show Breadcrumbs in top album/root page
+- Fixed issue with Calendar not displayed properly when no items are returned
+- CSS: Increased padding for in-page description block
+
+version 3.0.4
+- FP: New framepack - book
+  Please note that if bottom aligned description is used, it need to be the same for both album and photo thumbs.
+- CSS: #g-album-grid-container renamed to .g-album-grid-container
+- CSS: Fixed slight misalignment of 3 level main menu items
+- ADMIN: New position for main menu - Top Bar - top aligned/fixed positioned menu. Useful for admin mode menu
+- ADMIN: Added support for separate option for description position in album thumbs
+
+version 3.0.3
+- ADMIN: Added option for Root Page slideshow delay
+- ADMIN: Added option for Alternative Description for Root Page which overwrites Description from Root album
+- CSS: Fix issue with context menu hotspot z-index in thumbs
+- CSS: Fixed margin in Uploadify dialog to prevent overlap
+- ADMIN: Page cache option has been deprecated. It can be achieved via .htaccess instead
+
+version 3.0.2
+- Wind Color Pack: Fixed issue with missing background image for dialog header
+- CSS: Wind Color Pack: Set dialog background to white
+- ADMIN: Fixed issue of Maintenance group label not being translated
+- Fixed issue with float division for photo page
+- Fixed issue with BBCode in info block not being converted (regression error)
+- Fixed small misalignment of the image with the "Actual" Aspect Ratio Thumb
+- Added CSS class marker for portrait thumb images
+- IE9: Added support for Pinned Site mode and Jump List menu
+
+version 3.0.1
+- ADMIN: Page Header and Footer Text allows BBCode
+- ADMIN: Added support for apple-touch-icon - icon similar to favicon to be used on iPad/iPhone/iPod devices
+- ADMIN: New option - Album Description Display Mode - allowing placement of the description in the album pages
+- ADMIN: Main menu could be now positioned as Top-Left/Bottom-Left aligned
+- ADMIN: Bradcrumbs could be now positioned as Top-Left/Bottom-Left/Bottom-Right or Hidden
+- Added <span> wrappers for Header and Footer texts allowing further CSS manipulation
+- Added support for custom header/footer inclusion - simply drop header.html.php and/or footer.html.php in the views folder and content would be added in the header/footer section
+- Info sidebar block logic synchronized to match default but still allow BBCode
+
+version 3.0.0
+- Due to extensive changes to CSS it is now a major release
+- Rules from screen.css moved into base.css. Screen.css used as loader file only.
+- Introduced better support for RTL
+- Some of the icons moved into ui-icons.png for optimization. Color adjustments for visibility.
+- Added support for frame packs. Included: greydragon (default), simple, android, iphone, iphoto, darkglass
+- Fixed issue with regular wide thumb format not being set/displayed properly
+- Breadcrumb logic extended to take in consideration [visible_title_length] variable value introduced in G3
+- Reordered JS registration to comply with default G3 3.0.1 logic
+- Added some missing translation hooks in Admin area
+- Some Page load optimization
+- Added logic to take in consideration date display format for info module
+- Performed validation and necessary adjustments for IE 9/IE 9 compatibility mode
+- IE Fix CSS is only applied for IE 6. Older versions are no longer supported
+
+version 2.7.9
+- Optimized session handling for colorpack cmd param
+- Removed validation for colorpack presence
+
+version 2.7.8
+- Fixed issue with colorpack detection. Reenabled
+- Fixed issue with sidebar position could be "stuck" when switching from Grey Dragon Wind Theme
+- Fixed introduced error with missing forms.css reference
+- Theme's CSS/JS is combined into session based G3 files
+
+version 2.7.7
+- Adjusted for 3.0.1 release of G3
+- New color pack: blackhawk
+- ADMIN: New sidebar position supported - top (new rules added to colorpacks)
+- CSS: Some clean up for included colorpacks - CSS/image resources, sprite image optimization for sidebar position buttons
+- Added session persistence for colorpack url parameter for demo purposes
+- ADMIN: Prerequisites module check extended to make it more relevant when Root Page is allowed
+- CSS: Sync positions of main menu and breadcrumbs when in alternative header layout format
+- colorpack location validation has been disabled for now until issue is resolved
+
+version 2.7.6
+- ADMIN: "Large" Thumb sizes are removed from Aspect dropdown and managed via "Expanded Aspect Ratio (300px wide)" option
+- ADMIN: New Thumb aspect ratio - Wide/HDTV (16:9), "Actual" aspect is supported in Expanded mode
+- ADMIN: Root Page - new option "Show Gallery Description"
+- Added check if Shadowbox is loaded so that theme's initialization JS does not produce hidden exception
+- Added pointer cursor for clickable overlay area in Root Page until Minislideshow is loaded
+
+version 2.7.5
+- ADMIN: Full Slideshow RSS feed url now being used. This solves some issues with Flash loader and allows creation of custom playlists to be used in the root page
+- Root Page: Fixed issue with Flash Slideshow not being loaded properly
+
+version 2.7.4
+- Root Page: Added "Click to Enter" to indicate clickable state
+- Root Page: Quote is now taken from root album description field. If description is empty, slideshow content is centered.
+- Added branding icons for "gallery 3" and theme/color packs.
+- Fixed issue with page layout for calendar module.
+- Fixed issue with URL parameters not being recognized in some server configurations
+- CSS: Fixed aspect ratio for thumbs. Some css alignments optimization
+- CSS: Turned back on borders for blocks in bottom aligned sidebar
+- ADMIN: New option for Photo Description Display Mode - Overlay Bottom. !!!! Color pack's CSS rules affected.
+- ADMIN: Maintenance section: Added "Reset IPIC Info" (if module is active) and "Purge cache data", some tweaks for "Reset EXIF Info"
+
+version 2.7.3
+- ADMIN: New option - Randomize Thumb Image
+- Missing markup in rootpage.html.php
+- Root Page - set size of the slideshow to auto so it can be managed via CSS
+- Sync page.html.php structure with latest git changes
+- CSS: Fixed styles for progress dialog when invoked from non-admin area
+
+version 2.7.2
+- CSS: Restored visible state of rotation operations for photos
+- JS: To resolve issue with Opera OS, background image need to be set for #g-rootpage-link instead of roller object. Finalization JS for root page slideshow extended to clear background for overlay.
+- Reenabled support for site status messages
+
+version 2.7.1
+- Root Page layout/css extended to allow click on the image while slideshow is still loading
+- ADMIN: Some changes in setting's titles and help
+- Fixed issue with meta data overlay not being shown for some title/meta combinations
+
+version 2.7.0
+- DEV: new url parameter support added - colorpack. Ex: <gallery_url>?colorpack=<name> 
+- ADMIN: 2 to 5 columns layout is now supported. Flex column option moved into column selector. 
+- ADMIN: Added new mode for Description overlay in Album - Overlay Bottom (Static) - places description on the bottom of the thumb as static overlay. Metadata would not be shown. 
+- ADMIN: Metadata Display Mode for Thumbs introduced. [Hide metadata] merged into it. Metadata can now be merged with description. 
+- W3C: resolved some validation errors in album page 
+- CSS: !!! Colorpack !!! - adjusted to reflect changes to thumb description structure 
+- CSS: Changes for columns CSS (.g-column-3/.g-column-4) - moved to list level - several php files also affected 
+- CSS: Fixed issue with re-authenticate dialog layout 
+- CSS: Fixed issue search button in IE7 Compatibility mode for wind color pack 
+- ShadowBox module config settings changed to prevent flickering - enabled dialog animation. Slideshow timeout increased to 7 sec. Updated version of ShadowBox module is available. 
+- CSS: Deprecated styles for ShadowBox Ajax dialogs as they are not supported by the library in Core and color pack references 
+
+version 2.6.3
+- ADMIN: New "Title Display Mode" added - Overlay (Static)
+- CSS: syncronization between colorpacks. Some simplification
+
+version 2.6.2
+- Added support for initial background in the Root Page to be removed as soon as slideshow starts (requires imageblockex 2.1)
+- ADMIN: Added option allowing feed selection for Root Page, Quote text
+- Small changes in color pack and layout for Upload dialog
+- Fixed logic in roopage.html.php to properly construct the link for navigation
+
+version 2.6.0
+- Support for root page added
+- Added borders for main wrapper in Slate Blue color pack to accommodate centered layout
+- Added JS to preload next/prior images in photo pages
+- Added content wrapper for album grid to allow external CSS application - ex: center grid content
+- ALERT! Improved rendering of admin panel. This would break admin panels for any modules which uses the same file by inheritance. Please download updated module distros.
+- Fixed wrong reference to layout_non_ie.css file - not used
+- Removed restrictions for displaying sidebar in satellite pages
+- Fixed status message alignment in Upload dialog
+- Fixed W3C validation error in Photo page markup
+- "controllers" folder deprecated
+                                                 
+version 2.5.1
+- Fixed issue with relative path not being used when changing sidebar display mode
+- ADMIN: Added support for Blend effect for page transitions
+- ADMIN: Added check to identify module collision between FancyBox and ShadowBox
+- ADMIN: New option "Keep Thumb Nav Block on the side" for Photo Pages
+- CSS: small css changes for bottom aligned sidebar positioning
+- CSS: Fix for dialog overlay div to properly position itself and prevent scrollbars to appear without reason
+- CSS: slateblue color pack - make regular text grey
+- CSS: set min height for bottom aligned sidebar
+- CSS: Fixed issue with font size for dialogs in IE8 Compatability mode 
+- Custom layout for tag_block.html.php is depricated
+- Some W3C Validation clean-up
+
+version 2.5.0
+- New colorpack - SlateBlue
+- Added support for bottom aligned Sidebar
+- CSS: opacity in .ui-widget-overlay (forms.css) set to 70
+- CSS: Fixed issue with misallignment of sidebar toolbar area and page header info
+- CSS: Removed left pagging for g-photo element to properly align in the div
+- CSS: Added thumb size restrictions for Image Block module
+- Removed logic to use Shadowbox when showing Exif data
+
+version 2.4.9
+- ADMIN: Top Align Thumb Image option added - do not center thumb image in the view window. Useful for portrait oriented photos.
+- ADMIN: Added a new Advanced option - Relative path to custom.css, if used - allowing inclusion of custom css override
+- Ignore albums when building item list for Fancybox/Shadowbox Slideshow in Photo page. Fix issue with extra item added when start with first item.
+- Fixed issue with not properly sanitized titles for links for Fancybox/Shadowbox Slideshow in Photo page
+- Small adjustment to FancyBox slideshow navigation arrows
+- Force min height requirement for H1/H2 elements
+- Fixed spelling for g-thumlink -> g-thumblink
+- Force size of the thumb link to fill crop area - situation when thumb image is smaller then view area
+- Removed custom layout for User Profile page
+
+version 2.4.8
+- Fixed inverted state of "Disallow Search Engine Indexing (No Bots)
+- Fixed JS syntax incompatibility in IE7/IE8 compatibility mode
+- Fixed display of thumb title and photo description on hover in IE7/IE8 compatibility mode
+- Fixed issue with Dialogs not skinned properly in Carbon/Wind themes
+- Fixed issue with metadata for photo thumbs when Aspect Ratio: Actual Size and Title Display Mode: Bottom
+
+version 2.4.7
+- Fixed issue with some .g-block structures.
+  Fixed issue with avatar not properly aligned in comment section.
+
+version 2.4.6
+- Fixed some issues when strict error reporting is enabled for PHP
+- Fixed background color for description for bottom Display Title Mode (greydragon colorpack)
+- Added support for two new Thumb Sizes - Digital Ex and Film Ex - 300px wide thumbs
+- Fixed issue with buttons in the block "jumping" out
+- Added check in block view to verify that theme is defined
+
+version 2.4.5
+- Min G3 core requirement is set to v.41
+- Fixed issue with Exif dialog data integration
+- Fixed issue with permission dialog
+- CSS: Changes form style management. Fixed issue with breadcrumbs display in dialogs.
+- CSS: Important! Colorpack files are affected
+- Removed no longer required custom Login dialog logic
+- JS cleanup
+
+version 2.4.4
+
+Please drop GD themes folder before uploading a new version
+
+- CSS: screen.css - fixed layout naming change preventing proper display of authentification form when accessing protected areas
+- CSS: Removed some temp files not required by the theme.
+- Support for Fancybox added as alternative to Shadowbox
+- Added support for CalendarView module
+
+version 2.4.3
+- Fixed issue with sidebar mode switch link being incorrect
+- CSS: small style adjustment to neutralize default style effect for the search entry box
+
+version 2.4.2
+- Fixed issue some modules requiring scrollTo() function.
+- Shadowbox is now optional. Special logic added to allow/disallow SB slideshow mode. If disabled, theme would not support full view for images to be in the popup window, new window will be used instead.
+- CSS: Minor improvements for thumb layout in Overlay and Bottom Title Display mode
+- ADMIN: Support for flex column layout added
+- ADMIN Help: Small improvements
+
+version 2.4.1
+- Organize module support reenabled
+- Register module support reenabled
+- Partial support for Shopping Basket module
+- CSS clean-up after dialog engine conversion - round #1
+- Fixed issue with Exif dialog not properly rendered
+
+version 2.4.0
+- Apply g-button style only to forms
+- Fix to properly display videos
+- Fix to account for changes in Comments module
+- Favicon removed from theme's package
+- Fixed uninitialized state warnings of the variables in PHP protected mode
+- Album thumbs now have "lighter" background
+- First draft to change how dialogs are handled - switched to standard code
+- ADMIN: G3 Core version requirement is set to 32
+- ADMIN: Added missing settings initializations
+- ADMIN: Fixed issue with Navigator position setting not being persisted
+- ADMIN: Abstract admin form styles for reuse from regular module admin panels
+- ADMIN: Added option to specify favicon location. If not specified default G3 icon is used.
+
+version 2.3.1
+- Hide Rotate operations for pictures since they are not supported by the theme
+- Added use of common gallery.ajax.js. Fix issue with some Ajax based links.
+- Layout fixes for Translation form overlay
+- Changed CSS styling for buttons to provide unified coverage for buttons and links exposed as buttons.
+- ADMIN: Fixed options group styles in Theme's Admin panel
+- ADMIN: Advanced Settings for Thumbs and Individual Photo are moved into separate sections.
+- ADMIN: New option - display meta data in Photo description section
+- ADMIN: New option/fix - SEO indexing is now allowed by default. In order to prevent your site from being indexed, you can now use "Disallow Search Engine Indexing" option
+
+version 2.3.0
+- Adopted for Gallery 3.0RC2 changes (minor template adjustments, css class name changes, etc.)
+
+version 2.2.1
+- Redesigned Ready event handler for the theme to ensure proper ShadowBox initialization
+- Added support for gallery_dialog() function call used by some 3rd party modules - some sync issues are solved by imposed delay of 1 second
+- GPS module - better action list alignment in the sidebar
+
+version 2.2.0
+- Added support for slideshow mode in Photo Preview
+- Fixed issue with Info side block - missing markup
+- Fixed issue with Upload dialog layout with some resolutions/fonts
+- ADMIN: Added option to hide breadcrumbs
+- ADMIN: Added prerequisite check for Info module - required for Thumb meta data display
+
+version 2.1.7
+- Added support for missing images in the thumbs to allow proper operations with empty albums or albums with broken thumbs
+- Some color optimizations
+- Color improvements for "Add Image" dialog
+- Better support for Basket module
+
+version 2.1.6
+- Wind colorpack adjusted to closer match default Wind theme
+
+version 2.1.5
+- Minor changes in ADMIN infrastructure
+- ADMIN: added check for Kbd Navigation module
+- ADMIN: New color pack - carbon
+
+version 2.1.4
+- Minor refactoring in paginator
+- Added support for keyboard navigation module (http://codex.gallery2.org/Gallery3:Modules:kbd_nav)
+
+version 2.1.3
+- Sidebar restricted to item related pages (album, photo, movie, etc)
+- Fixed issue with bottom border not applied to all instances of H1 tag
+- Min footer size set to 4em
+- ADMIN: "Photo: Description Display Mode" option added
+- ADMIN: Added new maintenance operation - "Reset Exif Info"
+
+version 2.1.2
+- Fixed issue with Album thumbs - empty space under
+- Thumb Item's Title Display Mode expanded to be applied to Item's description in Photo page
+- More documentations in CSS files, some movements
+- Some cleanup for Wind color pack
+- Fixed font name typo in screen.css
+- Fixed "Waiting" roller for Wind theme to match background
+- Added "up" button in navigation
+
+version 2.1.1
+- Increased size of Add photo dialog for better display on some lower resolutions.
+- ADMIN: New option: "Thumb: Item's Title Display Mode" - specifies how to display item's title in thumbs : Overlay Bottom Hide 
+
+version 2.1.0
+- Custom Info Block to include item's description
+- Image is centered when "Actual Size" aspect is used for thumbs
+- Added support for color packs - included: greydragon, wind
+- ADMIN: Improved error handling
+- ADMIN: Disable submit button on click to prevent Dbl-click
+- ADMIN: New option: Enable page cache - adds header marker for page to be cached for 60 seconds
+
+version 2.0.1
+- Enable BBCode/HTML support in individual photo descriptions
+- Fixed main menu overlay issue when in top position
+- Theme's credits moved into dedicated method
+- CSS clean up
+- Comments module layout enhancements
+
+version 2.0.0
+- Major redesign of the gallery flow.
+    - Added caption and metadata (Admin/optional) overlay for thumbs.
+    - Added description overlay in individual Photo view (look for "Learn More" marker).
+    - Based on Admin setting, thumbs are adjusted to fit Digital/Film/Actual size.
+- Attempt to fix issue with JS load latency to prevent unhandled AJAX calls
+- Added code protection for theme initialization procedure
+- ADMIN: Thumb Aspect Ratio option. See help section for more info.
+
+version 1.8.2
+- Increased based font size
+- Layout adjusted to match new settings
+- ADMIN: New option - Place Login Link in the Header 
+
+version 1.8.1
+- ADMIN: small adjustments in layout and help info
+- 3rd party module's related CSS moved into contrib.css
+- Adjust user profile screen to match new layout
+- initial design for calendar module
+
+version 1.8.0
+- ADMIN: Major redesign of the layout. Help section added.
+- ADMIN: New option - Show main menu for guest user
+- Minimum required Gallery version set to 30
+- When configured not to use sidebar, theme is switched into 4 columns layout
+
+version 1.7.6
+- Organize module: CSS improvements
+- Fixed issue with Chrome browser
+
+version 1.7.5
+- ADMIN: Added option to reset theme to default state
+- CSS: some size adjustments for dialogs. Added minimum height for overlay to keep dialogs from shrinking.
+
+version 1.7.4
+- ADMIN: Theme Gallery 3 core requirement changed to v.26
+- ADMIN: Most of theme's settings are documented using element's title attribute - hover over to see a description
+- Edit Permissions form redesigned and enlarged to fit more information
+
+version 1.7.3
+- ADMIN: Default states for the theme options are no longer being stored. Please save theme settings at least once to take advantage of a new functionality.
+- Photo Navigator default position is set to Top Only
+
+version 1.7.2
+- Fix in Uploader dialog to keep items inside respected boxes
+- Organize module support has been abandoned. Please use GWT Organize module instead. Added item in Prerequisites Checklist.
+
+version 1.7.1
+- CSS: Fixed visibility of the "Select Photo" button in "Add photo" dialog
+- CSS: Fixed "ghost" line for navigation buttons when zoomed-in in IE
+- Admin: fixed issue with prerequisite check not detecting deleted modules
+- <theme>/views/support folder deprecated. Logic moved into Theme_View extension class for Theme_View_Core
+- Theme Options Page management, generic Page code and BBCode processor moved into Theme_View class
+- HACK: Info block is not displayed if there is no description for the item
+
+version 1.6.4
+- Admin: Added "Show Sidebar for Albums only" option
+- Admin: added error visibility to the requirements validation list
+- Small CSS adjustments: Fixed footer min size issue when no site credit info is displayed; added space between Credits in the footer and Footer text area.
+- Few missing parts from last git sync
+
+version 1.6.3
+- Kohana 2.4 support
+- Support for Movie files view
+- Admin: Allow hide Sidebar Block header
+
+version 1.6.2
+- Admin: Page navigator option changed to use combobox
+- Admin: Added option to hide item description in albums
+
+version 1.6.2
+- Small CSS adjustments.
+- All operation dialogs should be visible now
+- Context menu: "Rotate 90..." items are removed due to an issue with image quality affected by the operation
+- Context menu: "Choose as the album cover" is now properly handled
+
+version 1.6.1
+- Admin: When allowed sidebar position is "Default Only", don't disregard selected Default position
+- Adjust item's toolbar buttons to align properly when side bar position is fixed
+- BBCode parser improved to support stripping of BBCode for Page title and breadcrumbs
+- Fixed issue with main menu missing class declaration not allowing open dialogs
+- Adjust context dialogs to properly show caption info
+- Caption added to Full size Preview
+- "New Comment" form styled
+- Admin: Option to align main menu to the top and Breadcrumbs to the left
+
+version 1.6.0
+- Admin: Fixed issue with "Rebuild thumbs" option in theme admin
+- Admin: Fixed issue with Item's toolbar not properly aligned in Quirks Mode
+- Exif data dialog Layout changes
+- Item context menu improvements:
+    - Fixed issue with submit logic
+    - Layout fixes for context menu dialogs 
+
+version 1.5.8
+- Admin: First release of the Theme admin option. After theme installation, visit Appearance/Theme
+  Options to configure the theme. If you had older version of the theme, initial setup is also required.
+  The following settings are available:
+    - Rows per album page - theme uses 3 columns layout for pictures, therefore default page_size is computed in x3 increments
+    - Thumb size is restricted to 200 and therefore not available for administration
+    - Mark to build resizes/thumbs - allows force rebuilding of images
+    - Show/Hide top/bottom photo navigators
+    - Specify allowed and default sidebar position
+    - Administrator can now specify Copyright message to display in the footer
+    - Site logo is now default to Gallery 3 logo, but admin can provide a path to custom logo.
+    - Admin module validates Theme's requirements (Shadowbox module need to be installed/active)
+- Sidebar session cookie is set to expire in 365 days
+
+version 1.5.7
+- Status message has been moved into header as popup to prevent obstruction of the main view.
+  jQuery is used to fade it out in 10 sec.
+- Improved logic for dialogs on submit
+- Theme related JS has been moved out of the page.html.php
+
+version 1.5.6
+- Fixed issue with tollbar buttons not properly aligned/shown when page is resized.
+- Copyright info moved into DB. To change default settings add [th_greydragon/copyright] into VARS table.
+
+version 1.5.5
+- CSS fixes.
+- Theme adjusted to be compatible with latest Git.
+- Login links are moved into footer.
+- Pagination module redesigned to support new structure of paging data.
+
+version 1.5.4
+- CSS fixes.
+- Added support for Comments block.
+- Improved support for Modal dialogs.
+
+version 1.5.3
+- Updated to match latest git.
+- Exif menu customization is now part of the theme.
+- Sidebar management button is disabled for current mode.
+
+version 1.5.2
+- Code, layout, css cleanup.
+- New thumbs for buttons.
+- First set of Ajax dialogs is ready and now operational: Login, user info, edit album, exit info.
+- Fixed some browser related issues.
\ No newline at end of file
diff --git a/themes/greydragon_old/controllers/greydragon.php b/themes/greydragon_old/controllers/greydragon.php
new file mode 100644
index 0000000..0ecfc4f
--- /dev/null
+++ b/themes/greydragon_old/controllers/greydragon.php
@@ -0,0 +1,14 @@
+<?
+
+class GreyDragon_Controller extends Controller {
+
+  public function custom_css() {
+
+    // Draw the page.
+//    $template = new Theme_View("gd_custom.css", "other", "Custom_CSS");
+
+    print $template;
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/themes/greydragon_old/css/base.css b/themes/greydragon_old/css/base.css
new file mode 100644
index 0000000..4d6288a
--- /dev/null
+++ b/themes/greydragon_old/css/base.css
@@ -0,0 +1,321 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules - Main CSS ruleset
+ *
+ * Color rules for font/background/lines can be found in dedicated colorpack files
+ */
+        
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* base.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+body { font-family: Arial, verdana, sans-serif; font-size: 0.9em; }
+
+a { text-decoration: none; outline: none; -moz-outline-style: none; }
+a:focus, a:active, a:hover { text-decoration: none; outline: none; }
+img { border: none; }
+p { text-indent: 0;  }
+ul { list-style: none none; padding-left: 0; }
+
+h1 { font-weight: bold; font-size: 1.1em; padding-bottom: 1px; min-height: 1.1em; }
+h2 { font-weight: bold; font-size: 1.1em; min-height: 1.1em; }
+h3 { font-weight: bold; }
+h4 { font-weight: bold; }
+h5 { font-weight: bold; }
+
+.txtright { text-align: right; }
+.g-metadata { overflow: hidden; }
+.g-avatar { float: right; }
+.g-hide { display: none; }
+
+.ui-icon { display: inline-block; zoom: 1; width: 16px; height: 15px; }
+.ui-icon-first { background-position: -162px -178px; }
+.ui-icon-first-d { background-position: -162px -162px; }
+.ui-icon-prev { background-position: -178px -178px; }
+.ui-icon-prev-d { background-position: -178px -162px; }
+.ui-icon-parent { background-position: -226px -178px; }
+.ui-icon-parent-d { background-position: -226px -162px; }
+.ui-icon-next { background-position: -194px -178px; }
+.ui-icon-next-d { background-position: -194px -162px; }
+.ui-icon-last { background-position: -210px -178px; }
+.ui-icon-last-d { background-position: -210px -162px; }
+.ui-icon-signal-diag { background-position: -16px  -178px; }
+.ui-icon-info { background-position: -16px  -144px; }
+.ui-icon-plus { background-position: -14px  -129px; }
+.ui-icon-minus { background-position: -46px  -129px; }
+.ui-icon-note { background-position: -66px  -98px;  }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-left .ui-icon { float: left; margin-right: .2em; }
+.ui-icon-right .ui-icon { float: right; margin-left: .2em; }
+
+/* base.css - Inline layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-inline li { float: left; }
+
+/* base.css - Header ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-header { height: 90px; padding: 0; font-size: 0.9em; }
+#g-logo { position: absolute; top: 8px; left: 16px; }
+
+.g-breadcrumbs { position: absolute; background-color: transparent; }
+.g-breadcrumbs.g-default     { bottom: 4px; right: 14px; }
+.g-breadcrumbs.g-bottom-left { bottom: 4px; left: 21.4em; }
+.g-breadcrumbs.g-top-right   { top: 4px; right: 14px; }
+.g-breadcrumbs.g-top-left    { top: 4px; left: 21.4em; }
+
+.g-breadcrumbs li { display: inline; } 
+.g-breadcrumbs li.g-first { background-image: none; padding-left: 0; }
+.rtl .g-breadcrumbs .g-first { background-image: none; padding-left: 0; }
+.g-breadcrumbs li.g-active { padding-right: 0; }
+
+#g-header .g-message-block { position: absolute; z-index: 10; min-width: 30em; padding: 0; right: 20em; top: 34px; overflow: hidden; font: bold 9pt Arial, verdana, sans-serif; text-align: center; }
+#g-header #g-login-menu { position: absolute; top: 0.2em; right: 1em; background-color: transparent; display: none; }
+#g-site-status li { padding: .3em .3em .3em 30px; }
+
+/* base.css - Main ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-main { display: block; margin: 0; }
+#g-main-in { display: block; position: relative; }
+
+#g-column-center, #g-column-centerleft { padding: 6px 6px 6px 10px; }
+#g-column-centerfull { padding: 6px 12px 6px 10px; }
+#g-column-centerright { padding: 6px 10px 6px 6px; }
+#g-column-left { padding: 6px 4px 6px 10px; }
+#g-column-right { padding: 6px 10px 6px 4px; }
+
+/* base.css - Footer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-footer { padding: 6px 6px 6px 14px; zoom: 1; font-size: 0.9em; }
+#g-footer ul { float: left; padding: 0; text-align: left; }
+#g-footer li { padding: 0 0 2px 0; }
+
+#g-footer #g-login-menu { position: absolute; bottom: 0.5em; right: 1em; background-color: transparent; display: none; }
+
+#g-login-menu li { display: inline; padding-left: 1.2em; }
+#g-logout-link { float: none; margin-right: 0; } 
+
+#g-copyright { font-size: x-small; }
+#g-footer #g-footer-rightside { float: right; padding-right: 6px; text-align: right; }
+#g-credits { margin-right: 14px; }
+#g-credits li.g-branding a { float: left; }
+#g-credits .g-first { display: none; }
+#g-gallery-logo { display: block; width: 70px; height: 18px; background: transparent url('../images/gallery.png') no-repeat; }
+#g-theme-logo { display: block; width: 70px; height: 18px; }
+
+/* base.css - Mini Mode ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.viewmode-mini #g-header { height: 2.3em; }
+.viewmode-mini #g-footer { display: none; }
+
+/* base.css - Pagination ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-paginator { display: inline-block; width: 100%; padding: 4px 0 0 0; zoom: 1; }
+.g-paginator li { display: inline; float: left; margin-left: 0; zoom: 1; }
+.g-paginator a { padding: 0; }
+
+.g-paginator .g-pagination { width: 80%; font-size: 0.8em; }
+.g-paginator .g-navigation { text-align: right; width: 20%; }
+
+/* base.css - Album grid ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-album-grid { padding: 6px 0 0 0; width: 100%; display: inline-block; margin: 0px auto; }
+#g-album-grid .g-item { position: relative; float: left; margin: 4px 2px 4px 0; min-width: 212px; zoom: 1; }
+.g-extended #g-album-grid .g-item { min-width: 314px; }
+.g-column-2 #g-album-grid .g-item { width: 48%; margin-right: 0; }
+.g-column-3 #g-album-grid .g-item { width: 30%; margin-right: 0; }
+.g-column-4 #g-album-grid .g-item { width: 23%; margin-right: 0; }
+.g-column-5 #g-album-grid .g-item { width: 18%; margin-right: 0; }
+#g-album-grid .g-item p { text-align: center; }
+#g-album-grid h2 { position: absolute; top: 164px; left: 12px; width: 150px; font: 100%/100% Arial, Helvetica, sans-serif; }
+#g-album-grid h2 a { display: block; margin-top: 4px; font: bold 0.8em Arial, Helvetica, Verdana, Sans-Serif; letter-spacing: 0.1em; text-transform: uppercase; min-height: 2em; }
+
+/* base.css - Thumbs : Common ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-thumbslide { font-size: 0.9em; width: 208px; min-height: 139px; padding-top: 6px; padding-left: 6px; overflow: hidden; text-align: left; }
+.g-thumbtype-sqr .g-thumbslide { height: 208px; }                                                                           
+.g-thumbtype-flm .g-thumbslide { height: 141px; }
+.g-thumbtype-dgt .g-thumbslide { height: 158px; }
+.g-thumbtype-wd  .g-thumbslide  { height: 120px; }
+
+.g-extended .g-thumbslide { width: 308px; }
+.g-extended .g-thumbtype-sqr .g-thumbslide { height: 308px; }
+.g-extended .g-thumbtype-flm .g-thumbslide { height: 207px; }
+.g-extended .g-thumbtype-dgt .g-thumbslide { height: 233px; }
+.g-extended .g-thumbtype-wd  .g-thumbslide { height: 176px; }
+
+.g-thumbcrop { overflow: hidden; position: relative; width: 200px; min-height: 112px; }
+.g-thumbtype-sqr .g-thumbcrop { height: 200px; }
+.g-thumbtype-flm .g-thumbcrop { height: 133px; }
+.g-thumbtype-dgt .g-thumbcrop { height: 150px; }
+.g-thumbtype-wd  .g-thumbcrop { height: 112px; }
+
+.g-extended .g-thumbcrop { width: 300px; }
+.g-extended .g-thumbtype-sqr .g-thumbcrop { height: 300px; }
+.g-extended .g-thumbtype-flm .g-thumbcrop { height: 199px; }
+.g-extended .g-thumbtype-dgt .g-thumbcrop { height: 225px; }
+.g-extended .g-thumbtype-wd  .g-thumbcrop { height: 168px; }
+
+.g-album .g-description strong { padding-left: 16px; }
+
+/* Force size of the link to fill thumbcrop */
+
+.g-thumbcrop a.g-thumblink { display: block; position: relative; min-width: 200px; }
+.g-thumbtype-sqr a.g-thumblink { min-height: 200px; }
+.g-thumbtype-flm a.g-thumblink { min-height: 133px; }
+.g-thumbtype-dgt a.g-thumblink { min-height: 150px; }
+.g-thumbtype-wd  a.g-thumblink { min-height: 112px; }
+
+.g-extended .g-thumbcrop a.g-thumblink { min-width: 300px; }
+.g-extended .g-thumbtype-sqr a.g-thumblink { min-height: 300px; }
+.g-extended .g-thumbtype-flm a.g-thumblink { min-height: 200px; }
+.g-extended .g-thumbtype-dgt a.g-thumblink { min-height: 225px; }
+.g-extended .g-thumbtype-wd  a.g-thumblink { min-height: 168px; }
+
+/* base.css - Thumbs : Overlay ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-thumbslide .g-description { display: none; position: absolute; left: 6px; top: 6px; min-height: 24px; width: 184px; overflow: hidden; z-index: 3; text-align: left; padding: 2px 8px; font-size: 0.85em; margin: 10px 0 1px 11px; }
+.g-extended .g-thumbslide .g-description { width: 284px; }
+.g-thumbslide:hover .g-description { display: block; }
+.g-thumbslide .g-description li { display: inline; padding-right: 0.8em; }
+.g-thumbslide .g-description .g-title { display: block; font-weight: bold; font-size: 1.1em; letter-spacing: 0.1em; text-transform: uppercase; padding-top: 3px; }  
+.g-album .g-thumbslide .g-description .g-title { padding-left: 24px; }
+
+.g-thumbslide .g-description.g-overlay-top    { display: block; }
+.g-thumbslide .g-description.g-overlay-bottom { display: block; top: auto; bottom: 6px; margin-bottom: 10px; }
+
+.g-thumbslide .g-metadata    { display: none; position: absolute; left: 6px; bottom: 6px; padding: 2px 4px 2px 10px; width: 186px; margin: 10px 0 11px 11px; }
+.g-thumbslide .g-metadata li { padding: 0; margin: 0; font-size: 0.9em; }
+.g-extended .g-thumbslide .g-metadata { width: 286px; }
+.g-thumbslide:hover .g-metadata { display: block; }
+
+/* base.css - Thumbs : Expanded View mode ~~~~~~~~~~~~~~*/
+
+.g-expanded .g-thumbslide { font-size: 0.9em; width: 208px; min-height: 139px; padding-top: 6px; padding-left: 6px; line-height: 1.2em; overflow: hidden; }
+.g-thumbtype-sqr.g-expanded .g-thumbslide { height: 238px; }
+.g-thumbtype-flm.g-expanded .g-thumbslide { height: 171px; }
+.g-thumbtype-dgt.g-expanded .g-thumbslide { height: 188px; }
+.g-thumbtype-wd.g-expanded  .g-thumbslide { height: 150px; }
+
+.g-extended .g-expanded .g-thumbslide                { width: 308px; }
+.g-extended .g-thumbtype-sqr.g-expanded .g-thumbslide { height: 346px; }
+.g-extended .g-thumbtype-flm.g-expanded .g-thumbslide { height: 244px; }
+.g-extended .g-thumbtype-dgt.g-expanded .g-thumbslide { height: 270px; }
+.g-extended .g-thumbtype-wd.g-expanded  .g-thumbslide { height: 214px; }
+
+.g-expanded .g-thumbslide .g-description { position: static; display: block; }
+.g-expanded .g-thumbslide .g-description li { display: inline; padding-right: 0.8em; }
+.g-expanded .g-thumbslide .g-description .g-title { display: block; font-weight: bold; font-size: 1.1em; letter-spacing: 0.1em; text-transform: uppercase; }  
+.g-album.g-expanded .g-thumbslide .g-description .g-title { padding-left: 24px; }
+
+.g-expanded .g-thumbslide .g-description.g-overlay-bottom { width: 192px; }
+.g-expanded .g-thumbslide .g-metadata { bottom: 10px; }
+.g-expanded .g-thumbslide .g-metadata li { padding: 0; margin: 0; font-size: 0.9em; }
+.g-expanded .g-thumbslide:hover .g-metadata { display: block; bottom: 40px; }
+ 
+/* base.css - Photo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-item { float: left; height: 100%; width: 100%; }
+#g-photo { padding: 6px 0 6px 0; text-align: center; float: left; height: 100%; width: 100%; }
+div.g-resize { position: relative; left: 50%; float: left; padding: 5px; font-size: 0.9em; }
+div.g-resize>a { float: left; overflow: hidden; }
+div.g-resize>a img { float: left; }
+
+div.g-resize .g-description { display: none; position: absolute; left: 5px; text-align: left; padding: 10px; }
+div.g-resize .g-description strong { display: block; margin-bottom: 5px; text-transform: uppercase; }
+div.g-resize .g-description.g-align-top { top: 0px; margin-top: 5px; }
+div.g-resize .g-description.g-align-bottom { bottom: 4px; }
+div.g-resize .g-description.g-align-static { display: block; }
+div.g-resize:hover .g-description { display: block; }
+
+div.g-resize .g-more { display: block; position: absolute; right: 16px; padding: 4px 8px; }
+div.g-resize:hover .g-more { display: none; visibility: hidden; }
+div.g-resize .g-more.g-align-top { top: 16px; }
+div.g-resize .g-more.g-align-bottom { bottom: 20px; }
+
+.ul-table { text-align: center; margin: 0px auto; padding: 0; list-style-type: none; clear: both; }
+.ul-table li { float: left; text-align: center; } 
+
+#g-info { display: inline-block; width: 100%; }
+#g-info .g-description { margin-top: .4em; margin-bottom: .4em; padding: .5em 1em; }
+#g-movie { padding: 6px 0 6px 6px; position: relative; }
+
+#g-item a.g-movie { display: block; margin: 0 auto; }
+
+.g-description .g-metadata { padding: 0.4em 0 0 0; font-size: 0.8em; }
+.g-description .g-metadata li { display: inline; padding-right: 1em; }
+
+/* base.css - Sidebar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* base.css - Sidebar : Common ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-block { margin-bottom: 4px; padding-bottom: 4px; position: relative; clear: both; } 
+.g-block h2 { padding: 6px 4px 6px 8px; font-size: 1em; }
+.g-block-content { margin: 6px 6px 0 6px; display: block; zoom: 1; }
+
+#g-column-top .g-block, #g-column-bottom .g-block { float: left; clear: none; width: 240px; margin-left: 10px; }
+#g-column-top .g-toolbar, #g-column-bottom .g-toolbar { margin-bottom: 0.5em; }
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { display: none; }
+
+/* base.css - Sidebar : Buttons ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-viewformat { z-index: 5; position: absolute; padding: 0; top: 6px; right: 10px; }
+#g-viewformat li { float: left; margin-right: 2px; }
+#g-viewformat span { display: block; width: 17px; height: 15px; line-height: 1px; text-indent: -900em; background-repeat: no-repeat; }
+#g-viewformat .g-sidebar-left   { background-position: -128px -210px; }
+#g-viewformat .g-sidebar-top    { background-position: -148px -210px; }
+#g-viewformat .g-sidebar-full   { background-position: -168px -210px; }
+#g-viewformat .g-sidebar-right  { background-position: -188px -210px; }
+#g-viewformat .g-sidebar-bottom { background-position: -208px -210px; }
+#g-viewformat .g-sidebar-left:hover,  #g-viewformat .g-sidebar-left.g-current  { background-position: -128px -225px; }
+#g-viewformat .g-sidebar-top:hover,   #g-viewformat .g-sidebar-top.g-current   { background-position: -148px -225px; }
+#g-viewformat .g-sidebar-full:hover,  #g-viewformat .g-sidebar-full.g-current  { background-position: -168px -225px; }
+#g-viewformat .g-sidebar-right:hover, #g-viewformat .g-sidebar-right.g-current { background-position: -188px -225px; }
+#g-viewformat .g-sidebar-bottom:hover,#g-viewformat .g-sidebar-bottom.g-current{ background-position: -208px -225px; }
+
+#g-view-menu { position: absolute; top: 6px; right: 106px; height: 16px; z-index: 5; zoom: 1; margin: 0 0 6px 0; padding: 0 0 4px 0; }
+#g-view-menu.g-buttonset-shift { right: 6px; }
+.g-toolbar { margin: 0 0 4px 0; } 
+.g-menu { margin: 0; padding: 0; text-align: left; }
+.g-menu li { display: inline; }
+
+.g-menu-element,
+.g-menu-link { display: inline; float: left; margin-right: 4px; background-repeat: no-repeat; background-position: center top; }
+
+.g-buttonset .g-menu-link { text-indent: -99999px; width: 22px; height: 15px; overflow: hidden; }
+
+#g-slideshow-link { background-position: -103px -210px; } 
+#g-slideshow-link:hover { background-position: -103px -225px; }
+
+.g-fullsize-link:hover, #g-exifdata-link:hover { background-position: left bottom; }
+
+/* base.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-quote { float: left; width: 300px; padding-top: 6px; font-size: 110%; }
+#g-rootpage-roll  { float: right; text-align: center; z-index: 1; position: relative; width: 800px; height: 540px; }
+#g-rootpage-link  { z-index: 10; position: absolute; height: 540px; width: 800px; top: 0; left: 0; cursor: pointer; }
+#g-rootpage-roll span { z-index: 12; display: block; position: absolute; right: 16px; padding: 4px 8px; top: 20px; cursor: pointer; font-size: 0.9em; }
+#g-rootpage-roll.g-full { margin-left: auto; margin-right: auto; float: none; }
+
+/* base.css - Large toolbar icons support ~~~~~~~~~~~~~~*/
+
+.g-toolbar-large .g-buttonset .g-menu-link { width: 26px; height: 22px; }
+.g-toolbar-large h1 { line-height: 24px; height: 24px; }
+.g-toolbar-large #g-calendarview-link:hover { background-position: top center; }
+.g-toolbar-large #g-viewformat { top: 9px; }
+
+.g-toolbar-large .g-navigation .ui-icon { width: 23px; height: 22px; }
+.g-toolbar-large .ui-icon-first    { background-position: 0px -240px; }
+.g-toolbar-large .ui-icon-first-d  { background-position: 0px -263px; }
+.g-toolbar-large .ui-icon-prev     { background-position: -23px -240px; }
+.g-toolbar-large .ui-icon-prev-d   { background-position: -23px -263px; }
+.g-toolbar-large .ui-icon-parent   { background-position: -47px -240px; }
+.g-toolbar-large .ui-icon-parent-d { background-position: -47px -263px; }
+.g-toolbar-large .ui-icon-next     { background-position: -70px -240px; }
+.g-toolbar-large .ui-icon-next-d   { background-position: -70px -263px; }
+.g-toolbar-large .ui-icon-last     { background-position: -93px -240px; }
+.g-toolbar-large .ui-icon-last-d   { background-position: -93px -263px; }
+
+/* base.css - Upload dialog ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-status li.g-success { background: url('../images/ico-success.png') transparent no-repeat .4em 50%; }
+#g-add-photos-status li.g-error   { background: url('../images/ico-error.png') transparent no-repeat .4em 50%; color: #f00; }
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/css/colors.css b/themes/greydragon_old/css/colorpacks/blackhawk/css/colors.css
new file mode 100644
index 0000000..d2cbb15
--- /dev/null
+++ b/themes/greydragon_old/css/colorpacks/blackhawk/css/colors.css
@@ -0,0 +1,170 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: SlateBlue
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #101010; }
+body { color: #8C8C8C; background: #101010; }
+
+h1 { border-bottom: #424242 1px solid; }
+a { color: #6392CF !important; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png') no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-header { border: #424242 1px solid; }
+#g-header .g-message-block { border: 1px #888 solid; background-color: #AAA; color: #000; }
+#g-main { border-left: #424242 1px solid; border-right: #424242 1px solid; }
+.viewmode-mini #g-main { border-bottom: #424242 1px solid; }
+
+#g-footer { font-size: 10px; border: #424242 1px solid; }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top, #g-column-bottom { border-left: #424242 1px solid; border-right: #424242 1px solid; }
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info .g-description { border: #424242 1px solid; }
+
+.g-thumbcrop { border-color: #424142; }
+.g-thumbslide, .g-album .g-thumbslide { background: #212021; border-color: #424142 #000 #000 #424142; }
+.g-thumbslide .g-description { color: #fff; border-top: 1px solid #424142; border-bottom: 1px solid #424142; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-album.g-expanded .g-thumbslide .g-description { background: transparent url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-album .g-thumbslide .g-description { background: #1E1E1E url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-thumbslide .g-metadata { border-top: 1px solid #424142; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-expanded .g-thumbslide .g-metadata { border-top: 1px solid #424142; background: #1E1E1E; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { background: #212021; border-top: 1px solid #424142; border-left: 1px solid #424142; border-right: 1px solid #000; border-bottom: 1px solid #000; }
+div.g-resize .g-description { color: #fff; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #999; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #999; }
+div.g-resize .g-more { border: 1px solid #999; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+.g-movie  { border: 1px solid #888; padding: 5px; background: #555; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block h2 { border-top: 1px solid #424142; border-left: 1px solid #424142; border-right: 1px solid #000; border-bottom: 1px solid #000; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #424142; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #101415; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #101415 url('../images/section.png') repeat-x; }
+#sb-counter a { color: #fff !important; font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #101010; border: #303030 1px solid; }
+#g-add-photos-status { background-color: #101010; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #888 1px solid; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile .g-avatar { border: 1px solid #888; background: #555; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li a:hover { color: #000000; background-color: #303030; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #303030; border-bottom: #000000 1px solid; }
+#g-site-menu li ul { border: #000000 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #212121; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #303030; }
+
+#g-site-menu.g-bar { border: #000000 1px solid; background-color: #212121; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #181818 none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #303030; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #303030 1px solid; }
+#g-exif-data .g-even { background-color: #404040; }
+#g-exif-data .g-odd { background-color: #303030; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #424242; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #888; background: #555; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #424242; color: #8C8C8C; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #424242; }
+#g-comment-form { border: 1px dotted #424242; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #8C8C8C; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #424242; color: #8C8C8C; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background: url(../images/section.png) repeat-x; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #424242; }
+.ui-widget-content { border: 1px solid #303030; background-color: #101010; color: #8C8C8C; }
+.ui-progressbar .ui-progressbar-value { background: #424242; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/ajax-loading.gif b/themes/greydragon_old/css/colorpacks/blackhawk/images/ajax-loading.gif
new file mode 100644
index 0000000..0996045
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/ajax-loading.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/colorpack.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/colorpack.png
new file mode 100644
index 0000000..96f5372
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/colorpack.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-album.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-album.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-error.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-error.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-help.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-help.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-info.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-warning.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/ico-warning.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/loading-large.gif b/themes/greydragon_old/css/colorpacks/blackhawk/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/loading-large.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/loading-small.gif b/themes/greydragon_old/css/colorpacks/blackhawk/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/loading-small.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/search.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/search.png
new file mode 100644
index 0000000..1bfa411
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/search.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/ui-icons.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/ui-icons.png
new file mode 100644
index 0000000..a71d438
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/ui-icons.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/view-calendar-b.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-calendar-b.png
new file mode 100644
index 0000000..c5a1248
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-calendar-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/view-calendar.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-calendar.png
new file mode 100644
index 0000000..bd1d03c
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-calendar.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/view-comments-b.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-comments-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/view-comments.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-comments.png
new file mode 100644
index 0000000..293c587
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-comments.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/view-fullsize-b.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-fullsize-b.png
new file mode 100644
index 0000000..f659d79
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-fullsize-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/view-fullsize.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-fullsize.png
new file mode 100644
index 0000000..ed76257
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-fullsize.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/view-info-b.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-info-b.png
new file mode 100644
index 0000000..880d3e8
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-info-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/view-info-o.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-info-o.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/view-info.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-info.png
new file mode 100644
index 0000000..521439c
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/blackhawk/images/view-slideshow-b.png b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/blackhawk/images/view-slideshow-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/css/colors.css b/themes/greydragon_old/css/colorpacks/carbon/css/colors.css
new file mode 100644
index 0000000..9211767
--- /dev/null
+++ b/themes/greydragon_old/css/colorpacks/carbon/css/colors.css
@@ -0,0 +1,188 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: Carbon
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #333; }
+body { color: #999; background-color: #333; }
+
+h1 { border-bottom: #6f6f6f 1px solid; }
+a { color: #999 !important; font-weight: bold; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png') no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-header .g-message-block { border: 1px #888 solid; background-color: #AAA; color: #000; }
+#g-main { background-color: #3f3f3f; margin-left: 10px; margin-right: 10px; }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top { border-top: #737373 1px solid; }
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info .g-description { border: #6f6f6f 1px solid; }
+
+.g-thumbslide { background: #555; border-color: #303E43; }
+.g-album .g-thumbslide { border-color: #6f6f6f; }
+.g-thumbcrop  { border-color: #303E43; }
+
+.g-thumbslide .g-description { color: #fff; border-top: 1px solid #303e43; border-bottom: 1px solid #303e43; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-album.g-expanded .g-thumbslide .g-description { background: transparent url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-album .g-thumbslide .g-description { background: #3f3f3f url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-thumbslide .g-metadata { border-top: 1px solid #303e43; background: #3f3f3f; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; color: #FFF; }
+.g-expanded .g-thumbslide .g-metadata { border-top: 1px solid #303e43; background: #3f3f3f; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: 1px solid #888; background: #555; }
+div.g-resize .g-description { color: #fff; background: #3f3f3f; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #999; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #999; }
+div.g-resize .g-more { border: 1px solid #999; background: #3f3f3f; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-movie  { border: 1px solid #888; padding: 5px; background: #555; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block { border: 1px solid #6f6f6f; } 
+
+.g-block h2 { background-color: rgb(51, 51, 51); }
+#g-column-bottom .g-block h2 { background-color: rgb(41, 41, 41); }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #999; background: #3f3f3f; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li a:hover { color: #000000; background-color: #333; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #333; border-bottom: #000000 1px solid; }
+#g-site-menu li ul { border: #000000 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #333; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #ddf2ff; }
+
+#g-site-menu.g-bar { border: #000000 1px solid; background-color: #333; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #333 none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #ddf2ff; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #101415; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background-color: #333; }
+#sb-counter a { color: #fff !important; font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #101010; border: #303030 1px solid; }
+#g-add-photos-button { border: #303030 1px solid; color: #bbb; }
+#g-add-photos-status { background-color: #101010; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile .g-avatar { border: 1px solid #888; background: #555; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li a:hover { color: #000000; background-color: #303030; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #303030; border-bottom: #000000 1px solid; }
+#g-site-menu li ul { border: #000000 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #212121; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #303030; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #181818 none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #303030; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #303030 1px solid; }
+#g-exif-data .g-even { background-color: #404040; }
+#g-exif-data .g-odd { background-color: #303030; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #737373; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #888; background: #555; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #737373; }
+#g-comment-form { border: 1px dotted #737373; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #737373; color: #BBB; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background: url(../images/section.png) repeat-x; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #333 url('../images/section.png') repeat-x; }
+.ui-widget-content { border: 1px solid #303030; background-color: #333; color: #bbb; }
+.ui-progressbar .ui-progressbar-value { background: #737373; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #737373 1px solid; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/ajax-loading.gif b/themes/greydragon_old/css/colorpacks/carbon/images/ajax-loading.gif
new file mode 100644
index 0000000..0996045
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/ajax-loading.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/colorpack.png b/themes/greydragon_old/css/colorpacks/carbon/images/colorpack.png
new file mode 100644
index 0000000..96f5372
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/colorpack.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/ico-album.png b/themes/greydragon_old/css/colorpacks/carbon/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/ico-album.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/ico-error.png b/themes/greydragon_old/css/colorpacks/carbon/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/ico-error.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/ico-help.png b/themes/greydragon_old/css/colorpacks/carbon/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/ico-help.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/ico-info.png b/themes/greydragon_old/css/colorpacks/carbon/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/ico-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/ico-warning.png b/themes/greydragon_old/css/colorpacks/carbon/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/ico-warning.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/loading-large.gif b/themes/greydragon_old/css/colorpacks/carbon/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/loading-large.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/loading-small.gif b/themes/greydragon_old/css/colorpacks/carbon/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/loading-small.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/search.png b/themes/greydragon_old/css/colorpacks/carbon/images/search.png
new file mode 100644
index 0000000..1bfa411
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/search.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/section.png b/themes/greydragon_old/css/colorpacks/carbon/images/section.png
new file mode 100644
index 0000000..8180ecb
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/section.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/ui-icons.png b/themes/greydragon_old/css/colorpacks/carbon/images/ui-icons.png
new file mode 100644
index 0000000..ef92612
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/ui-icons.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/view-calendar-b.png b/themes/greydragon_old/css/colorpacks/carbon/images/view-calendar-b.png
new file mode 100644
index 0000000..c5a1248
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/view-calendar-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/view-calendar.png b/themes/greydragon_old/css/colorpacks/carbon/images/view-calendar.png
new file mode 100644
index 0000000..bd1d03c
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/view-calendar.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/view-comments-b.png b/themes/greydragon_old/css/colorpacks/carbon/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/view-comments-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/view-comments.png b/themes/greydragon_old/css/colorpacks/carbon/images/view-comments.png
new file mode 100644
index 0000000..293c587
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/view-comments.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/view-fullsize-b.png b/themes/greydragon_old/css/colorpacks/carbon/images/view-fullsize-b.png
new file mode 100644
index 0000000..f659d79
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/view-fullsize-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/view-fullsize.png b/themes/greydragon_old/css/colorpacks/carbon/images/view-fullsize.png
new file mode 100644
index 0000000..ed76257
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/view-fullsize.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/view-info-b.png b/themes/greydragon_old/css/colorpacks/carbon/images/view-info-b.png
new file mode 100644
index 0000000..880d3e8
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/view-info-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/view-info-o.png b/themes/greydragon_old/css/colorpacks/carbon/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/view-info-o.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/view-info.png b/themes/greydragon_old/css/colorpacks/carbon/images/view-info.png
new file mode 100644
index 0000000..521439c
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/view-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/carbon/images/view-slideshow-b.png b/themes/greydragon_old/css/colorpacks/carbon/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/carbon/images/view-slideshow-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/css/colors.css b/themes/greydragon_old/css/colorpacks/greydragon/css/colors.css
new file mode 100644
index 0000000..241dd23
--- /dev/null
+++ b/themes/greydragon_old/css/colorpacks/greydragon/css/colors.css
@@ -0,0 +1,174 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: GreyDragon - Default color pack
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #1A2022; }
+body { color: #BBB; background: #1A2022; }
+
+h1 { border-bottom: #737373 1px solid; }
+a { color: #6392CF !important; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png')  no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-header { border-left: #10151c 1px solid; border-right: #10151c 1px solid; background: url(../images/background-top.gif) #1A2022 repeat-x; }
+#g-header .g-message-block { border: 1px #888 solid; background-color: #AAA; color: #000; }
+#g-main { border-left: #10151c 1px solid; border-right: #10151c 1px solid; background: url(../images/background-bottom.gif) #1A2022 repeat-x; }
+.viewmode-mini #g-main { border-bottom: #10151c 1px solid; }
+#g-footer { background: url(../images/footer.png) #1A2022 repeat-x top !important; }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top { background: url(../images/background-bottom.gif) #1A2022 repeat-x; border: #10151C 1px solid; }
+#g-column-bottom { background-color: #1a2022; border: #10151C 1px solid; }
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info .g-description { border: #737373 1px solid; }
+
+.g-thumbslide { background: #1E1E1E url('../images/image-thumb.gif') repeat-x; border-color: #303E43; }
+.g-album .g-thumbslide { border-color: #43565B; }
+.g-thumbcrop  { border-color: #303E43; }
+.g-thumbslide .g-description { color: #fff; border-top: 1px solid #303e43; border-bottom: 1px solid #303e43; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-album.g-expanded .g-thumbslide .g-description { background: transparent url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-album .g-thumbslide .g-description { background: #1E1E1E url(../images/ico-album.png) no-repeat 8px 4px; }
+.g-thumbslide .g-metadata { border-top: 1px solid #303e43; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-expanded .g-thumbslide .g-metadata { border-top: 1px solid #303e43; background: #1E1E1E; }
+.g-album .g-thumbslide, .g-photo .g-thumbslide { background-color: #1E1E1E; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: 1px solid #888; background: #555; }
+div.g-resize .g-description { color: #fff; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #999; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #999; }
+div.g-resize .g-more { border: 1px solid #999; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+.g-movie  { border: 1px solid #888; padding: 5px; background: #555; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block { border: 1px solid #737373; background-color: #101415; } 
+.g-block h2 { background: url(../images/section.png) repeat-x; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #999; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background: #101415 url('../images/ajax-loading.gif') no-repeat center center; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #101415 url('../images/section.png') repeat-x; }
+#sb-counter a { color: #fff !important; font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #101010; border: #303030 1px solid; }
+#ag-add-photos-button { border: #303030 1px solid; color: #bbb; }
+#g-add-photos-status { background-color: #101010; border: #303030 1px solid; }
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile .g-avatar { border: 1px solid #888; background: #555; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li a:hover { color: #000000; background-color: #303030; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #303030; border-bottom: #000000 1px solid; }
+#g-site-menu li ul { border: #000000 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #212121; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #303030; }
+
+#g-site-menu.g-bar { border: #000000 1px solid; background-color: #212121; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #181818 none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #303030; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #303030 1px solid; }
+#g-exif-data .g-even { background-color: #404040; }
+#g-exif-data .g-odd { background-color: #303030; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #737373; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #888; background: #555; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #737373; }
+#g-comment-form { border: 1px dotted #737373; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #737373; color: #BBB; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background: url(../images/section.png) repeat-x; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #101415 url('../images/section.png') repeat-x; }
+.ui-widget-content { border: 1px solid #303030; background-color: #1a2022; color: #bbb; }
+.ui-progressbar .ui-progressbar-value { background: #737373; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #888 1px solid; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/ajax-loading.gif b/themes/greydragon_old/css/colorpacks/greydragon/images/ajax-loading.gif
new file mode 100644
index 0000000..0996045
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/ajax-loading.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/background-bottom.gif b/themes/greydragon_old/css/colorpacks/greydragon/images/background-bottom.gif
new file mode 100644
index 0000000..1f675f3
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/background-bottom.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/background-top.gif b/themes/greydragon_old/css/colorpacks/greydragon/images/background-top.gif
new file mode 100644
index 0000000..ec70a64
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/background-top.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/background.gif b/themes/greydragon_old/css/colorpacks/greydragon/images/background.gif
new file mode 100644
index 0000000..b808356
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/background.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/colorpack.png b/themes/greydragon_old/css/colorpacks/greydragon/images/colorpack.png
new file mode 100644
index 0000000..b4bd4ca
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/colorpack.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/footer.png b/themes/greydragon_old/css/colorpacks/greydragon/images/footer.png
new file mode 100644
index 0000000..04d5ee5
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/footer.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/ico-album.png b/themes/greydragon_old/css/colorpacks/greydragon/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/ico-album.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/ico-error.png b/themes/greydragon_old/css/colorpacks/greydragon/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/ico-error.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/ico-help.png b/themes/greydragon_old/css/colorpacks/greydragon/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/ico-help.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/ico-info.png b/themes/greydragon_old/css/colorpacks/greydragon/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/ico-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/ico-warning.png b/themes/greydragon_old/css/colorpacks/greydragon/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/ico-warning.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/image-thumb.gif b/themes/greydragon_old/css/colorpacks/greydragon/images/image-thumb.gif
new file mode 100644
index 0000000..bc3a192
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/image-thumb.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/loading-large.gif b/themes/greydragon_old/css/colorpacks/greydragon/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/loading-large.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/loading-small.gif b/themes/greydragon_old/css/colorpacks/greydragon/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/loading-small.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/search.png b/themes/greydragon_old/css/colorpacks/greydragon/images/search.png
new file mode 100644
index 0000000..1bfa411
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/search.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/section.png b/themes/greydragon_old/css/colorpacks/greydragon/images/section.png
new file mode 100644
index 0000000..8180ecb
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/section.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/ui-icons.png b/themes/greydragon_old/css/colorpacks/greydragon/images/ui-icons.png
new file mode 100644
index 0000000..41ce8ff
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/ui-icons.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/view-calendar-b.png b/themes/greydragon_old/css/colorpacks/greydragon/images/view-calendar-b.png
new file mode 100644
index 0000000..c5a1248
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/view-calendar-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/view-calendar.png b/themes/greydragon_old/css/colorpacks/greydragon/images/view-calendar.png
new file mode 100644
index 0000000..bd1d03c
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/view-calendar.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/view-comments-b.png b/themes/greydragon_old/css/colorpacks/greydragon/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/view-comments-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/view-comments.png b/themes/greydragon_old/css/colorpacks/greydragon/images/view-comments.png
new file mode 100644
index 0000000..293c587
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/view-comments.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/view-fullsize-b.png b/themes/greydragon_old/css/colorpacks/greydragon/images/view-fullsize-b.png
new file mode 100644
index 0000000..f659d79
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/view-fullsize-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/view-fullsize.png b/themes/greydragon_old/css/colorpacks/greydragon/images/view-fullsize.png
new file mode 100644
index 0000000..ed76257
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/view-fullsize.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/view-info-b.png b/themes/greydragon_old/css/colorpacks/greydragon/images/view-info-b.png
new file mode 100644
index 0000000..880d3e8
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/view-info-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/view-info-o.png b/themes/greydragon_old/css/colorpacks/greydragon/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/view-info-o.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/view-info.png b/themes/greydragon_old/css/colorpacks/greydragon/images/view-info.png
new file mode 100644
index 0000000..521439c
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/view-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/greydragon/images/view-slideshow-b.png b/themes/greydragon_old/css/colorpacks/greydragon/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/greydragon/images/view-slideshow-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/css/colors.css b/themes/greydragon_old/css/colorpacks/roundrobin/css/colors.css
new file mode 100644
index 0000000..ab0df26
--- /dev/null
+++ b/themes/greydragon_old/css/colorpacks/roundrobin/css/colors.css
@@ -0,0 +1,193 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: Wind - White Hawk color pack
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #FFFFFF; }
+body { color: #555; margin-top: 1em; padding-left: 0px; padding-right: 0px; background: transparent url(../images/bg-body.jpg) top left; border-radius: 10px; box-shadow: 4px 4px 12px #333; }
+                                                                               
+a { color: #555 !important }
+a:hover { text-decoration: underline; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png') no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-main-in { overflow: visible; }
+#g-header { border-bottom: #050505 1px solid; background: transparent url(../images/bg-header.jpg) repeat-x top left; border-top-left-radius: 10px; border-top-right-radius: 10px; }
+#g-header .g-message-block { border: 1px #ccc solid; color: #000; }
+#g-footer { border-top: #050505 1px solid; background: transparent url(../images/bg-header.jpg) repeat-x top left; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; }
+
+#g-column-left  { position: relative; float: left; right: 40px; top: 16px; background: transparent url(../images/bg-header.jpg) top left; border-radius: 6px; padding-top: 4px; box-shadow: 4px 4px 12px #333; }
+#g-column-right { position: relative; float: right; left: 40px; top: 16px; background: transparent url(../images/bg-header.jpg) top left; border-radius: 6px; padding-top: 4px; box-shadow: 4px 4px 12px #333; }
+
+.g-sidebar-left #g-column-centerright { position: relative; left: -16px; }
+.g-sidebar-left #g-view-menu { right: 120px; }
+.g-sidebar-left #g-viewformat { right: 24px; }
+
+.g-sidebar-right #g-column-centerleft { position: relative; left: 16px; }
+.g-sidebar-right #g-view-menu { top: 22px; }
+.g-sidebar-right #g-viewformat { top: 22px; }
+.g-toolbar-large.g-sidebar-right #g-viewformat { top: 26px; }
+
+#g-gallery-logo { background-image: url('../images/gallery.png'); }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+#g-rootpage.g-sidebar-left #g-column-centerright,
+#g-rootpage.g-sidebar-right #g-column-centerleft { left: 0px; padding-left: 26px; }
+#g-header #g-login-menu { top: 0.6em; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info h1, #g-album-header h1 { border-bottom: #ccc 1px solid; }
+#g-info .g-description { border: #ccc 1px solid; }
+
+.g-thumbslide { border-color: #ccc; }
+.g-album .g-thumbslide { border-color: #ccc; }
+.g-thumbcrop  { border-color: #ccc; }
+                                                                                                                 
+.g-default  .g-thumbslide .g-description { color: #000; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-expanded .g-thumbslide .g-description { color: #fff; background: transparent; border: none; }
+.g-album    .g-thumbslide .g-description { background-image: url(../images/ico-album.png); background-repeat: no-repeat; background-position: 8px 4px; }
+.g-thumbslide .g-metadata { border-top: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: 1px solid #ccc; }
+div.g-resize .g-description { color: #000; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #ccc; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #ccc; }
+div.g-resize .g-more { border: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+.g-movie  { border: 1px solid #ccc; padding: 5px; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block {  } 
+.g-block h2 { border-bottom: 1px solid #ccc; background: rgba(255, 255, 255, 0.5); border-radius: 5px; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #fff; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #e8e8e8; color: #000; }
+#sb-title-inner { color: #000; }
+#sb-counter a { font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #fff; border: #303030 1px solid; }
+#g-add-photos-button { border: #303030 1px solid; }
+#g-add-photos-status { background-color: #fff; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile h1 { border-bottom: #ccc 1px solid; }
+#g-user-profile .g-avatar { border: 1px solid #ccc; background: #fff; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; color: #000; }
+#g-site-menu li { background-color: #ccc; }
+#g-site-menu li ul { border: #ccc 1px solid; }
+#g-site-menu li ul li { border: #ccc 0px solid; background-color: #ccc; }
+
+#g-site-menu>ul>li { background-color: transparent; }
+
+#g-site-menu.g-bar { border: #ccc 1px solid; background-color: #ccc; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #e8e8e8 none; border: 1px #ccc solid; }
+.g-item .g-context-menu li li a:hover { background-color: #e8e8e8; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #ccc 1px solid; }
+#g-exif-data .g-even { background-color: #e8e8e8; }
+#g-exif-data .g-odd { background-color: #FFFFFF; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #ccc; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #ccc; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #ccc; }
+#g-comment-form { border: 1px dotted #ccc; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form.g-short-form li { margin-left: -2px !important; }
+#g-quick-search-form input[type="text"]   { background-color: #FFF; border: 1px solid #ccc; color: #666;  border-top-left-radius: 4px; border-bottom-left-radius: 4px; }
+#ag-quick-search-form input[type="submit"] { border: #c5dbec 1px solid; text-indent: 0; width: auto; height: auto; font: 80% arial, helvetica, clean, sans-serif; font-weight: bold; padding-top: 3px; padding-bottom: 3px; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+#g-search-results h1 { border-bottom: #ccc 1px solid; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background-color: #e8e8e8; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #e8e8e8; color: #666666; }
+.ui-widget-content { border: 1px solid #303030; background-color: #fff; color: #000; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; background: #303030; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #ccc 1px solid; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/ajax-loading.gif b/themes/greydragon_old/css/colorpacks/roundrobin/images/ajax-loading.gif
new file mode 100644
index 0000000..53dd589
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/ajax-loading.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/bg-body.jpg b/themes/greydragon_old/css/colorpacks/roundrobin/images/bg-body.jpg
new file mode 100644
index 0000000..08f519b
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/bg-body.jpg differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/bg-header.jpg b/themes/greydragon_old/css/colorpacks/roundrobin/images/bg-header.jpg
new file mode 100644
index 0000000..f33f0c6
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/bg-header.jpg differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/colorpack.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/colorpack.png
new file mode 100644
index 0000000..12fea30
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/colorpack.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/gallery.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/gallery.png
new file mode 100644
index 0000000..9ee765c
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/gallery.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-album.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-album.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-error.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-error.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-help.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-help.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-info.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-warning.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/ico-warning.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/loading-large.gif b/themes/greydragon_old/css/colorpacks/roundrobin/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/loading-large.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/loading-small.gif b/themes/greydragon_old/css/colorpacks/roundrobin/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/loading-small.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/search.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/search.png
new file mode 100644
index 0000000..d9592d8
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/search.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/ui-icons.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/ui-icons.png
new file mode 100644
index 0000000..4082a0e
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/ui-icons.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/view-calendar-b.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-calendar-b.png
new file mode 100644
index 0000000..f3ab6aa
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-calendar-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/view-calendar.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-calendar.png
new file mode 100644
index 0000000..a4d038a
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-calendar.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/view-comments-b.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-comments-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/view-comments.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-comments.png
new file mode 100644
index 0000000..5aca071
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-comments.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/view-fullsize-b.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-fullsize-b.png
new file mode 100644
index 0000000..fad5e53
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-fullsize-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/view-fullsize.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-fullsize.png
new file mode 100644
index 0000000..cc4fbba
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-fullsize.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/view-info-b.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-info-b.png
new file mode 100644
index 0000000..90f1bb4
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-info-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/view-info-o.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-info-o.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/view-info.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-info.png
new file mode 100644
index 0000000..4bdb724
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/roundrobin/images/view-slideshow-b.png b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/roundrobin/images/view-slideshow-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/css/colors.css b/themes/greydragon_old/css/colorpacks/slateblue/css/colors.css
new file mode 100644
index 0000000..70b1c2a
--- /dev/null
+++ b/themes/greydragon_old/css/colorpacks/slateblue/css/colors.css
@@ -0,0 +1,177 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: SlateBlue
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #1c242e; }
+body { color: #BBB; background: #1c242e; }
+
+h1 { border-bottom: #737373 1px solid; }
+a { color: #6392CF !important; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png')  no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-header { border-left: #10151c 1px solid; border-right: #10151c 1px solid; background: url(../images/background.jpg) #1c242e repeat-x; }
+.viewmode-mini #g-header { border-bottom: #10151c 1px solid; }
+#g-header .g-message-block { border: 1px #888 solid; background-color: #AAA; color: #000; }
+#g-main { border-left: #10151c 1px solid; border-right: #10151c 1px solid; }
+.viewmode-mini #g-main { border-bottom: #10151c 1px solid; }
+#g-footer { background: #000; font-size: 10px; }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top, #g-column-bottom { background-color: #1a1e27; border: #10151C 1px solid; border-top: none;}
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info .g-description { border: #10151c 1px solid; background-color: #1a1e27; }
+
+.g-thumbslide { border-color: #303E43; }
+.g-album .g-thumbslide { border-color: #43565B; }
+.g-thumbcrop  { border-color: #303E43; }
+
+.g-default  .g-thumbslide .g-description { color: #fff; background: #1E1E1E; border-top: 1px solid #303e43; border-bottom: 1px solid #303e43; opacity:.85; -ms-filter: "alpha (opacity=85)"; filter: alpha (opacity=85);  }
+.g-expanded .g-thumbslide .g-description { color: #fff; background: transparent; border: none; }
+.g-album .g-thumbslide .g-description { background-image: url(../images/ico-album.png); background-repeat: no-repeat; background-position: 8px 4px; }
+
+.g-thumbslide .g-metadata { border-top: 1px solid #303e43; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+#g-album-grid.g-panel .g-album .g-thumbslide, #g-album-grid.g-panel .g-thumbslide { border-width: 1px; border-style: solid; border-left-color: #666; border-top-color: #666; border-right-color: #10151C; border-bottom-color: #10151C; }
+// #g-album-grid.g-panel .g-album .g-thumbslide, #g-album-grid.g-panel .g-thumbslide { border-width: 1px; border-style: solid; border-left-color: #666; border-top-color: #666; border-right-color: #202020; border-bottom-color: #202020; }
+
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: #10151c 1px solid; background: #4a4e67; }
+div.g-resize .g-description { color: #fff; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #999; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #999; }
+div.g-resize .g-more { border: 1px solid #999; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+.g-movie  { border: 1px solid #888; padding: 5px; background: #555; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block { border-width: 1px; border-style: solid; border-left-color: #303e43; border-top-color: #303e43; border-right-color: #10151C; border-bottom-color: #10151C; background-color: #1a1e27; } 
+.g-block h2 { background: #1c242e; border-bottom: #273444 1px solid; border-top: #273444 1px solid; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #999; background: #1E1E1E; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #101415; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #101415 url('../images/section.png') repeat-x; }
+#sb-counter a { color: #fff !important; font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #101010; border: #303030 1px solid; }
+#g-add-photos-status { background-color: #101010; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #888 1px solid; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile .g-avatar { border: 1px solid #888; background: #555; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li a:hover { color: #000000; background-color: #303030; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #303030; border-bottom: #000000 1px solid; }
+#g-site-menu li ul { border: #000000 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #212121; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #303030; }
+
+#g-site-menu.g-bar { border: #000000 1px solid; background-color: #212121; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #181818 none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #303030; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #303030 1px solid; }
+#g-exif-data .g-even { background-color: #404040; }
+#g-exif-data .g-odd { background-color: #303030; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #737373; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #888; background: #555; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #737373; }
+#g-comment-form { border: 1px dotted #737373; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #737373; color: #BBB; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background: url(../images/section.png) repeat-x; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #101415 url('../images/section.png') repeat-x; }
+.ui-widget-content { border: 1px solid #303030; background-color: #1a2022; color: #bbb; }
+.ui-progressbar .ui-progressbar-value { background: #737373; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/ajax-loading.gif b/themes/greydragon_old/css/colorpacks/slateblue/images/ajax-loading.gif
new file mode 100644
index 0000000..0996045
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/ajax-loading.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/background.jpg b/themes/greydragon_old/css/colorpacks/slateblue/images/background.jpg
new file mode 100644
index 0000000..7ec958a
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/background.jpg differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/colorpack.png b/themes/greydragon_old/css/colorpacks/slateblue/images/colorpack.png
new file mode 100644
index 0000000..d3fd993
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/colorpack.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/footer.png b/themes/greydragon_old/css/colorpacks/slateblue/images/footer.png
new file mode 100644
index 0000000..04d5ee5
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/footer.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/ico-album.png b/themes/greydragon_old/css/colorpacks/slateblue/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/ico-album.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/ico-error.png b/themes/greydragon_old/css/colorpacks/slateblue/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/ico-error.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/ico-help.png b/themes/greydragon_old/css/colorpacks/slateblue/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/ico-help.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/ico-info.png b/themes/greydragon_old/css/colorpacks/slateblue/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/ico-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/ico-warning.png b/themes/greydragon_old/css/colorpacks/slateblue/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/ico-warning.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/loading-large.gif b/themes/greydragon_old/css/colorpacks/slateblue/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/loading-large.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/loading-small.gif b/themes/greydragon_old/css/colorpacks/slateblue/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/loading-small.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/search.png b/themes/greydragon_old/css/colorpacks/slateblue/images/search.png
new file mode 100644
index 0000000..1bfa411
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/search.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/section.png b/themes/greydragon_old/css/colorpacks/slateblue/images/section.png
new file mode 100644
index 0000000..8180ecb
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/section.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/ui-icons.png b/themes/greydragon_old/css/colorpacks/slateblue/images/ui-icons.png
new file mode 100644
index 0000000..41ce8ff
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/ui-icons.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/view-calendar-b.png b/themes/greydragon_old/css/colorpacks/slateblue/images/view-calendar-b.png
new file mode 100644
index 0000000..c5a1248
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/view-calendar-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/view-calendar.png b/themes/greydragon_old/css/colorpacks/slateblue/images/view-calendar.png
new file mode 100644
index 0000000..bd1d03c
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/view-calendar.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/view-comments-b.png b/themes/greydragon_old/css/colorpacks/slateblue/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/view-comments-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/view-comments.png b/themes/greydragon_old/css/colorpacks/slateblue/images/view-comments.png
new file mode 100644
index 0000000..293c587
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/view-comments.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/view-fullsize-b.png b/themes/greydragon_old/css/colorpacks/slateblue/images/view-fullsize-b.png
new file mode 100644
index 0000000..f659d79
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/view-fullsize-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/view-fullsize.png b/themes/greydragon_old/css/colorpacks/slateblue/images/view-fullsize.png
new file mode 100644
index 0000000..ed76257
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/view-fullsize.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/view-info-b.png b/themes/greydragon_old/css/colorpacks/slateblue/images/view-info-b.png
new file mode 100644
index 0000000..880d3e8
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/view-info-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/view-info-o.png b/themes/greydragon_old/css/colorpacks/slateblue/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/view-info-o.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/view-info.png b/themes/greydragon_old/css/colorpacks/slateblue/images/view-info.png
new file mode 100644
index 0000000..521439c
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/view-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/slateblue/images/view-slideshow-b.png b/themes/greydragon_old/css/colorpacks/slateblue/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/slateblue/images/view-slideshow-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/css/colors.css b/themes/greydragon_old/css/colorpacks/whitehawk/css/colors.css
new file mode 100644
index 0000000..58a4ef2
--- /dev/null
+++ b/themes/greydragon_old/css/colorpacks/whitehawk/css/colors.css
@@ -0,0 +1,174 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: Wind - White Hawk color pack
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #FFFFFF; }
+body { color: #666666; padding-left: 10px; padding-right: 10px; }
+                                                                               
+a { color: #666666 !important }
+a:hover { text-decoration: underline; }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png') no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-header { border-bottom: #ccc 1px solid; }
+#g-header .g-message-block { border: 1px #ccc solid; color: #000; }
+#g-footer { border-top: #ccc 1px solid; }
+
+#g-gallery-logo { background-image: url('../images/gallery.png'); }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info h1, #g-album-header h1 { border-bottom: #ccc 1px solid; }
+#g-info .g-description { border: #ccc 1px solid; }
+
+.g-thumbslide { border-color: #ccc; }
+.g-album .g-thumbslide { border-color: #ccc; }
+.g-thumbcrop  { border-color: #ccc; }
+                                                                                                                 
+.g-default  .g-thumbslide .g-description { color: #000; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-expanded .g-thumbslide .g-description { color: #fff; background: transparent; border: none; }
+.g-album    .g-thumbslide .g-description { background-image: url(../images/ico-album.png); background-repeat: no-repeat; background-position: 8px 4px; }
+.g-thumbslide .g-metadata { border-top: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: 1px solid #ccc; }
+div.g-resize .g-description { color: #000; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #ccc; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #ccc; }
+div.g-resize .g-more { border: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+.g-movie  { border: 1px solid #ccc; padding: 5px; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block { border: 1px solid #ccc; } 
+.g-block h2 { border-bottom: 1px solid #ccc; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #ccc; background: #FFFFFF; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #fff; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #e8e8e8; color: #000; }
+#sb-title-inner { color: #000; }
+#sb-counter a { font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #fff; border: #303030 1px solid; }
+#g-add-photos-button { border: #303030 1px solid; }
+#g-add-photos-status { background-color: #fff; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile h1 { border-bottom: #ccc 1px solid; }
+#g-user-profile .g-avatar { border: 1px solid #ccc; background: #fff; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li { background-color: #FFFFFF; }
+#g-site-menu li ul { border: #ccc 1px solid; }
+#g-site-menu li ul li { border: #ccc 0px solid; background-color: #FFFFFF; }
+
+#g-site-menu.g-bar { border: #ccc 1px solid; background-color: #FFFFFF; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #e8e8e8 none; border: 1px #ccc solid; }
+.g-item .g-context-menu li li a:hover { background-color: #e8e8e8; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #ccc 1px solid; }
+#g-exif-data .g-even { background-color: #e8e8e8; }
+#g-exif-data .g-odd { background-color: #FFFFFF; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #ccc; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #ccc; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #ccc; }
+#g-comment-form { border: 1px dotted #ccc; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #ccc; color: #666;  }
+#ag-quick-search-form input[type="submit"] { border: #c5dbec 1px solid; text-indent: 0; width: auto; height: auto; font: 80% arial, helvetica, clean, sans-serif; font-weight: bold; padding-top: 3px; padding-bottom: 3px; }
+#g-quick-search-form input[type="submit"] { background: transparent url(../images/search.png) no-repeat center top; border: none; }
+
+#g-search-results h1 { border-bottom: #ccc 1px solid; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background-color: #e8e8e8; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #e8e8e8; color: #666666; }
+.ui-widget-content { border: 1px solid #303030; background-color: #fff; color: #000; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; background: #303030; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #ccc 1px solid; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar-b.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/view-fullsize-b.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/ajax-loading.gif b/themes/greydragon_old/css/colorpacks/whitehawk/images/ajax-loading.gif
new file mode 100644
index 0000000..53dd589
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/ajax-loading.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/colorpack.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/colorpack.png
new file mode 100644
index 0000000..3b7afef
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/colorpack.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/gallery.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/gallery.png
new file mode 100644
index 0000000..3ba425d
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/gallery.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-album.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-album.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-error.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-error.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-help.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-help.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-info.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-warning.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/ico-warning.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/loading-large.gif b/themes/greydragon_old/css/colorpacks/whitehawk/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/loading-large.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/loading-small.gif b/themes/greydragon_old/css/colorpacks/whitehawk/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/loading-small.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/search.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/search.png
new file mode 100644
index 0000000..bb323e5
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/search.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/ui-icons.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/ui-icons.png
new file mode 100644
index 0000000..db1ec71
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/ui-icons.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/view-calendar-b.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-calendar-b.png
new file mode 100644
index 0000000..f3ab6aa
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-calendar-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/view-calendar.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-calendar.png
new file mode 100644
index 0000000..a4d038a
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-calendar.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/view-comments-b.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-comments-b.png
new file mode 100644
index 0000000..aa91298
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-comments-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/view-comments.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-comments.png
new file mode 100644
index 0000000..5aca071
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-comments.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/view-fullsize-b.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-fullsize-b.png
new file mode 100644
index 0000000..fad5e53
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-fullsize-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/view-fullsize.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-fullsize.png
new file mode 100644
index 0000000..cc4fbba
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-fullsize.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/view-info-b.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-info-b.png
new file mode 100644
index 0000000..90f1bb4
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-info-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/view-info-o.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-info-o.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/view-info.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-info.png
new file mode 100644
index 0000000..4bdb724
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/whitehawk/images/view-slideshow-b.png b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/whitehawk/images/view-slideshow-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/css/colors.css b/themes/greydragon_old/css/colorpacks/wind/css/colors.css
new file mode 100644
index 0000000..3c79a06
--- /dev/null
+++ b/themes/greydragon_old/css/colorpacks/wind/css/colors.css
@@ -0,0 +1,176 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * ColorPack: Wind - Wind theme-like color pack
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* styles.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { background-color: #ccc; }
+body { color: #000; background-color: #ccc; padding-left: 10px; padding-right: 10px; }
+                                                                               
+a { color: #33629f !important }
+.ui-icon, #g-slideshow-link { background-image: url(../images/ui-icons.png); }
+
+#g-site-status li { border-bottom: 1px solid #ccc; color: #333; } 
+#g-site-status .g-error   { background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; }
+#g-site-status .g-info    { background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; }
+#g-site-status .g-success { background: #d9efc2 url('../../../../images/ico-success.png') no-repeat .4em 50%; }
+#g-site-status .g-warning { background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; }
+
+/* styles.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#g-header { background-color: #e8e8e8; border-bottom: #ccc 1px solid; }
+#g-header .g-message-block { border: 1px #888 solid; background-color: #aaa; color: #000; }
+#g-main { background-color: #fff; }
+#g-footer { background-color: #e8e8e8; border-top: #ccc 1px solid; }
+#g-theme-logo { background: transparent url('../images/colorpack.png') no-repeat; }
+
+/* styles.css - Album Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-top, #g-column-bottom { background-color: #e8e8e8; }
+#g-column-top .g-toolbar h1, #g-column-bottom .g-toolbar h1 { border: none; }
+#g-info h1, #g-album-header h1 { border-bottom: #ccc 1px solid; }
+#g-info .g-description { border: #888 1px solid; }
+
+.g-thumbslide { background: #e8e8e8; border-color: #707E83; }
+.g-album .g-thumbslide { border-color: #707E83; }
+.g-thumbcrop  { border-color: #707E83; }
+                                                                                                                 
+.g-default  .g-thumbslide .g-description { color: #000; border-top: 1px solid #707E83; border-bottom: 1px solid #707E83; background: #e8e8e8; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+.g-expanded .g-thumbslide .g-description { color: #fff; background: transparent; border: none; }
+.g-album    .g-thumbslide .g-description { background-image: url(../images/ico-album.png); background-repeat: no-repeat; background-position: 8px 4px; }
+
+.g-thumbslide .g-metadata { border-top: 1px solid #707E83; background: #e8e8e8; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* styles.css - Photo Layout ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+div.g-resize { border: 1px solid #888; background: #e8e8e8; }
+div.g-resize .g-description { color: #000; background: #e8e8e8; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+div.g-resize .g-description.g-align-top { border-bottom: 1px solid #999; }
+div.g-resize .g-description.g-align-bottom { border-top: 1px solid #999; }
+div.g-resize .g-more { border: 1px solid #999; background: #e8e8e8; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+.g-movie  { border: 1px solid #888; padding: 5px; background: #e8e8e8; }
+
+/* styles.css - Sidebar Blocks : Common ~~~~~~~~~~~~~~*/
+
+.g-block { border: 1px solid #ccc; } 
+.g-block h2 { background-color: #e8e8e8; }
+
+/* styles.css - Sidebar Blocks : Buttons ~~~~~~~~~~~~~*/
+
+.g-fullsize-link  { background: url("../images/view-fullsize.png") top left no-repeat; }
+#g-exifdata-link  { background: url("../images/view-info.png") top left no-repeat; }
+
+/* styles.css - Root Page ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage-roll span { border: 1px solid #999; background: #e8e8e8; filter:alpha(opacity=85); opacity:.85; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* styles.css - Photo Slideshow ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-body { background-color: #fff; }
+#sb-title { border-left: #303030 1px solid; border-right: #303030 1px solid; background: #e8e8e8; color: #000; }
+#sb-title-inner { color: #000; }
+#sb-counter a { font-weight: bold; font-size: 11px; }
+
+/* forms.css - Add item ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { background-color: #fff; border: #303030 1px solid; }
+#g-add-photos-button { border: #303030 1px solid; }
+#g-add-photos-status { background-color: #fff; border: #303030 1px solid; }
+
+.uploadifyQueueItem { color: #000; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile h1 { border-bottom: #ccc 1px solid; }
+#g-user-profile .g-avatar { border: 1px solid #888; background: #fff; } 
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu ul { border: #000000 0 solid; }
+#g-site-menu li { background-color: #bdd2ff; }
+#g-site-menu li a:hover { color: #000000; background-color: #cfdeff; }
+#g-site-menu li:hover,
+#g-site-menu li.iemhover { border: #303030 1px solid; background-color: #cfdeff; border-bottom: #cfdeff 1px solid; }
+#g-site-menu li ul { border: #cfdeff 1px solid; }
+#g-site-menu li ul li { border: #C0C0C0 0px solid; background-color: #bdd2ff; }
+#g-site-menu li ul li:hover,
+#g-site-menu li ul li.iemhover { border: #C0C0C0 0 solid; background-color: #ddf2ff; }
+
+#g-site-menu.g-bar { border: #cfdeff 1px solid; background-color: #bdd2ff; }
+#g-site-menu.g-bar li:hover,
+#g-site-menu.g-bar li.iemhover { border-bottom-color: transparent; }
+
+.g-item .g-context-menu { background-image: url(../images/ui-icons.png); } 
+.g-item .g-context-menu:hover { background: #bdd2ff none; border: 1px #888 solid; }
+.g-item .g-context-menu li li a:hover { background-color: #ddf2ff; }
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - Exif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data table { border: #303030 1px solid; }
+#g-exif-data .g-even { background-color: #A0A0A0; }
+#g-exif-data .g-odd { background-color: #C0C0C0; }
+
+/* modules.css - Info module ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata .g-description { border-top: 1px solid #ccc; }
+
+/* modules.css - Image block  ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-image-block img { border: 1px solid #888; background: #555; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments .g-author { border-bottom: 1px solid #202628; color: #999; }
+#g-comments-link { background-image: url(../images/view-comments.png); }
+#g-comment-detail>ul>li { border: 1px dotted #ccc; }
+#g-comment-form { border: 1px dotted #ccc; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-view-menu #g-calendarview-link { background-image: url(../images/view-calendar.png); }
+#g-view-calendar-form ul { border: 1px #888 solid; }
+table.calendar    { border: #a2adbc 1px solid; color: #616b76; }
+table.calendar th { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; background: #d9e2e1; color: #616b76; }
+table.calendar td { border-bottom: #a2adbc 1px solid; border-right: #a2adbc 1px solid; }
+table.calendar td.title   { background-color: #a2adbc; color: #fff; }
+table.calendar td.title a { color: #fff !important; }
+table.calendar td a     { color: red !important; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form input[type="text"]   { background-color: transparent; border: 1px solid #ccc; color: #666;  }
+#g-quick-search-form input[type="submit"] { border: #c5dbec 1px solid; text-indent: 0; width: auto; height: auto; font: 80% arial, helvetica, clean, sans-serif; font-weight: bold; padding-top: 3px; padding-bottom: 3px; }
+#g-search-results h1 { border-bottom: #ccc 1px solid; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#checkout legend { background-color: #e8e8e8; }
+
+/* forms.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.ui-dialog .ui-dialog-titlebar { background: #ccc url('../images/section.png') repeat-x; }
+.ui-widget-content { border: 1px solid #303030; background-color: #fff; color: #000; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; background: #303030; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-column-centerfull #g-login { border: #888 1px solid; }
+
+/* Large toolbar icons support ~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-toolbar-large #g-view-menu #g-calendarview-link { background-image: url(../../../../../../modules/calendarview/images/ico-view-calendarview.png); }
+.g-toolbar-large #g-slideshow-link { background: url(../images/view-slideshow-b.png) no-repeat top center; }
+.g-toolbar-large .g-fullsize-link { background: url(../images/ico-view-fullsize.png) no-repeat top center; }
+.g-toolbar-large #g-exifdata-link { background: url(../images/view-info-b.png) no-repeat top center; }
+.g-toolbar-large #g-comments-link { background: url(../images/view-comments-b.png) no-repeat top center; }
+
+.g-thumbcrop a.g-meta-exif-link { background-image: url(../images/view-info-o.png); }
\ No newline at end of file
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/ajax-loading.gif b/themes/greydragon_old/css/colorpacks/wind/images/ajax-loading.gif
new file mode 100644
index 0000000..53dd589
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/ajax-loading.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/colorpack.png b/themes/greydragon_old/css/colorpacks/wind/images/colorpack.png
new file mode 100644
index 0000000..d217920
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/colorpack.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/ico-album.png b/themes/greydragon_old/css/colorpacks/wind/images/ico-album.png
new file mode 100644
index 0000000..ac87ec4
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/ico-album.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/ico-error.png b/themes/greydragon_old/css/colorpacks/wind/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/ico-error.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/ico-help.png b/themes/greydragon_old/css/colorpacks/wind/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/ico-help.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/ico-info.png b/themes/greydragon_old/css/colorpacks/wind/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/ico-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/ico-view-fullsize.png b/themes/greydragon_old/css/colorpacks/wind/images/ico-view-fullsize.png
new file mode 100644
index 0000000..740183a
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/ico-view-fullsize.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/ico-view-slideshow-rtl.png b/themes/greydragon_old/css/colorpacks/wind/images/ico-view-slideshow-rtl.png
new file mode 100644
index 0000000..9552d30
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/ico-view-slideshow-rtl.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/ico-view-slideshow.png b/themes/greydragon_old/css/colorpacks/wind/images/ico-view-slideshow.png
new file mode 100644
index 0000000..d43a560
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/ico-view-slideshow.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/ico-warning.png b/themes/greydragon_old/css/colorpacks/wind/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/ico-warning.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/loading-large.gif b/themes/greydragon_old/css/colorpacks/wind/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/loading-large.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/loading-small.gif b/themes/greydragon_old/css/colorpacks/wind/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/loading-small.gif differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/section.png b/themes/greydragon_old/css/colorpacks/wind/images/section.png
new file mode 100644
index 0000000..33fc350
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/section.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/ui-icons.png b/themes/greydragon_old/css/colorpacks/wind/images/ui-icons.png
new file mode 100644
index 0000000..7dc8ab9
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/ui-icons.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/view-calendar.png b/themes/greydragon_old/css/colorpacks/wind/images/view-calendar.png
new file mode 100644
index 0000000..13e0e8f
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/view-calendar.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/view-comments-b.png b/themes/greydragon_old/css/colorpacks/wind/images/view-comments-b.png
new file mode 100644
index 0000000..64f8c50
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/view-comments-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/view-comments.png b/themes/greydragon_old/css/colorpacks/wind/images/view-comments.png
new file mode 100644
index 0000000..f33bdf1
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/view-comments.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/view-fullsize.png b/themes/greydragon_old/css/colorpacks/wind/images/view-fullsize.png
new file mode 100644
index 0000000..58b3e0b
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/view-fullsize.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/view-info-b.png b/themes/greydragon_old/css/colorpacks/wind/images/view-info-b.png
new file mode 100644
index 0000000..90f1bb4
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/view-info-b.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/view-info-o.png b/themes/greydragon_old/css/colorpacks/wind/images/view-info-o.png
new file mode 100644
index 0000000..612ba96
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/view-info-o.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/view-info.png b/themes/greydragon_old/css/colorpacks/wind/images/view-info.png
new file mode 100644
index 0000000..2cc7a68
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/view-info.png differ
diff --git a/themes/greydragon_old/css/colorpacks/wind/images/view-slideshow-b.png b/themes/greydragon_old/css/colorpacks/wind/images/view-slideshow-b.png
new file mode 100644
index 0000000..ad13671
Binary files /dev/null and b/themes/greydragon_old/css/colorpacks/wind/images/view-slideshow-b.png differ
diff --git a/themes/greydragon_old/css/custom.css b/themes/greydragon_old/css/custom.css
new file mode 100644
index 0000000..1c4cd73
--- /dev/null
+++ b/themes/greydragon_old/css/custom.css
@@ -0,0 +1,2 @@
+#g-metadata strong.caption { display: inline; }
+#g-view-menu #g-download-fullsize-link { background-size: 22px 15px; }
diff --git a/themes/greydragon_old/css/forms.css b/themes/greydragon_old/css/forms.css
new file mode 100644
index 0000000..1361d4a
--- /dev/null
+++ b/themes/greydragon_old/css/forms.css
@@ -0,0 +1,113 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules related to forms/dialogs
+ */
+
+.ui-widget-overlay { position: absolute; top:0; left:0; bottom: 0; right: 0; position: fixed; width:100%; filter: alpha(opacity=70); -moz-opacity: 0.7; -khtml-opacity: 0.7; opacity: 0.7; background-color: #111; zoom: 1; }
+.ui-widget-overlay { height: expression(document.documentElement.clientHeight + 'px'); }
+.ui-widget-overlay { height: 100%; }
+
+/* Dialog ----------------------------------*/
+
+.ui-dialog { position: relative; width: 300px; display: inline-block; }
+.ui-dialog .ui-dialog-titlebar { height: 1em; padding: .5em .3em .3em 1em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; } 
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; text-indent: -900em; }
+.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; display: block; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-dialog ul { padding: 0; }
+.ui-dialog .ui-dialog-content .g-right { margin-right: 20px; }
+
+/* forms.css - Component containers ~~~~~~~~~~~~~~~~~~*/
+.ui-widget-header { color: #ffffff; font-weight: bold; }
+.ui-widget-header a { color: #ffffff; }
+.ui-widget-content a { color: #222222; }
+
+/* forms.css - Forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+form        { margin: 0; }
+form p.g-error { color: red; }
+fieldset    { border: 1px solid #ccc; padding: 0 1em .8em 1em; }
+legend      { display: none; }
+input.textbox, input[type="text"], input[type="password"], textarea { border: 1px solid #e8e8e8; border-top-color: #ccc; border-left-color: #ccc; clear: both; color: #333; width: 50%; }
+textarea    { height: 12em; width: 97%; }
+input:focus, input.textbox:focus, input[type=text]:focus, textarea:focus, option:focus { background-color: #ffc; color: #000; }
+input.checkbox, input[type=checkbox], input.radio, input[type=radio] { float: left; margin-right: .4em; }
+
+/* forms.css - Layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+form li { margin: 0; padding: 0 0 .2em 0; }
+form ul { margin-top: 0; }
+form ul ul { clear: both; }
+form ul ul li { float: left; margin-right: 0.6em; }
+input, select, textarea { display: block; clear: both; }
+input[type="submit"], input[type="reset"] { display: inline; }
+input[type="submit"], .g-button, button, .ui-dialog .g-cancel { cursor: pointer; cursor: hand; font-size: 0.8em; color: #333 !important; font-weight: normal; line-height: 1.4em; padding: 2px 10px; margin-right: 0.4em; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); border: 1px solid; border-color: #999 #666 #666 #999; background-color: #ddd; }
+
+.g-button { margin: 0 0.4em 0.4em 0; }
+.ui-dialog .g-cancel { margin-top: 0.6em; }
+.g-right { float: right; }
+
+/* forms.css - Forms in dialogs and panels ~~~~~~~~~~~*/
+
+#g-dialog ul li { padding-bottom: 0.6em; }
+#g-dialog fieldset, #g-panel fieldset { border: none; padding: 0; }
+#g-panel legend { display: none; }
+input[readonly] { background-color: #F4F4FC; }
+#g-dialog input.textbox, #g-dialog input[type=text], #g-dialog input[type=password], #g-dialog textarea { width: 97%; }
+
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
+.g-progress-bar { height: 1em; width: 100%; margin-top: .5em; display: inline-block; }
+#g-progress #g-status { padding: 0.5em 0; }
+
+/* forms.css - Short forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-short-form legend, .g-short-form label { display: none; }
+.g-short-form fieldset { border: none; padding: 0; }
+.g-short-form li { float: left; margin: 0 !important; padding: .4em 0; }
+.g-short-form .textbox, .g-short-form input[type=text] { color: #666; padding: .3em .6em; width: 100%; }
+.g-short-form .textbox.g-error { border: 1px solid #f00; color: #f00; padding-left: 24px; }
+.g-short-form .g-cancel { display: block; margin: .3em .8em; }
+#g-sidebar .g-short-form li { padding-left: 0; padding-right: 0; }
+
+#g-quick-search-form input[type="submit"] { filter: none; margin-top: 0; }
+
+/* forms.css - Reauthentificate ~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-login fieldset { border: none; }
+#g-login legend { display: none; }
+#g-login label { display: block; }
+
+#g-column-centerfull #g-error h2 { padding-top: 10px; }
+#g-column-centerfull #g-login { width: 270px; margin-top: 10px; padding-top: 10px; }
+#g-column-centerfull #g-login input[type='text'], #g-column-centerfull #g-login input[type='password'] { width: 100%; }
+#g-column-centerfull #g-login #g-password-reset { position: relative; bottom: 20px; right: 14px; }
+
+/* forms.css - User Profile ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-user-profile { display: block; }
+#g-user-profile h1 { margin: 0 0 1em 0; }
+#g-user-profile .g-avatar { float: left; margin: .4em; }
+#g-user-profile .g-block { position: static; min-height: 5em; clear: none; margin-left: 4em; }
+#g-user-profile .g-block ul { padding: 0.6em 0; }
+#g-user-profile th { text-align: left; }
+
+#g-user-profile-operations { height: 1.5em; }
+#g-user-profile #g-rest-key .g-button { margin-left: 1em; }
+
+/* forms.css - Uploadify ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-add-photos-canvas { margin-top: 1.1em; }
+#g-add-photos-status #g-action-status li { padding-top: 0.3em; padding-bottom: 0.3em; padding-left: 2em; }
+.uploadifyQueueItem { padding-top: 6px; padding-bottom: 4ps; }
+
+/* forms.css - Permission ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-permissions .g-breadcrumbs { position: static; }
+
+aaa#g-edit-album-form { width: 340px; }
\ No newline at end of file
diff --git a/themes/greydragon_old/css/framepacks/android/css/frame.css b/themes/greydragon_old/css/framepacks/android/css/frame.css
new file mode 100644
index 0000000..548b152
--- /dev/null
+++ b/themes/greydragon_old/css/framepacks/android/css/frame.css
@@ -0,0 +1,32 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Android
+ */
+
+#g-album-grid>li { padding: 10px 6px 10px 10px; }
+.g-thumbslide { background: transparent; }
+
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { border-color: #ADAEAD; }
+.g-thumbcrop { border-width: 1px; border-style: solid; border-color: #ADAEAD; }
+
+.g-thumbtype-sqr { background: url('../images/thumb-sqr.png') no-repeat top left; }
+.g-thumbtype-flm { background: url('../images/thumb-flm.png') no-repeat top left; }
+.g-thumbtype-dgt { background: url('../images/thumb-dgt.png') no-repeat top left; }
+.g-thumbtype-wd  { background: url('../images/thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-thumbtype-sqr { background-image: url('../images/thumb-sqr-ext.png'); }
+.g-extended .g-thumbtype-flm { background-image: url('../images/thumb-flm-ext.png'); }
+.g-extended .g-thumbtype-dgt { background-image: url('../images/thumb-dgt-ext.png'); }
+.g-extended .g-thumbtype-wd  { background-image: url('../images/thumb-wd-ext.png'); }
+
+.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-e.png'); }
+.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-e.png'); }
+.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-e.png'); }
+.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-e.png'); }
+
+.g-extended .g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-eext.png'); }
+.g-extended .g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-eext.png'); }
+.g-extended .g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-eext.png'); }
+.g-extended .g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-eext.png'); }
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-dgt-e.png b/themes/greydragon_old/css/framepacks/android/images/thumb-dgt-e.png
new file mode 100644
index 0000000..39a793a
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-dgt-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-dgt-eext.png b/themes/greydragon_old/css/framepacks/android/images/thumb-dgt-eext.png
new file mode 100644
index 0000000..df4aa49
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-dgt-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-dgt-ext.png b/themes/greydragon_old/css/framepacks/android/images/thumb-dgt-ext.png
new file mode 100644
index 0000000..297a456
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-dgt-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-dgt.png b/themes/greydragon_old/css/framepacks/android/images/thumb-dgt.png
new file mode 100644
index 0000000..b9cc40e
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-dgt.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-flm-e.png b/themes/greydragon_old/css/framepacks/android/images/thumb-flm-e.png
new file mode 100644
index 0000000..b97c8c1
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-flm-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-flm-eext.png b/themes/greydragon_old/css/framepacks/android/images/thumb-flm-eext.png
new file mode 100644
index 0000000..45c38dc
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-flm-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-flm-ext.png b/themes/greydragon_old/css/framepacks/android/images/thumb-flm-ext.png
new file mode 100644
index 0000000..7361f20
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-flm-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-flm.png b/themes/greydragon_old/css/framepacks/android/images/thumb-flm.png
new file mode 100644
index 0000000..a407409
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-flm.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-sqr-e.png b/themes/greydragon_old/css/framepacks/android/images/thumb-sqr-e.png
new file mode 100644
index 0000000..33bcd99
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-sqr-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-sqr-eext.png b/themes/greydragon_old/css/framepacks/android/images/thumb-sqr-eext.png
new file mode 100644
index 0000000..c924637
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-sqr-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-sqr-ext.png b/themes/greydragon_old/css/framepacks/android/images/thumb-sqr-ext.png
new file mode 100644
index 0000000..3fdc3a3
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-sqr-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-sqr.png b/themes/greydragon_old/css/framepacks/android/images/thumb-sqr.png
new file mode 100644
index 0000000..3a038b0
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-sqr.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-wd-e.png b/themes/greydragon_old/css/framepacks/android/images/thumb-wd-e.png
new file mode 100644
index 0000000..3e78ce8
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-wd-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-wd-eext.png b/themes/greydragon_old/css/framepacks/android/images/thumb-wd-eext.png
new file mode 100644
index 0000000..c51abf3
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-wd-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-wd-ext.png b/themes/greydragon_old/css/framepacks/android/images/thumb-wd-ext.png
new file mode 100644
index 0000000..a5aa4b2
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-wd-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/android/images/thumb-wd.png b/themes/greydragon_old/css/framepacks/android/images/thumb-wd.png
new file mode 100644
index 0000000..36a6a4f
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/android/images/thumb-wd.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/css/frame.css b/themes/greydragon_old/css/framepacks/book/css/frame.css
new file mode 100644
index 0000000..abc26d7
--- /dev/null
+++ b/themes/greydragon_old/css/framepacks/book/css/frame.css
@@ -0,0 +1,59 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Book
+ */
+
+#g-album-grid>li { padding: 10px 0px 10px 14px; }
+.g-thumbslide { background: transparent; }
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { background-color: #FFF; border-color: #ADAEAD; color: #111; margin-left: 15px; }
+.g-thumbcrop { border: #ADAEAD 1px solid; } 
+.g-album .g-thumbslide .g-description { background-image: none; }
+.g-album .g-thumbslide .g-description .g-title { padding-left: 0; }
+.g-expanded.g-album .g-thumbslide .g-description .g-title { padding-left: 0; }
+
+.g-item .g-context-menu { left: 200px; }
+.g-item .g-context-menu:hover { left: 20px; }
+.g-extended .g-item .g-context-menu { left: 304px; }
+.g-extended .g-item .g-context-menu:hover { left: 20px; }
+
+.g-album.g-thumbtype-sqr { background: url('../images/a-thumb-sqr.png') no-repeat top left; }
+.g-album.g-thumbtype-flm { background: url('../images/a-thumb-flm.png') no-repeat top left; }
+.g-album.g-thumbtype-dgt { background: url('../images/a-thumb-dgt.png') no-repeat top left; }
+.g-album.g-thumbtype-wd  { background: url('../images/a-thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-album.g-thumbtype-sqr { background-image: url('../images/a-thumb-sqr-ext.png'); }
+.g-extended .g-album.g-thumbtype-flm { background-image: url('../images/a-thumb-flm-ext.png'); }
+.g-extended .g-album.g-thumbtype-dgt { background-image: url('../images/a-thumb-dgt-ext.png'); }
+.g-extended .g-album.g-thumbtype-wd  { background-image: url('../images/a-thumb-wd-ext.png'); }
+
+.g-album.g-thumbtype-sqr.g-expanded { background-image: url('../images/a-thumb-sqr-e.png'); }
+.g-album.g-thumbtype-flm.g-expanded { background-image: url('../images/a-thumb-flm-e.png'); }
+.g-album.g-thumbtype-dgt.g-expanded { background-image: url('../images/a-thumb-dgt-e.png'); }
+.g-album.g-thumbtype-wd.g-expanded  { background-image: url('../images/a-thumb-wd-e.png'); }
+
+.g-extended .g-album.g-thumbtype-sqr.g-expanded { background-image: url('../images/a-thumb-sqr-eext.png'); }
+.g-extended .g-album.g-thumbtype-flm.g-expanded { background-image: url('../images/a-thumb-flm-eext.png'); }
+.g-extended .g-album.g-thumbtype-dgt.g-expanded { background-image: url('../images/a-thumb-dgt-eext.png'); }
+.g-extended .g-album.g-thumbtype-wd.g-expanded  { background-image: url('../images/a-thumb-wd-eext.png'); }
+
+.g-photo.g-thumbtype-sqr { background: url('../images/thumb-sqr.png') no-repeat top left; }
+.g-photo.g-thumbtype-flm { background: url('../images/thumb-flm.png') no-repeat top left; }
+.g-photo.g-thumbtype-dgt { background: url('../images/thumb-dgt.png') no-repeat top left; }
+.g-photo.g-thumbtype-wd  { background: url('../images/thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-photo.g-thumbtype-sqr { background-image: url('../images/thumb-sqr-ext.png'); }
+.g-extended .g-photo.g-thumbtype-flm { background-image: url('../images/thumb-flm-ext.png'); }
+.g-extended .g-photo.g-thumbtype-dgt { background-image: url('../images/thumb-dgt-ext.png'); }
+.g-extended .g-photo.g-thumbtype-wd  { background-image: url('../images/thumb-wd-ext.png'); }
+
+.g-photo.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-e.png'); }
+.g-photo.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-e.png'); }
+.g-photo.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-e.png'); }
+.g-photo.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-e.png'); }
+
+.g-extended .g-photo.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-eext.png'); }
+.g-extended .g-photo.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-eext.png'); }
+.g-extended .g-photo.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-eext.png'); }
+.g-extended .g-photo.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-eext.png'); }
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-e.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-e.png
new file mode 100644
index 0000000..486f50b
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-eext.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-eext.png
new file mode 100644
index 0000000..64bd017
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-ext.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-ext.png
new file mode 100644
index 0000000..bb5089d
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt.png
new file mode 100644
index 0000000..458cc15
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-dgt.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-e.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-e.png
new file mode 100644
index 0000000..7be7ffe
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-eext.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-eext.png
new file mode 100644
index 0000000..0ec4d3c
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-ext.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-ext.png
new file mode 100644
index 0000000..a06d963
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm.png
new file mode 100644
index 0000000..b1ec950
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-flm.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-e.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-e.png
new file mode 100644
index 0000000..bf972a3
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-eext.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-eext.png
new file mode 100644
index 0000000..c13dd02
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-ext.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-ext.png
new file mode 100644
index 0000000..f197016
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr.png
new file mode 100644
index 0000000..6eb7f26
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-sqr.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-e.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-e.png
new file mode 100644
index 0000000..2699b36
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-eext.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-eext.png
new file mode 100644
index 0000000..ff78ba5
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-ext.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-ext.png
new file mode 100644
index 0000000..7501df7
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd.png b/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd.png
new file mode 100644
index 0000000..df1164b
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/a-thumb-wd.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-dgt-e.png b/themes/greydragon_old/css/framepacks/book/images/thumb-dgt-e.png
new file mode 100644
index 0000000..2b9dc15
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-dgt-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-dgt-eext.png b/themes/greydragon_old/css/framepacks/book/images/thumb-dgt-eext.png
new file mode 100644
index 0000000..9d5cbe1
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-dgt-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-dgt-ext.png b/themes/greydragon_old/css/framepacks/book/images/thumb-dgt-ext.png
new file mode 100644
index 0000000..a1afba6
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-dgt-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-dgt.png b/themes/greydragon_old/css/framepacks/book/images/thumb-dgt.png
new file mode 100644
index 0000000..020ed3b
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-dgt.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-flm-e.png b/themes/greydragon_old/css/framepacks/book/images/thumb-flm-e.png
new file mode 100644
index 0000000..89724e8
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-flm-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-flm-eext.png b/themes/greydragon_old/css/framepacks/book/images/thumb-flm-eext.png
new file mode 100644
index 0000000..1c84d91
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-flm-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-flm-ext.png b/themes/greydragon_old/css/framepacks/book/images/thumb-flm-ext.png
new file mode 100644
index 0000000..04bc46a
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-flm-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-flm.png b/themes/greydragon_old/css/framepacks/book/images/thumb-flm.png
new file mode 100644
index 0000000..1709bbe
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-flm.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-sqr-e.png b/themes/greydragon_old/css/framepacks/book/images/thumb-sqr-e.png
new file mode 100644
index 0000000..ede2e1b
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-sqr-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-sqr-eext.png b/themes/greydragon_old/css/framepacks/book/images/thumb-sqr-eext.png
new file mode 100644
index 0000000..48416c6
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-sqr-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-sqr-ext.png b/themes/greydragon_old/css/framepacks/book/images/thumb-sqr-ext.png
new file mode 100644
index 0000000..d7e2e53
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-sqr-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-sqr.png b/themes/greydragon_old/css/framepacks/book/images/thumb-sqr.png
new file mode 100644
index 0000000..95e5890
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-sqr.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-wd-e.png b/themes/greydragon_old/css/framepacks/book/images/thumb-wd-e.png
new file mode 100644
index 0000000..eae6d66
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-wd-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-wd-eext.png b/themes/greydragon_old/css/framepacks/book/images/thumb-wd-eext.png
new file mode 100644
index 0000000..ee89913
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-wd-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-wd-ext.png b/themes/greydragon_old/css/framepacks/book/images/thumb-wd-ext.png
new file mode 100644
index 0000000..d303a1d
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-wd-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/book/images/thumb-wd.png b/themes/greydragon_old/css/framepacks/book/images/thumb-wd.png
new file mode 100644
index 0000000..6d344c5
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/book/images/thumb-wd.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/css/frame.css b/themes/greydragon_old/css/framepacks/darkglass/css/frame.css
new file mode 100644
index 0000000..30d5c9a
--- /dev/null
+++ b/themes/greydragon_old/css/framepacks/darkglass/css/frame.css
@@ -0,0 +1,32 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - DarkGlass
+ */
+
+#g-album-grid>li { padding: 10px 6px 10px 10px; }
+.g-thumbslide { background: transparent; }
+
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { border-color: #ADAEAD; }
+.g-thumbcrop { border-width: 1px; border-style: solid; border-color: #7F7F7F; }
+
+.g-thumbtype-sqr { background: url('../images/thumb-sqr.png') no-repeat top left; }
+.g-thumbtype-flm { background: url('../images/thumb-flm.png') no-repeat top left; }
+.g-thumbtype-dgt { background: url('../images/thumb-dgt.png') no-repeat top left; }
+.g-thumbtype-wd  { background: url('../images/thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-thumbtype-sqr { background-image: url('../images/thumb-sqr-ext.png'); }
+.g-extended .g-thumbtype-flm { background-image: url('../images/thumb-flm-ext.png'); }
+.g-extended .g-thumbtype-dgt { background-image: url('../images/thumb-dgt-ext.png'); }
+.g-extended .g-thumbtype-wd  { background-image: url('../images/thumb-wd-ext.png'); }
+
+.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-e.png'); }
+.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-e.png'); }
+.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-e.png'); }
+.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-e.png'); }
+
+.g-extended .g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-eext.png'); }
+.g-extended .g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-eext.png'); }
+.g-extended .g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-eext.png'); }
+.g-extended .g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-eext.png'); }
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-e.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-e.png
new file mode 100644
index 0000000..c96c40c
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-eext.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-eext.png
new file mode 100644
index 0000000..0f87149
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-ext.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-ext.png
new file mode 100644
index 0000000..ed89c39
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt.png
new file mode 100644
index 0000000..ace3e98
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-dgt.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-e.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-e.png
new file mode 100644
index 0000000..f8e8841
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-eext.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-eext.png
new file mode 100644
index 0000000..4e735c8
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-ext.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-ext.png
new file mode 100644
index 0000000..9c0bff5
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm.png
new file mode 100644
index 0000000..460ee7c
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-flm.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-e.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-e.png
new file mode 100644
index 0000000..eb28835
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-eext.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-eext.png
new file mode 100644
index 0000000..3af47df
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-ext.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-ext.png
new file mode 100644
index 0000000..d2e268e
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr.png
new file mode 100644
index 0000000..da45039
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-sqr.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-e.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-e.png
new file mode 100644
index 0000000..62f5f1e
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-eext.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-eext.png
new file mode 100644
index 0000000..bf8b2e7
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-ext.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-ext.png
new file mode 100644
index 0000000..bc994bc
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd.png b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd.png
new file mode 100644
index 0000000..62e7881
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/darkglass/images/thumb-wd.png differ
diff --git a/themes/greydragon_old/css/framepacks/greydragon/css/frame.css b/themes/greydragon_old/css/framepacks/greydragon/css/frame.css
new file mode 100644
index 0000000..cb6c0fc
--- /dev/null
+++ b/themes/greydragon_old/css/framepacks/greydragon/css/frame.css
@@ -0,0 +1,40 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - GreyDragon
+ */
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in { min-width: 1302px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in { min-width: 1546px; }
+
+.g-thumbslide { margin-right: 6px; }
+.g-thumbslide .g-description { margin: 1px 0 0 2px; }
+.g-thumbslide .g-metadata    { margin-bottom: 4px; margin-left: 2px; }
+
+.g-extended #g-album-grid .g-item { min-width: 320px; }
+
+.g-item .g-context-menu { left: 190px; top: 12px; }
+.g-item .g-context-menu:hover { left: 6px; top: 6px; }
+
+.g-extended .g-item .g-context-menu { left: 290px; top: 12px; }
+.g-extended .g-item .g-context-menu:hover { left: 8px; top: 8px; }
+
+.g-thumbslide, .g-thumbslide-ext, .g-thumbcrop { border-width: 1px; border-style: solid; background-color: inherit; }
+.g-album .g-thumbslide, .g-album .g-thumbslide-ext { border-right-width: 4px; border-right-style: double; border-bottom-width: 4px; border-bottom-style: double; }
+.g-photo .g-thumbslide, .g-photo .g-thumbslide-ext { margin-bottom: 4px; } /* Need to compensate for double border in album's thumbs */
+
diff --git a/themes/greydragon_old/css/framepacks/iphone/css/frame.css b/themes/greydragon_old/css/framepacks/iphone/css/frame.css
new file mode 100644
index 0000000..0d24188
--- /dev/null
+++ b/themes/greydragon_old/css/framepacks/iphone/css/frame.css
@@ -0,0 +1,31 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - iPhone
+ */
+
+#g-album-grid>li { padding: 10px 6px 10px 10px; }
+.g-thumbslide { background: transparent; }
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { border-color: #7D7E7D; }
+.g-thumbcrop { border-width: 1px; border-style: solid; border-color: #7D7E7D; } 
+
+.g-thumbtype-sqr { background: url('../images/thumb-sqr.png') no-repeat top left; }
+.g-thumbtype-flm { background: url('../images/thumb-flm.png') no-repeat top left; }
+.g-thumbtype-dgt { background: url('../images/thumb-dgt.png') no-repeat top left; }
+.g-thumbtype-wd  { background: url('../images/thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-thumbtype-sqr { background-image: url('../images/thumb-sqr-ext.png'); }
+.g-extended .g-thumbtype-flm { background-image: url('../images/thumb-flm-ext.png'); }
+.g-extended .g-thumbtype-dgt { background-image: url('../images/thumb-dgt-ext.png'); }
+.g-extended .g-thumbtype-wd  { background-image: url('../images/thumb-wd-ext.png'); }
+
+.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-e.png'); }
+.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-e.png'); }
+.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-e.png'); }
+.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-e.png'); }
+
+.g-extended .g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-eext.png'); }
+.g-extended .g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-eext.png'); }
+.g-extended .g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-eext.png'); }
+.g-extended .g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-eext.png'); }
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-e.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-e.png
new file mode 100644
index 0000000..daa2002
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-eext.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-eext.png
new file mode 100644
index 0000000..9362e8b
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-ext.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-ext.png
new file mode 100644
index 0000000..e477616
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt.png
new file mode 100644
index 0000000..c514620
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-dgt.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-e.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-e.png
new file mode 100644
index 0000000..3d3ddaa
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-eext.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-eext.png
new file mode 100644
index 0000000..aedd558
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-ext.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-ext.png
new file mode 100644
index 0000000..62e62a2
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm.png
new file mode 100644
index 0000000..0094def
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-flm.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-e.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-e.png
new file mode 100644
index 0000000..1dc590c
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-eext.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-eext.png
new file mode 100644
index 0000000..9f6024b
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-ext.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-ext.png
new file mode 100644
index 0000000..4233c84
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr.png
new file mode 100644
index 0000000..c9e5714
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-sqr.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-e.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-e.png
new file mode 100644
index 0000000..15a0c4c
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-eext.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-eext.png
new file mode 100644
index 0000000..0867baa
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-ext.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-ext.png
new file mode 100644
index 0000000..213d494
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd.png b/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd.png
new file mode 100644
index 0000000..a25d477
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphone/images/thumb-wd.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/css/frame.css b/themes/greydragon_old/css/framepacks/iphoto/css/frame.css
new file mode 100644
index 0000000..0dba3e9
--- /dev/null
+++ b/themes/greydragon_old/css/framepacks/iphoto/css/frame.css
@@ -0,0 +1,31 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - iPhoto
+ */
+
+#g-album-grid>li { padding: 10px 6px 10px 10px; }
+.g-thumbslide { background: transparent; }
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { background-color: #FFF; border-color: #ADAEAD; color: #111; }
+.g-thumbcrop { border: #ADAEAD 1px solid; } 
+
+.g-thumbtype-sqr { background: url('../images/thumb-sqr.png') no-repeat top left; }
+.g-thumbtype-flm { background: url('../images/thumb-flm.png') no-repeat top left; }
+.g-thumbtype-dgt { background: url('../images/thumb-dgt.png') no-repeat top left; }
+.g-thumbtype-wd  { background: url('../images/thumb-wd.png') no-repeat top left; }
+
+.g-extended .g-thumbtype-sqr { background-image: url('../images/thumb-sqr-ext.png'); }
+.g-extended .g-thumbtype-flm { background-image: url('../images/thumb-flm-ext.png'); }
+.g-extended .g-thumbtype-dgt { background-image: url('../images/thumb-dgt-ext.png'); }
+.g-extended .g-thumbtype-wd  { background-image: url('../images/thumb-wd-ext.png'); }
+
+.g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-e.png'); }
+.g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-e.png'); }
+.g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-e.png'); }
+.g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-e.png'); }
+
+.g-extended .g-thumbtype-sqr.g-expanded { background-image: url('../images/thumb-sqr-eext.png'); }
+.g-extended .g-thumbtype-flm.g-expanded { background-image: url('../images/thumb-flm-eext.png'); }
+.g-extended .g-thumbtype-dgt.g-expanded { background-image: url('../images/thumb-dgt-eext.png'); }
+.g-extended .g-thumbtype-wd.g-expanded  { background-image: url('../images/thumb-wd-eext.png'); }
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-e.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-e.png
new file mode 100644
index 0000000..616d1d5
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-eext.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-eext.png
new file mode 100644
index 0000000..828528a
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-ext.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-ext.png
new file mode 100644
index 0000000..c090406
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt.png
new file mode 100644
index 0000000..5190758
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-dgt.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-e.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-e.png
new file mode 100644
index 0000000..251216b
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-eext.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-eext.png
new file mode 100644
index 0000000..c60ba42
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-ext.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-ext.png
new file mode 100644
index 0000000..b1f8675
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm.png
new file mode 100644
index 0000000..44c67c3
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-flm.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-e.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-e.png
new file mode 100644
index 0000000..02ddcd2
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-eext.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-eext.png
new file mode 100644
index 0000000..a6f6946
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-ext.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-ext.png
new file mode 100644
index 0000000..de2fae4
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr.png
new file mode 100644
index 0000000..57c192f
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-sqr.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-e.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-e.png
new file mode 100644
index 0000000..492432e
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-e.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-eext.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-eext.png
new file mode 100644
index 0000000..901a13a
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-eext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-ext.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-ext.png
new file mode 100644
index 0000000..0efa766
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd-ext.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd.png b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd.png
new file mode 100644
index 0000000..f6bb30f
Binary files /dev/null and b/themes/greydragon_old/css/framepacks/iphoto/images/thumb-wd.png differ
diff --git a/themes/greydragon_old/css/framepacks/iphoto/views/frame.html.php b/themes/greydragon_old/css/framepacks/iphoto/views/frame.html.php
new file mode 100644
index 0000000..87ed99b
--- /dev/null
+++ b/themes/greydragon_old/css/framepacks/iphoto/views/frame.html.php
@@ -0,0 +1,5 @@
+<div class="g-thumb-wrapper"><div class="g-thumb-content"><div class="g-thumb-topleft"></div>
+	<?= $thumb_content; ?>
+	</div>
+	<div class="g-thumb-bottom"><div></div></div>
+</div>
diff --git a/themes/greydragon_old/css/framepacks/panel/css/frame.css b/themes/greydragon_old/css/framepacks/panel/css/frame.css
new file mode 100644
index 0000000..6a25113
--- /dev/null
+++ b/themes/greydragon_old/css/framepacks/panel/css/frame.css
@@ -0,0 +1,35 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Panel
+ */
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in { min-width: 1302px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in { min-width: 1546px; }
+
+.g-album .g-thumbslide, .g-thumbslide { border-width: 1px; border-style: solid; }
+.g-thumbslide .g-description { margin: 0 0 0 1px; }
+.g-thumbslide .g-metadata    { margin-bottom: 3px; margin-left: 1px; }
+
+.g-extended #g-album-grid .g-item { min-width: 320px; }
+
+.g-item .g-context-menu { left: 188px; top: 12px; }
+.g-item .g-context-menu:hover { left: 6px; top: 6px; }
+.g-extended .g-item .g-context-menu { left: 288px; top: 12px; }
+.g-extended .g-item .g-context-menu:hover { left: 6px; top: 6px; }
+
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { border-color: #ADAEAD; }
diff --git a/themes/greydragon_old/css/framepacks/roundcorners/css/frame.css b/themes/greydragon_old/css/framepacks/roundcorners/css/frame.css
new file mode 100644
index 0000000..9e44c1e
--- /dev/null
+++ b/themes/greydragon_old/css/framepacks/roundcorners/css/frame.css
@@ -0,0 +1,42 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Round Corners
+ */
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in,
+body.g-extended.g-column-4 #g-header { min-width: 1278px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in { min-width: 1520px; }
+
+.g-thumbslide .g-description { margin: 0 0 0 0px; border-top-left-radius: 10px; border-top-right-radius: 10px; }
+.g-thumbslide .g-description.g-overlay-bottom { border-top-left-radius: 0; border-top-right-radius: 0; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; bottom: -3px; }
+.g-thumbslide .g-metadata    { margin: 0 0 1px 0px; }
+
+.g-item .g-context-menu { left: 188px; top: 12px; }
+.g-item .g-context-menu:hover { left: 6px; top: 6px; }
+.g-extended .g-item .g-context-menu { left: 288px; top: 12px; }
+.g-extended .g-item .g-context-menu:hover { left: 6px; top: 6px; }
+
+.g-default .g-thumbslide .g-description, 
+.g-expanded .g-thumbslide .g-description { border-color: #ADAEAD; color: #3c5580; }
+.g-thumbslide .g-metadata { border-color: #ADAEAD; color: #3c5580; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; }
+.g-thumbcrop { border-radius: 10px; box-shadow: 3px 3px 8px #333; }
+.g-thumbslide { background-image: none; }
+.g-thumbslide:hover .g-thumbcrop { box-shadow: 4px 4px 8px #333; }
+
+#g-photo .g-resize { border: none; background: transparent; }
+#g-photo .g-resize a { border-radius: 10px; box-shadow: 3px 3px 8px #333; }
\ No newline at end of file
diff --git a/themes/greydragon_old/css/framepacks/simple/css/frame.css b/themes/greydragon_old/css/framepacks/simple/css/frame.css
new file mode 100644
index 0000000..648057e
--- /dev/null
+++ b/themes/greydragon_old/css/framepacks/simple/css/frame.css
@@ -0,0 +1,33 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Simple
+ */
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in { min-width: 1278px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in { min-width: 1520px; }
+
+.g-thumbslide .g-description { margin: 0 0 0 1px; }
+.g-thumbslide .g-metadata    { margin: 0 0 1px 1px; }
+
+.g-item .g-context-menu { left: 188px; top: 12px; }
+.g-item .g-context-menu:hover { left: 6px; top: 6px; }
+.g-extended .g-item .g-context-menu { left: 288px; top: 12px; }
+.g-extended .g-item .g-context-menu:hover { left: 6px; top: 6px; }
+
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description, .g-thumbslide .g-metadata { border-color: #ADAEAD; }
+.g-thumbcrop { border-width: 1px; border-style: solid; border-color: #ADAEAD; }
diff --git a/themes/greydragon_old/css/framepacks/wall/css/frame.css b/themes/greydragon_old/css/framepacks/wall/css/frame.css
new file mode 100644
index 0000000..b8f434b
--- /dev/null
+++ b/themes/greydragon_old/css/framepacks/wall/css/frame.css
@@ -0,0 +1,46 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2010 Serguei Dosyukov
+ *
+ * CSS rules - Frames - Simple
+ */
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in { min-width: 1224px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in { min-width: 1470px; }
+
+
+.g-thumbslide { padding-top: 0; padding-left: 0; width: 200px; min-height: auto; }
+.g-extended .g-thumbslide { width: 300px; }
+
+.g-thumbtype-flm .g-thumbslide, .g-extended .g-thumbtype-flm .g-thumbslide,
+.g-thumbtype-dgt .g-thumbslide, .g-extended .g-thumbtype-dgt .g-thumbslide,
+.g-thumbtype-wd  .g-thumbslide, .g-extended .g-thumbtype-wd  .g-thumbslide,
+.g-thumbtype-sqr .g-thumbslide, .g-extended .g-thumbtype-sqr .g-thumbslide { height: auto; }
+
+.g-item .g-context-menu { left: 184px; top: 2px; }
+.g-extended .g-item .g-context-menu { left: 282px; top: 4px; }
+.g-item .g-context-menu:hover, .g-extended .g-item .g-context-menu:hover { left: 0px; top: 0; }
+
+#g-album-grid .g-item { margin: 0; min-width: 200px; }
+.g-extended #g-album-grid .g-item { min-width: 300px; }
+
+.g-album-grid-container .g-wall > li { width: auto; }
+
+.g-thumbslide .g-description { margin: 0 0 0 0; left: 0; top: 0; min-height: 2.4em; }
+.g-thumbslide .g-metadata    { margin: 0 0 0 0; left: 0; bottom: 0; min-height: 2.4em; }
+
+.g-default .g-thumbslide .g-description, .g-expanded .g-thumbslide .g-description { border-color: #ADAEAD; border-top: none; }
+.g-thumbcrop { border: none; }
diff --git a/themes/greydragon_old/css/gd_common.css b/themes/greydragon_old/css/gd_common.css
new file mode 100644
index 0000000..32b780b
--- /dev/null
+++ b/themes/greydragon_old/css/gd_common.css
@@ -0,0 +1,59 @@
+/**
+ * Gallery 3 Grey Dragon Common Module
+ * Copyright (C) 2012 Serguei Dosyukov
+ *
+ * CSS rules for admin section
+ */
+
+body { min-width: 1200px; }
+
+#g-content { font-size: 1em; margin-bottom: 0; width: auto; padding-left: 1em; padding-right: 1em; }
+#g-content ul { margin-bottom: 0; }
+
+#g-content h3 { color: #d54e21; border-bottom: #a2bdbf 1px solid; margin-top: 0.3em; margin-bottom: 0.3em; }
+#g-content p  { color: #333; }
+#g-content table { margin-bottom: 0; }
+
+#g-content input     { display: inline; float: left; margin-right: 0.8em; color: #555555; border: 1px solid #ccc; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }
+#g-content textarea  { height: 6em; color: #555555; border: 1px solid #ccc; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }
+#g-content select    { display: inline; float: left; margin-right: 0.8em; width: 50.6%; color: #555555; border: 1px solid #ccc; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }
+
+#g-content input[type='checkbox'] { border: none; }
+#g-content input[type='text'] { width: 50%; }
+
+#g-content input.submit { display: inline-block; min-width: 100px; padding: 4px 10px 4px; font-size: 13px; line-height: 18px; color:#333333; text-align: center; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); background-color: #fafafa; background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-repeat: no-repeat; filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); border: 1px solid #ccc; border-bottom-color: #bbb; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05); cursor: pointer; *margin-left: .3em; }
+#g-content input.submit:first-child { *margin-left: 0; }
+#g-content input.submit:hover { color: #333333; text-decoration: none; background-color: #e6e6e6; background-position: 0 -15px; -webkit-transition: background-position 0.1s linear; -moz-transition: background-position 0.1s linear; -ms-transition: background-position 0.1s linear; -o-transition: background-position 0.1s linear; transition: background-position 0.1s linear; }
+
+#g-content input.g-error   { padding-left: 30px; border: none; }
+#g-content input.g-success { background-color: transparent; }
+#g-content input.g-warning { background-color: transparent; border: none; }
+
+#g-content p.g-error       { padding-left: 30px; border: none; margin-bottom: 0; background-image: none; }
+
+#gd-admin-header { padding: 7px 0; margin: 4px 0 0 0; background-color: #fbfbfb; background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); background-image:- ms-linear-gradient(top, #ffffff, #f5f5f5); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); background-image: linear-gradient(top, #ffffff, #f5f5f5); background-repeat: repeat-x; filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); border: 1px solid #ddd; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; display: inline-block;  width: 100%; }
+#gd-admin-header .divider{padding:0 5px;color:#999999;}
+#gd-admin-header .active a{color:#333333;}
+
+#gd-admin-version, 
+#gd-admin-version-2 { margin-top: 4px; padding: 7px 14px; background-color: rgb(217, 237, 247); border: 1px solid #bce8f1; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; }
+
+#gd-admin-title     { float: left; padding-left: 10px; color: #333v42; font-weight: bold; font-size: 1.4em; text-shadow: #deeefa 0 1px 0; display: inline-block; }
+#gd-admin-hlinks    { float: right; padding-right: 10px; }
+#gd-admin-hlinks li { list-style-type: none; float: left; color: #618299; display: inline; text-shadow: 0 1px 0 #ffffff; }
+#gd-admin-hlinks a  { line-height: 1.6em; }
+#gd-admin-hlinks a[disabled="disabled"], #gd-admin-hlinks a[disabled="disabled"]:hover { text-decoration: none; cursor: default; }
+
+#g-autoupdate-config { display: none; border: 1px solid #ddd; border-top: none; width: 45%; height: 2.5em; margin-left: 54%; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; }
+#g-autoupdate-config.visible { min-height: 30px; display: inline-block;  }
+#g-autoupdate-config ul { float: right; margin: 6px 10px;}
+#g-autoupdate-config li { float: left; display: inline; line-height: 1.5em; }
+
+#g-admin-container          { margin-top: 14px; font-size: 0.9em; line-height: 1.6em; }
+#g-admin-container .column1 { float: left; width: 53%; min-width: 610px; }
+#g-admin-container .column2 { float: right; width: 46%; min-width: 529px; }
+
+#g-admin-container fieldset { position: relative; border-top-left-radius: 0.4em; border-top-right-radius: 0.4em; overflow: hidden; }
+#g-admin-container legend   { position: absolute; left: 0; width: 100%; padding: 0.4em 0.8em; background: url(../images/blue-grad.png) #d5e6f2 repeat-x left top; border-bottom: #dfdfdf 1px solid;  }
+#g-admin-container fieldset ul { margin-top: 34px; }
+
diff --git a/themes/greydragon_old/css/ipad.css b/themes/greydragon_old/css/ipad.css
new file mode 100644
index 0000000..801356f
--- /dev/null
+++ b/themes/greydragon_old/css/ipad.css
@@ -0,0 +1,20 @@
+/* Start Apple Styles */
+/* These styles support Apple products display of CSS. NOTES (orientation:landscape), (orientation:portrait) can also be used to be more specific */
+/* iPad [portrait + landscape] */
+@media only screen and (min-device-width:768px) and (max-device-width:1024px)
+{
+	#cboxOverlay { height: 200%; width: 200%; }
+	.g-bar#g-site-menu { width: 200%; }
+}
+
+/* iPhone 4 [portrait + landscape] */
+@media only screen and (resolution:326dpi) { }
+
+/* screen and (resolution: 163dpi) */
+/* iPhone 3 [portrait + landscape] */
+@media only screen and (max-device-width:480px) { }
+
+/* iPod Touch and older [portrait + landscape] */
+@media only screen and (resolution:326dpi) { }
+
+/* End Apple Styles */
diff --git a/themes/greydragon_old/css/layout.css b/themes/greydragon_old/css/layout.css
new file mode 100644
index 0000000..189ed93
--- /dev/null
+++ b/themes/greydragon_old/css/layout.css
@@ -0,0 +1,67 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules related to general layout
+ * Defined as 70em wide
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* layout.css - Common ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+html { overflow: auto; overflow: -moz-scrollbars-vertical; overflow-y: scroll; }
+* { margin: 0px; }
+body { min-width: 1020px; padding: 0; }
+.g-hideitem { display: none; }
+
+/* layout.css - Header ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-header { position: relative; min-width: 1020px; z-index: 5; }
+
+/* layout.css - Main ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-main { min-width: 1020px; height: auto; bottom: auto; }
+#g-main-in { min-width: 1020px; height: 100%; aoverflow: auto; bottom: auto; }
+
+#g-column-left   { float: left;  width: 230px; min-height: 32em; overflow: hidden; height: 100%; }
+#g-column-right  { float: right; width: 230px; min-height: 32em; overflow: hidden; height: 100%; }
+#g-column-center { margin: 0 17em 0 17em; min-height: 32em; overflow: hidden; height: 100%; }
+#g-column-centerleft { min-height: 32em; overflow: hidden; height: 100%; }
+#g-column-centerright { min-height: 32em; overflow: hidden; height: 100%; } 
+#g-column-centerfull { position: relative; min-height: 31em; overflow: hidden; height: 100%; }
+#g-column-top { display: block; overflow: hidden; }
+#g-column-bottom { display: block; overflow: hidden; }
+
+/* layout.css - Footer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-footer { position: relative; height: auto; min-width: 70em; min-height: 2.8em; clear: both; display: block; overflow: auto; }
+#g-footer-leftside { float: left; display: inline; }
+#g-footer-rightside { float: right; display: inline; }
+
+/* layout.css - Extended Layout ~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* layous.css - Extended Layout - 3 columns+sidebar ~~*/
+body.g-extended.g-column-3.g-sidebar-right #g-header,
+body.g-extended.g-column-3.g-sidebar-right #g-footer,
+body.g-extended.g-column-3.g-sidebar-right #g-main,
+body.g-extended.g-column-3.g-sidebar-right #g-main-in,
+body.g-extended.g-column-3.g-sidebar-left #g-header,
+body.g-extended.g-column-3.g-sidebar-left #g-footer,
+body.g-extended.g-column-3.g-sidebar-left #g-main,
+body.g-extended.g-column-3.g-sidebar-left #g-main-in { min-width: 1250px; }
+
+/* layous.css - Extended Layout - 4 columns ~~~~~~~~~~*/
+body.g-extended.g-column-4 #g-header,
+body.g-extended.g-column-4 #g-footer,
+body.g-extended.g-column-4 #g-main,
+body.g-extended.g-column-4 #g-main-in { min-width: 1342px; }
+
+/* layous.css - Extended Layout - 4 columns+sidebar ~~*/
+body.g-extended.g-column-4.g-sidebar-right #g-header,
+body.g-extended.g-column-4.g-sidebar-right #g-footer,
+body.g-extended.g-column-4.g-sidebar-right #g-main,
+body.g-extended.g-column-4.g-sidebar-right #g-main-in,
+body.g-extended.g-column-4.g-sidebar-left #g-header,
+body.g-extended.g-column-4.g-sidebar-left #g-footer,
+body.g-extended.g-column-4.g-sidebar-left #g-main,
+body.g-extended.g-column-4.g-sidebar-left #g-main-in { min-width: 1580px; }
diff --git a/themes/greydragon_old/css/menus.css b/themes/greydragon_old/css/menus.css
new file mode 100644
index 0000000..f13fb33
--- /dev/null
+++ b/themes/greydragon_old/css/menus.css
@@ -0,0 +1,58 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules related to menus
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* menus.css - Main menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-site-menu { position: absolute; } 
+#g-site-menu.g-default { left: 21em; bottom: 0; }
+#g-site-menu.g-top { left: 21em; top: 2px; }
+#g-site-menu.g-bottom-right { bottom: 0; right: 2em; }
+#g-site-menu.g-bar { left: 0; top: 0; width: 100%; padding-left: .5em; position: fixed !important; z-index: 9999; font-size: 0.9em; }
+
+#g-site-menu ul { float: left; width: 100%; white-space: nowrap; z-index: 102; }
+#g-site-menu>ul>li>ul { margin-top: 1px; }
+
+#g-site-menu ul ul ul { padding-top: 0; }
+#g-site-menu a  { display: block; padding: 0.2em 0.4em; text-align: center; width: auto; letter-spacing: 0; cursor: pointer; z-index: 102; }
+#g-site-menu li { float: left; padding: 0; background-color: transparent; border: transparent 1px solid; z-index: 102; }
+#g-site-menu li ul a { text-align: left; padding: 0.3em 0; text-indent: 0.8em; letter-spacing: 0; }
+#g-site-menu li ul a:hover { background-image: none; }
+#g-site-menu li ul { position: absolute; margin: 0 0 0 -1px; width: 14em; height: auto; left: -999em; }
+
+#g-site-menu li li { width: 14em; padding-right: 0; }
+#g-site-menu li ul a { width: 14em; }
+#g-site-menu li ul ul { margin: -1.8em 0 0 14em; }
+#g-site-menu li:hover ul ul,
+#g-site-menu li:hover ul ul ul,
+#g-site-menu li.iemhover ul ul,
+#g-site-menu li.iemhover ul ul ul { left: -999em; }
+#g-site-menu li:hover ul,
+#g-site-menu li li:hover ul,
+#g-site-menu li li li:hover ul,
+#g-site-menu li.iemhover ul,
+#g-site-menu li li.iemhover ul,
+#g-site-menu li li li.iemhover ul { left: auto; }
+
+#g-site-menu>ul>li>ul { display: none; }
+
+/* menus.css - Context menu ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.g-item .g-context-menu { position: absolute; margin: 0; padding: 0; top: 20px; left: 198px; width: 14px; height: 14px; background-position: -178px -144px; z-index: 4; } 
+.g-item .g-context-menu li { width: 100%; padding: 0; margin: 0; text-indent: -9999px; }
+.g-item .g-context-menu>li>a { font-size: 0em; }
+.g-item .g-context-menu:hover { top: 4px; left: 16px; top: 16px; width: 200px; height: auto; z-index: 102; }
+
+.g-extended .g-item .g-context-menu { left: 300px; }
+.g-extended .g-item .g-context-menu:hover { width: 300px; left: 16px; }
+.g-item .g-context-menu ul { padding: 0; margin: 0; }
+.g-item .g-context-menu li li { display: none; }
+.g-item .g-context-menu li li a { display: block; padding: 4px 6px; }
+.g-item .g-context-menu:hover li li { display: block; text-indent: 0px; } 
+
+.g-item.g-detail .g-context-menu { left: auto; right: 6px; }
+.g-item.g-detail .g-context-menu:hover { left: auto; right: 6px; }
\ No newline at end of file
diff --git a/themes/greydragon_old/css/modules.css b/themes/greydragon_old/css/modules.css
new file mode 100644
index 0000000..0271c23
--- /dev/null
+++ b/themes/greydragon_old/css/modules.css
@@ -0,0 +1,164 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules related to modules
+ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* modules.css - ShadowBox Skin ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#sb-title { overflow: hidden; }
+#sb-title-inner { font-size: 10pt; font-weight: bold; padding-left: 10px; }
+#sb-nav #sb-nav-close { background-image: url('../images/close.png'); width: 60px; }
+#sb-container > #sb-overlay { min-height: 530px; overflow: auto; }
+
+/* modules.css - FancyBox Skin ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#fancybox-outer { background: #555; }
+#fancybox-content { border-color: #555; }
+#fancybox-title-over { font-weight: bold; }
+.fancybox-title-inside { background: transparent; font-weight: bold; color: #FFF; text-align: left; }
+#fancybox-close { background: url(../images/close.png) 0 0 no-repeat; width: 60px; height: 16px; right: -6px; }
+#fancybox-left-ico { background: url(../images/arrows_left.png) no-repeat left center; width: 35px; height: 107px; top: 40%; }
+#fancybox-left:hover span { left: 10px; }
+#fancybox-right-ico { background: url(../images/arrows_right.png) no-repeat left center; width: 35px; height: 107px; top: 40%; }
+#fancybox-right:hover span { right: 10px; }
+
+/* modules.css - Exif Data ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-data td { padding: 0.2em; }
+.g-thumbcrop a.g-meta-exif-link { position: absolute; left: 278px; bottom: 4px; z-index: 100; display: block; background: none center bottom no-repeat; width: 17px; height: 16px; }
+
+/* modules.css - Image Block ~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-image-block>div { margin-left: 1px; margin-right: 1px; }
+.g-image-block { text-align: center; }
+.g-image-block img { padding: 5px; max-width: 200px; height: auto; }
+
+/* modules.css - Image Block Ex ~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-rootpage #g-column-bottom #g-image-block-ex { display: none; }
+
+/* modules.css - RSS Feeds ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ul#g-feeds { padding: 0; margin: 0; }
+
+/* modules.css - Tags ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-tag-cloud ul { padding: 0; font-size: 100%; }
+#g-tag-cloud ul li { line-height: 1.2em; }
+#g-tag-cloud ul li span { display: none; }
+
+#g-add-tag-form fieldset ul { float: left; display: inline-block; padding: 0; }
+#g-add-tag-form li { float: left; margin: 0; padding: 0; }
+
+/* modules.css - Comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-comments { margin-top: 2em; float: left; width: 100%; min-height: 2em; }
+#g-comments ul li { margin: 0.4em 0; }
+
+#g-comments .g-button { right: 0.4em; cursor: pointer; /* hand-shaped cursor */ cursor: hand; /* for IE 5.x */ font-size: 0.8em; color: #333 !important; padding: 2px 10px; margin-top: 0.4em; border: 1px solid; border-color: #999 #666 #666 #999; background-color: #ddd; font-weight: normal; }
+.ui-icon-comment { background-position: -210px -144px; }
+
+#g-comment-detail ul { padding: 0; }
+#g-comment-detail>ul>li { margin: 4px 0; padding: 6px; min-height: 40px; }
+#g-comment-detail div { margin-top: 6px; padding-bottom: 8px; }
+#g-comment-detail li.g-no-comments { display: none; }
+#g-comment-detail p.g-no-comments { padding-bottom: 4px; }
+
+#g-comment-form fieldset { border: none; }
+#g-comment-form legend { display: none; width: 100%; }
+#g-comment-form ul { padding: 0; }
+#g-comment-form>fieldset>ul { margin: 0px 10px; }
+#g-comment-form label { display: block; }
+#g-comment-form textarea { width: 99%; height: 140px; }
+#g-comment-form input[type="text"],
+#g-comment-form input[type="password"] { width: 99%; }
+
+#g-comments .g-author { height: 32px; line-height: 32px; }
+#g-comments .g-avatar { height: 32px; margin-right: .4em; width: 32px; }
+
+/* modules.css - Gallery Stats ~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-gallerystats ul { padding: 0; font-size: x-small; }
+
+/* modules.css - Info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-metadata ul { padding: 0; }
+#g-metadata .g-description { margin-top: 0.4em; padding: 0.4em 0; }
+
+/* modules.css - Calendar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-calendarview-link:hover { background-position: left bottom; }
+
+#g-view-calendar-form fieldset { border: none; }
+#g-view-calendar-form ul { padding: 8px; }
+#g-view-calendar-form li { padding-top: 8px; display: inline; padding-left: 10px; }
+#g-view-calendar-form label { margin: 4px 0; }
+#g-view-calendar-form select { margin: 4px 10px; }
+
+table.calendar { border-spacing: 1px; }
+table.calendar td.title a { font-weight: bold; }
+
+/* modules.css - ClustrMaps ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-clustrmaps .g-block-content { text-align: center; }
+
+/* modules.css - GPS Info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-exif-gps-maps ul { padding-left: 0; }
+
+/* modules.css - Search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-quick-search-form { position: absolute; top: 3em; right: 1em; background: none transparent; }
+.viewmode-mini #g-quick-search-form { top: auto; right: auto; left: 1em; bottom: 2px; }
+#g-quick-search-form label { display: none; }
+#g-quick-search-form li { display: inline; float: left; padding: 0px; }
+
+#g-quick-search-form input[type="text"] { width: 150px; padding-top: 0.1em; padding-bottom: 0.1em; }
+#g-quick-search-form input[type="submit"] { display: block; width: 23px; height: 23px; text-indent: -9999px; overflow: hidden; }
+
+/* modules.css - Basket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-header #basket, #g-header a[href="/basket/view_Orders"] { display: none; }
+#g-view-basket span.ui-icon { float: none; }
+
+#g-view-basket .ui-icon-plusthick { background-position: -32px -128px; }
+#g-view-basket .ui-icon-clipboard { background-position: -160px -128px; }
+#g-view-basket .ui-icon-trash     { background-position: -176px -96px; }
+#g-view-basket .ui-icon-cart      { background-position: -48px -112px; }
+#g-view-basket a.g-button { line-height: 2.2em; }
+#g-column-centerfull>.g-block { margin-top: 3em; }
+#g-column-centerfull>div>.basketbuttons>a.g-button>span { display: none; }
+
+/* modules.css - Register ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-welcome-message p { padding-bottom: 6px; }
+#g-change-password-user-form { height: 100%; }
+
+/* modules.css - Localization ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#l10n-client .labels { border-top: white 1px solid; height: 1.7em; }
+#l10n-client h2      { padding-top: 0.4em; padding-bottom: 0.3em; }
+#l10n-client .label.translation { margin-top: -0.4em; height: 1.7em; }
+#l10n-client #l10n-client-toggler { line-height: 1.7em; height: 1.7em; }
+#l10n-client .string-list li { font-size: 0.8em; line-height: 1.1em; }
+#l10n-client #l10n-client-string-select { width: 24%; }
+#l10n-client #l10n-client-string-select .string-list { border: 1px #ccc solid; }
+#l10n-client #g-l10n-search-form ul { padding: 0; }
+#l10n-client #l10n-client-string-editor { margin-left: 1em; }
+#l10n-client-string-editor .source .source-text { margin: 0 0.4em 0 0; border: 1px #ccc solid; padding: 0.4em; line-height: 1em; }
+#l10n-client-string-editor .translation { height: 19em; }
+#l10n-client #l10n-edit-translation { width: 97%; height: 17em; border: 1px #ccc solid; font-family: monospace; padding: 0.4em; }
+
+/* modules.css - jcarousel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+.jcarousel-skin-tango .jcarousel-container { padding-top: 0.5em; }
+
+/* modules.css - ThumbNav ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#g-thumbnav-block-inline { margin-top: 26px; }
+#g-thumbnav-block-inline h2 { display: none; }
+#g-thumbnav-block .g-block-content,
+#g-thumbnav-block-inline .g-block-content { width: 210px; margin-left: auto; margin-right: auto; }
diff --git a/themes/greydragon_old/css/normalize.css b/themes/greydragon_old/css/normalize.css
new file mode 100644
index 0000000..9776813
--- /dev/null
+++ b/themes/greydragon_old/css/normalize.css
@@ -0,0 +1,431 @@
+/*! normalize.css 2011-11-04T15:38 UTC - http://github.com/necolas/normalize.css */
+
+/* =============================================================================
+   HTML5 display definitions
+   ========================================================================== */
+
+/*
+ * Corrects block display not defined in IE6/7/8/9 & FF3
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+nav,
+section {
+    display: block;
+}
+
+/*
+ * Corrects inline-block display not defined in IE6/7/8/9 & FF3
+ */
+
+audio,
+canvas,
+video {
+    display: inline-block;
+    *display: inline;
+    *zoom: 1;
+}
+
+/*
+ * Prevents modern browsers from displaying 'audio' without controls
+ */
+
+audio:not([controls]) {
+    display: none;
+}
+
+/*
+ * Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4
+ * Known issue: no IE6 support
+ */
+
+[hidden] {
+    display: none;
+}
+
+
+/* =============================================================================
+   Base
+   ========================================================================== */
+
+/*
+ * 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units
+ *    http://clagnut.com/blog/348/#c790
+ * 2. Keeps page centred in all browsers regardless of content height
+ * 3. Prevents iOS text size adjust after orientation change, without disabling user zoom
+ *    www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/
+ */
+
+html {
+    font-size: 100%; /* 1 */
+    overflow-y: scroll; /* 2 */
+    -webkit-text-size-adjust: 100%; /* 3 */
+    -ms-text-size-adjust: 100%; /* 3 */
+}
+
+/*
+ * Addresses margins handled incorrectly in IE6/7
+ */
+
+body {
+    margin: 0;
+}
+
+/* 
+ * Addresses font-family inconsistency between 'textarea' and other form elements.
+ */
+
+body,
+button,
+input,
+select,
+textarea {
+    font-family: sans-serif;
+}
+
+
+/* =============================================================================
+   Links
+   ========================================================================== */
+
+/*
+ * Addresses outline displayed oddly in Chrome
+ */
+
+a:focus {
+    outline: thin dotted;
+}
+
+/*
+ * Improves readability when focused and also mouse hovered in all browsers
+ * people.opera.com/patrickl/experiments/keyboard/test
+ */
+
+a:hover,
+a:active {
+    outline: 0;
+}
+
+
+/* =============================================================================
+   Typography
+   ========================================================================== */
+
+/*
+ * Neutralise smaller font-size in 'section' and 'article' in FF4+, Chrome, S5
+ */
+
+h1 {
+    font-size: 2em;
+}
+
+/*
+ * Addresses styling not present in IE7/8/9, S5, Chrome
+ */
+
+abbr[title] {
+    border-bottom: 1px dotted;
+}
+
+/*
+ * Addresses style set to 'bolder' in FF3+, S4/5, Chrome
+*/
+
+b, 
+strong { 
+    font-weight: bold; 
+}
+
+blockquote {
+    margin: 1em 40px;
+}
+
+/*
+ * Addresses styling not present in S5, Chrome
+ */
+
+dfn {
+    font-style: italic;
+}
+
+/*
+ * Addresses styling not present in IE6/7/8/9
+ */
+
+mark {
+    background: #ff0;
+    color: #000;
+}
+
+/*
+ * Corrects font family set oddly in IE6, S4/5, Chrome
+ * en.wikipedia.org/wiki/User:Davidgothberg/Test59
+ */
+
+pre,
+code,
+kbd,
+samp {
+    font-family: monospace, serif;
+    _font-family: 'courier new', monospace;
+    font-size: 1em;
+}
+
+/*
+ * Improves readability of pre-formatted text in all browsers
+ */
+
+pre {
+    white-space: pre;
+    white-space: pre-wrap;
+    word-wrap: break-word;
+}
+
+/*
+ * 1. Addresses CSS quotes not supported in IE6/7
+ * 2. Addresses quote property not supported in S4
+ */
+
+/* 1 */
+
+q {
+    quotes: none;
+}
+
+/* 2 */
+
+q:before,
+q:after {
+    content: '';
+    content: none;
+}
+
+small {
+    font-size: 75%;
+}
+
+/*
+ * Prevents sub and sup affecting line-height in all browsers
+ * gist.github.com/413930
+ */
+
+sub,
+sup {
+    font-size: 75%;
+    line-height: 0;
+    position: relative;
+    vertical-align: baseline;
+}
+
+sup {
+    top: -0.5em;
+}
+
+sub {
+    bottom: -0.25em;
+}
+
+
+/* =============================================================================
+   Lists
+   ========================================================================== */
+
+ul,
+ol {
+    margin-left: 0;
+    padding: 0 0 0 40px;
+}
+
+dd {
+    margin: 0 0 0 40px;
+}
+
+nav ul,
+nav ol {
+    list-style: none;
+    list-style-image: none;
+}
+
+
+/* =============================================================================
+   Embedded content
+   ========================================================================== */
+
+/*
+ * 1. Removes border when inside 'a' element in IE6/7/8/9, FF3
+ * 2. Improves image quality when scaled in IE7
+ *    code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
+ */
+
+img {
+    border: 0; /* 1 */
+    -ms-interpolation-mode: bicubic; /* 2 */
+}
+
+/*
+ * Corrects overflow displayed oddly in IE9 
+ */
+
+svg:not(:root) {
+    overflow: hidden;
+}
+
+
+/* =============================================================================
+   Figures
+   ========================================================================== */
+
+/*
+ * Addresses margin not present in IE6/7/8/9, S5, O11
+ */
+
+figure {
+    margin: 0;
+}
+
+
+/* =============================================================================
+   Forms
+   ========================================================================== */
+
+/*
+ * Corrects margin displayed oddly in IE6/7
+ */
+
+form {
+    margin: 0;
+}
+
+/*
+ * Define consistent border, margin, and padding
+ */
+
+fieldset {
+    border: 1px solid #c0c0c0;
+    margin: 0 2px;
+    padding: 0.35em 0.625em 0.75em;
+}
+
+/*
+ * 1. Corrects color not being inherited in IE6/7/8/9
+ * 2. Corrects alignment displayed oddly in IE6/7
+ */
+
+legend {
+    border: 0; /* 1 */
+    *margin-left: -7px; /* 2 */
+}
+
+/*
+ * 1. Corrects font size not being inherited in all browsers
+ * 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome
+ * 3. Improves appearance and consistency in all browsers
+ */
+
+button,
+input,
+select,
+textarea {
+    font-size: 100%; /* 1 */
+    margin: 0; /* 2 */
+    vertical-align: baseline; /* 3 */
+    *vertical-align: middle; /* 3 */
+}
+
+/*
+ * Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet
+ */
+
+button,
+input {
+    line-height: normal; /* 1 */
+}
+
+/*
+ * 1. Improves usability and consistency of cursor style between image-type 'input' and others
+ * 2. Corrects inability to style clickable 'input' types in iOS
+ * 3. Removes inner spacing in IE7 without affecting normal text inputs
+ *    Known issue: inner spacing remains in IE6
+ */
+
+button,
+input[type="button"], 
+input[type="reset"], 
+input[type="submit"] {
+    cursor: pointer; /* 1 */
+    -webkit-appearance: button; /* 2 */
+    *overflow: visible;  /* 3 */
+}
+
+/*
+ * 1. Addresses box sizing set to content-box in IE8/9
+ * 2. Removes excess padding in IE8/9
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+    box-sizing: border-box; /* 1 */
+    padding: 0; /* 2 */
+}
+
+/*
+ * 1. Addresses appearance set to searchfield in S5, Chrome
+ * 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof)
+ */
+
+input[type="search"] {
+    -webkit-appearance: textfield; /* 1 */
+    -moz-box-sizing: content-box;
+    -webkit-box-sizing: content-box; /* 2 */
+    box-sizing: content-box;
+}
+
+/*
+ * Removes inner padding that is displayed in S5, Chrome on OS X
+ */
+
+input[type="search"]::-webkit-search-decoration {
+    -webkit-appearance: none;
+}
+
+/*
+ * Removes inner padding and border in FF3+
+ * www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+    border: 0;
+    padding: 0;
+}
+
+/*
+ * 1. Removes default vertical scrollbar in IE6/7/8/9
+ * 2. Improves readability and alignment in all browsers
+ */
+
+textarea {
+    overflow: auto; /* 1 */
+    vertical-align: top; /* 2 */
+}
+
+
+/* =============================================================================
+   Tables
+   ========================================================================== */
+
+/* 
+ * Remove most spacing between table cells
+ */
+
+table {
+    border-collapse: collapse;
+    border-spacing: 0;
+}
diff --git a/themes/greydragon_old/css/rtl.css b/themes/greydragon_old/css/rtl.css
new file mode 100644
index 0000000..1d74d90
--- /dev/null
+++ b/themes/greydragon_old/css/rtl.css
@@ -0,0 +1,47 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules related to general layout
+ * Defined as 70em wide
+ */
+
+.rtl { direction: rtl; }
+
+.rtl #g-header, .rtl #g-main, .rtl #g-sidebar, .rtl #g-footer, 
+.rtl caption, .rtl th, .rtl #g-dialog, 
+.rtl .g-context-menu li a, .rtl #g-site-menu a,
+.rtl .g-metadata li, .rtl DIV.g-resize .g-description,
+.rtl .g-message-box li, .rtl #g-site-status li { text-align: right; }
+
+.rtl .g-text-right { text-align: left; }
+
+.rtl #g-site-menu li:hover ul ul,
+.rtl #g-site-menu li:hover ul ul ul,
+.rtl #g-site-menu li.iemhover ul ul,
+.rtl #g-site-menu li.iemhover ul ul ul { left: 999em; }
+
+.rtl .g-left, .rtl .g-inline li, .rtl .g-breadcrumbs li, .rtl .g-paginator li,
+.rtl .g-navigation li .rtl .g-buttonset li, .rtl .ui-icon-left .ui-icon,
+.rtl .g-metadata li, 
+.rtl #g-column-bottom .g-block,
+.rtl .g-short-form li, .rtl form ul ul li, .rtl input[type="submit"],
+.rtl input[type="reset"], .rtl input.checkbox, .rtl input[type=checkbox],
+.rtl input.radio, .rtl input[type=radio] { float: right; }
+
+.rtl .g-paginator .g-navigation { text-align: left; }
+
+.rtl #g-column-centerfull #g-album-header h1 { padding-right: 12em; }
+.rtl .g-buttonset .g-menu-link { text-indent: 9999px; }
+
+.rtl .g-thumbslide { padding-left: 0; padding-right: 6px; }
+.rtl .g-thumbslide .g-description { padding-left: 10px; }
+
+.rtl .ui-icon-first { background-position: -210px -178px; }
+.rtl .ui-icon-first-d { background-position: -210px -162px; }
+.rtl .ui-icon-prev { background-position: -194px -178px; }
+.rtl .ui-icon-prev-d { background-position: -194px -162px; }
+.rtl .ui-icon-next { background-position: -178px -178px; }
+.rtl .ui-icon-next-d { background-position: -178px -162px; }
+.rtl .ui-icon-last { background-position: -162px -178px; }
+.rtl .ui-icon-last-d { background-position: -162px -162px; }
diff --git a/themes/greydragon_old/css/screen.css b/themes/greydragon_old/css/screen.css
new file mode 100644
index 0000000..d820ad5
--- /dev/null
+++ b/themes/greydragon_old/css/screen.css
@@ -0,0 +1,17 @@
+/**
+ * Gallery 3 Grey Dragon Theme
+ * Copyright (C) 2006-2011 Serguei Dosyukov
+ *
+ * CSS rules - Kitchen sync
+ *
+ * Color rules for font/background/lines can be found in dedicated colorpack files
+ */
+
+@import "normalize.css";
+@import "layout.css";
+@import "menus.css";
+@import "modules.css";
+@import "forms.css";
+@import "base.css";
+@import "ipad.css";
+@import "rtl.css";
diff --git a/themes/greydragon_old/helpers/exif_event.php b/themes/greydragon_old/helpers/exif_event.php
new file mode 100644
index 0000000..02536ff
--- /dev/null
+++ b/themes/greydragon_old/helpers/exif_event.php
@@ -0,0 +1,45 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+class exif_event_Core {
+  static function item_created($item) {
+    if (!$item->is_album()) {
+      exif::extract($item);
+    }
+  }
+
+  static function item_deleted($item) {
+    db::build()
+      ->delete("exif_records")
+      ->where("item_id", "=", $item->id)
+      ->execute();
+  }
+
+  static function photo_menu($menu, $theme) {
+    $item = $theme->item();
+    $menu->append(
+      Menu::factory("link")
+      ->id("exifdata-link")
+      ->label(t("Photo Details"))
+      ->url(url::site("exif/show/$item->id"))
+      ->css_id("g-exifdata-link")
+      ->css_class("g-dialog-link"));
+  }
+}
+?>
diff --git a/themes/greydragon_old/helpers/greydragon_event.php b/themes/greydragon_old/helpers/greydragon_event.php
new file mode 100644
index 0000000..8761b1a
--- /dev/null
+++ b/themes/greydragon_old/helpers/greydragon_event.php
@@ -0,0 +1,92 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+class greydragon_event_Core {
+
+  static function site_menu($menu, $theme) {
+    $submenu = $menu->get("add_menu");
+    if (!empty($submenu)) {
+      $item = $submenu->get("add_photos_item");
+      if (!empty($item)) { $item->css_class("ui-icon-plus"); }
+
+      $item = $submenu->get("add_album_item");
+      if (!empty($item)) { $item->css_class("ui-icon-note"); }
+    }
+
+    $submenu = $menu->get("options_menu");
+    if (!empty($submenu)) {
+      $item = $submenu->get("edit_item");
+      if (!empty($item)) { $item->css_class("ui-icon-pencil"); }
+
+      $item = $submenu->get("edit_permissions");
+      if (!empty($item)) { $item->css_class("ui-icon-key"); }
+    }
+  }
+
+  static function read_session_cmdparam($cmd, $cookie, $default) {
+    try {
+      $_cmd = $_GET[$cmd]; 
+    } catch (Exception $e) {
+    };
+
+    if (isset($_cmd)):
+      $_var = strtolower($_cmd);
+      $_from_cmd = TRUE;
+      if ($_var == "default"):
+        $_var = $default;
+      endif;
+    else:
+      $_from_cmd = FALSE;
+      if ($cookie):
+        try { 
+          $_var = $_COOKIE[$cookie];
+        } catch (Exception $e) {
+        };
+      endif;
+    endif;
+
+    if (!isset($_var)):
+      $_var = $default;
+    endif;
+
+    return $_var;
+  }
+
+  static function add_path($path) {
+    $config = Kohana_Config::instance();
+    $kohana_modules = $config->get("core.modules");                                                  
+    array_unshift($kohana_modules, THEMEPATH . $path); 
+    $config->set("core.modules",  $kohana_modules);
+    Kohana::include_paths(true);
+  }
+
+  static function add_path_ex($setting, $cmd, $cookie, $path, $default) {
+    $value = module::get_var("th_greydragon", $setting, $default);
+    $value = self::read_session_cmdparam($cmd, $cookie, $value);
+
+    self::add_path("greydragon/css/" . $path . "/" . $value);
+  }
+
+  static function gallery_ready() {
+    self::add_path_ex("frame_pack", "framepack", "gd_framepack", "framepacks", "greydragon");
+    self::add_path_ex("color_pack", "colorpack", "gd_colorpack", "colorpacks", "greydragon");
+    self::add_path("custom");
+  }
+}
+?>
\ No newline at end of file
diff --git a/themes/greydragon_old/helpers/greydragon_installer.php b/themes/greydragon_old/helpers/greydragon_installer.php
new file mode 100644
index 0000000..4f19787
--- /dev/null
+++ b/themes/greydragon_old/helpers/greydragon_installer.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+class greydragon_installer {
+  static function install() {
+    site_status::warning(t("Initial configuration for the theme may be required. Visit Admin\Appearance\Theme Options before continue."), "gd_init_configuration");
+  }
+
+  static function deactivate() {
+    site_status::clear("gd_init_configuration");
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/themes/greydragon_old/helpers/greydragon_theme.php b/themes/greydragon_old/helpers/greydragon_theme.php
new file mode 100644
index 0000000..1c502c1
--- /dev/null
+++ b/themes/greydragon_old/helpers/greydragon_theme.php
@@ -0,0 +1,20 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2011 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<? // Nothing to do here, just to fix errors when Kohana is unhappy about the file missing
+?>
diff --git a/themes/greydragon_old/images/apple-touch-icon.png b/themes/greydragon_old/images/apple-touch-icon.png
new file mode 100644
index 0000000..5017ea4
Binary files /dev/null and b/themes/greydragon_old/images/apple-touch-icon.png differ
diff --git a/themes/greydragon_old/images/arrows_left.png b/themes/greydragon_old/images/arrows_left.png
new file mode 100644
index 0000000..dc9dcdf
Binary files /dev/null and b/themes/greydragon_old/images/arrows_left.png differ
diff --git a/themes/greydragon_old/images/arrows_right.png b/themes/greydragon_old/images/arrows_right.png
new file mode 100644
index 0000000..80188c1
Binary files /dev/null and b/themes/greydragon_old/images/arrows_right.png differ
diff --git a/themes/greydragon_old/images/avatar.jpg b/themes/greydragon_old/images/avatar.jpg
new file mode 100644
index 0000000..71166cc
Binary files /dev/null and b/themes/greydragon_old/images/avatar.jpg differ
diff --git a/themes/greydragon_old/images/blue-grad.png b/themes/greydragon_old/images/blue-grad.png
new file mode 100644
index 0000000..868a657
Binary files /dev/null and b/themes/greydragon_old/images/blue-grad.png differ
diff --git a/themes/greydragon_old/images/button-grad-active-vs.png b/themes/greydragon_old/images/button-grad-active-vs.png
new file mode 100644
index 0000000..dc64172
Binary files /dev/null and b/themes/greydragon_old/images/button-grad-active-vs.png differ
diff --git a/themes/greydragon_old/images/button-grad-vs.png b/themes/greydragon_old/images/button-grad-vs.png
new file mode 100644
index 0000000..51c55a3
Binary files /dev/null and b/themes/greydragon_old/images/button-grad-vs.png differ
diff --git a/themes/greydragon_old/images/close.png b/themes/greydragon_old/images/close.png
new file mode 100644
index 0000000..d874f9a
Binary files /dev/null and b/themes/greydragon_old/images/close.png differ
diff --git a/themes/greydragon_old/images/donate.png b/themes/greydragon_old/images/donate.png
new file mode 100644
index 0000000..f36bb57
Binary files /dev/null and b/themes/greydragon_old/images/donate.png differ
diff --git a/themes/greydragon_old/images/gallery.png b/themes/greydragon_old/images/gallery.png
new file mode 100644
index 0000000..038b18a
Binary files /dev/null and b/themes/greydragon_old/images/gallery.png differ
diff --git a/themes/greydragon_old/images/ico-allowed.png b/themes/greydragon_old/images/ico-allowed.png
new file mode 100644
index 0000000..08f2493
Binary files /dev/null and b/themes/greydragon_old/images/ico-allowed.png differ
diff --git a/themes/greydragon_old/images/ico-denied-inactive.png b/themes/greydragon_old/images/ico-denied-inactive.png
new file mode 100644
index 0000000..56db3ff
Binary files /dev/null and b/themes/greydragon_old/images/ico-denied-inactive.png differ
diff --git a/themes/greydragon_old/images/ico-denied-passive.png b/themes/greydragon_old/images/ico-denied-passive.png
new file mode 100644
index 0000000..1e99223
Binary files /dev/null and b/themes/greydragon_old/images/ico-denied-passive.png differ
diff --git a/themes/greydragon_old/images/ico-denied.png b/themes/greydragon_old/images/ico-denied.png
new file mode 100644
index 0000000..08f2493
Binary files /dev/null and b/themes/greydragon_old/images/ico-denied.png differ
diff --git a/themes/greydragon_old/images/ico-error.png b/themes/greydragon_old/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/greydragon_old/images/ico-error.png differ
diff --git a/themes/greydragon_old/images/ico-help.png b/themes/greydragon_old/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/greydragon_old/images/ico-help.png differ
diff --git a/themes/greydragon_old/images/ico-info.png b/themes/greydragon_old/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/greydragon_old/images/ico-info.png differ
diff --git a/themes/greydragon_old/images/ico-lock.png b/themes/greydragon_old/images/ico-lock.png
new file mode 100644
index 0000000..2ebc4f6
Binary files /dev/null and b/themes/greydragon_old/images/ico-lock.png differ
diff --git a/themes/greydragon_old/images/ico-success-inactive.png b/themes/greydragon_old/images/ico-success-inactive.png
new file mode 100644
index 0000000..a209fb6
Binary files /dev/null and b/themes/greydragon_old/images/ico-success-inactive.png differ
diff --git a/themes/greydragon_old/images/ico-success-passive.png b/themes/greydragon_old/images/ico-success-passive.png
new file mode 100644
index 0000000..c8460d1
Binary files /dev/null and b/themes/greydragon_old/images/ico-success-passive.png differ
diff --git a/themes/greydragon_old/images/ico-success.png b/themes/greydragon_old/images/ico-success.png
new file mode 100644
index 0000000..a9925a0
Binary files /dev/null and b/themes/greydragon_old/images/ico-success.png differ
diff --git a/themes/greydragon_old/images/ico-warning.png b/themes/greydragon_old/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/greydragon_old/images/ico-warning.png differ
diff --git a/themes/greydragon_old/images/missing-img.png b/themes/greydragon_old/images/missing-img.png
new file mode 100644
index 0000000..12b7394
Binary files /dev/null and b/themes/greydragon_old/images/missing-img.png differ
diff --git a/themes/greydragon_old/js/jquery.cycle.js b/themes/greydragon_old/js/jquery.cycle.js
new file mode 100644
index 0000000..caef8ea
--- /dev/null
+++ b/themes/greydragon_old/js/jquery.cycle.js
@@ -0,0 +1,1544 @@
+/*!
+ * jQuery Cycle Plugin (with Transition Definitions)
+ * Examples and documentation at: http://jquery.malsup.com/cycle/
+ * Copyright (c) 2007-2010 M. Alsup
+ * Version: 2.9999.4 (29-MAR-2012)
+ * Dual licensed under the MIT and GPL licenses.
+ * http://jquery.malsup.com/license.html
+ * Requires: jQuery v1.3.2 or later
+ */
+;(function($, undefined) {
+"use strict";
+
+var ver = '2.9999.4';
+
+// if $.support is not defined (pre jQuery 1.3) add what I need
+if ($.support === undefined) {
+	$.support = {
+		opacity: !($.browser.msie)
+	};
+}
+
+function debug(s) {
+	if ($.fn.cycle.debug)
+		log(s);
+}		
+function log() {
+	if (window.console && console.log)
+		console.log('[cycle] ' + Array.prototype.join.call(arguments,' '));
+}
+$.expr[':'].paused = function(el) {
+	return el.cyclePause;
+};
+
+
+// the options arg can be...
+//   a number  - indicates an immediate transition should occur to the given slide index
+//   a string  - 'pause', 'resume', 'toggle', 'next', 'prev', 'stop', 'destroy' or the name of a transition effect (ie, 'fade', 'zoom', etc)
+//   an object - properties to control the slideshow
+//
+// the arg2 arg can be...
+//   the name of an fx (only used in conjunction with a numeric value for 'options')
+//   the value true (only used in first arg == 'resume') and indicates
+//	 that the resume should occur immediately (not wait for next timeout)
+
+$.fn.cycle = function(options, arg2) {
+	var o = { s: this.selector, c: this.context };
+
+	// in 1.3+ we can fix mistakes with the ready state
+	if (this.length === 0 && options != 'stop') {
+		if (!$.isReady && o.s) {
+			log('DOM not ready, queuing slideshow');
+			$(function() {
+				$(o.s,o.c).cycle(options,arg2);
+			});
+			return this;
+		}
+		// is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
+		log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
+		return this;
+	}
+
+	// iterate the matched nodeset
+	return this.each(function() {
+		var opts = handleArguments(this, options, arg2);
+		if (opts === false)
+			return;
+
+		opts.updateActivePagerLink = opts.updateActivePagerLink || $.fn.cycle.updateActivePagerLink;
+		
+		// stop existing slideshow for this container (if there is one)
+		if (this.cycleTimeout)
+			clearTimeout(this.cycleTimeout);
+		this.cycleTimeout = this.cyclePause = 0;
+
+		var $cont = $(this);
+		var $slides = opts.slideExpr ? $(opts.slideExpr, this) : $cont.children();
+		var els = $slides.get();
+
+		if (els.length < 2) {
+			log('terminating; too few slides: ' + els.length);
+			return;
+		}
+
+		var opts2 = buildOptions($cont, $slides, els, opts, o);
+		if (opts2 === false)
+			return;
+
+		var startTime = opts2.continuous ? 10 : getTimeout(els[opts2.currSlide], els[opts2.nextSlide], opts2, !opts2.backwards);
+
+		// if it's an auto slideshow, kick it off
+		if (startTime) {
+			startTime += (opts2.delay || 0);
+			if (startTime < 10)
+				startTime = 10;
+			debug('first timeout: ' + startTime);
+			this.cycleTimeout = setTimeout(function(){go(els,opts2,0,!opts.backwards);}, startTime);
+		}
+	});
+};
+
+function triggerPause(cont, byHover, onPager) {
+	var opts = $(cont).data('cycle.opts');
+	var paused = !!cont.cyclePause;
+	if (paused && opts.paused)
+		opts.paused(cont, opts, byHover, onPager);
+	else if (!paused && opts.resumed)
+		opts.resumed(cont, opts, byHover, onPager);
+}
+
+// process the args that were passed to the plugin fn
+function handleArguments(cont, options, arg2) {
+	if (cont.cycleStop === undefined)
+		cont.cycleStop = 0;
+	if (options === undefined || options === null)
+		options = {};
+	if (options.constructor == String) {
+		switch(options) {
+		case 'destroy':
+		case 'stop':
+			var opts = $(cont).data('cycle.opts');
+			if (!opts)
+				return false;
+			cont.cycleStop++; // callbacks look for change
+			if (cont.cycleTimeout)
+				clearTimeout(cont.cycleTimeout);
+			cont.cycleTimeout = 0;
+			if (opts.elements)
+				$(opts.elements).stop();
+			$(cont).removeData('cycle.opts');
+			if (options == 'destroy')
+				destroy(cont, opts);
+			return false;
+		case 'toggle':
+			cont.cyclePause = (cont.cyclePause === 1) ? 0 : 1;
+			checkInstantResume(cont.cyclePause, arg2, cont);
+			triggerPause(cont);
+			return false;
+		case 'pause':
+			cont.cyclePause = 1;
+			triggerPause(cont);
+			return false;
+		case 'resume':
+			cont.cyclePause = 0;
+			checkInstantResume(false, arg2, cont);
+			triggerPause(cont);
+			return false;
+		case 'prev':
+		case 'next':
+			opts = $(cont).data('cycle.opts');
+			if (!opts) {
+				log('options not found, "prev/next" ignored');
+				return false;
+			}
+			$.fn.cycle[options](opts);
+			return false;
+		default:
+			options = { fx: options };
+		}
+		return options;
+	}
+	else if (options.constructor == Number) {
+		// go to the requested slide
+		var num = options;
+		options = $(cont).data('cycle.opts');
+		if (!options) {
+			log('options not found, can not advance slide');
+			return false;
+		}
+		if (num < 0 || num >= options.elements.length) {
+			log('invalid slide index: ' + num);
+			return false;
+		}
+		options.nextSlide = num;
+		if (cont.cycleTimeout) {
+			clearTimeout(cont.cycleTimeout);
+			cont.cycleTimeout = 0;
+		}
+		if (typeof arg2 == 'string')
+			options.oneTimeFx = arg2;
+		go(options.elements, options, 1, num >= options.currSlide);
+		return false;
+	}
+	return options;
+	
+	function checkInstantResume(isPaused, arg2, cont) {
+		if (!isPaused && arg2 === true) { // resume now!
+			var options = $(cont).data('cycle.opts');
+			if (!options) {
+				log('options not found, can not resume');
+				return false;
+			}
+			if (cont.cycleTimeout) {
+				clearTimeout(cont.cycleTimeout);
+				cont.cycleTimeout = 0;
+			}
+			go(options.elements, options, 1, !options.backwards);
+		}
+	}
+}
+
+function removeFilter(el, opts) {
+	if (!$.support.opacity && opts.cleartype && el.style.filter) {
+		try { el.style.removeAttribute('filter'); }
+		catch(smother) {} // handle old opera versions
+	}
+}
+
+// unbind event handlers
+function destroy(cont, opts) {
+	if (opts.next)
+		$(opts.next).unbind(opts.prevNextEvent);
+	if (opts.prev)
+		$(opts.prev).unbind(opts.prevNextEvent);
+	
+	if (opts.pager || opts.pagerAnchorBuilder)
+		$.each(opts.pagerAnchors || [], function() {
+			this.unbind().remove();
+		});
+	opts.pagerAnchors = null;
+	$(cont).unbind('mouseenter.cycle mouseleave.cycle');
+	if (opts.destroy) // callback
+		opts.destroy(opts);
+}
+
+// one-time initialization
+function buildOptions($cont, $slides, els, options, o) {
+	var startingSlideSpecified;
+	// support metadata plugin (v1.0 and v2.0)
+	var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});
+	var meta = $.isFunction($cont.data) ? $cont.data(opts.metaAttr) : null;
+	if (meta)
+		opts = $.extend(opts, meta);
+	if (opts.autostop)
+		opts.countdown = opts.autostopCount || els.length;
+
+	var cont = $cont[0];
+	$cont.data('cycle.opts', opts);
+	opts.$cont = $cont;
+	opts.stopCount = cont.cycleStop;
+	opts.elements = els;
+	opts.before = opts.before ? [opts.before] : [];
+	opts.after = opts.after ? [opts.after] : [];
+
+	// push some after callbacks
+	if (!$.support.opacity && opts.cleartype)
+		opts.after.push(function() { removeFilter(this, opts); });
+	if (opts.continuous)
+		opts.after.push(function() { go(els,opts,0,!opts.backwards); });
+
+	saveOriginalOpts(opts);
+
+	// clearType corrections
+	if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
+		clearTypeFix($slides);
+
+	// container requires non-static position so that slides can be position within
+	if ($cont.css('position') == 'static')
+		$cont.css('position', 'relative');
+	if (opts.width)
+		$cont.width(opts.width);
+	if (opts.height && opts.height != 'auto')
+		$cont.height(opts.height);
+
+	if (opts.startingSlide !== undefined) {
+		opts.startingSlide = parseInt(opts.startingSlide,10);
+		if (opts.startingSlide >= els.length || opts.startSlide < 0)
+			opts.startingSlide = 0; // catch bogus input
+		else 
+			startingSlideSpecified = true;
+	}
+	else if (opts.backwards)
+		opts.startingSlide = els.length - 1;
+	else
+		opts.startingSlide = 0;
+
+	// if random, mix up the slide array
+	if (opts.random) {
+		opts.randomMap = [];
+		for (var i = 0; i < els.length; i++)
+			opts.randomMap.push(i);
+		opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+		if (startingSlideSpecified) {
+			// try to find the specified starting slide and if found set start slide index in the map accordingly
+			for ( var cnt = 0; cnt < els.length; cnt++ ) {
+				if ( opts.startingSlide == opts.randomMap[cnt] ) {
+					opts.randomIndex = cnt;
+				}
+			}
+		}
+		else {
+			opts.randomIndex = 1;
+			opts.startingSlide = opts.randomMap[1];
+		}
+	}
+	else if (opts.startingSlide >= els.length)
+		opts.startingSlide = 0; // catch bogus input
+	opts.currSlide = opts.startingSlide || 0;
+	var first = opts.startingSlide;
+
+	// set position and zIndex on all the slides
+	$slides.css({position: 'absolute', top:0, left:0}).hide().each(function(i) {
+		var z;
+		if (opts.backwards)
+			z = first ? i <= first ? els.length + (i-first) : first-i : els.length-i;
+		else
+			z = first ? i >= first ? els.length - (i-first) : first-i : els.length-i;
+		$(this).css('z-index', z);
+	});
+
+	// make sure first slide is visible
+	$(els[first]).css('opacity',1).show(); // opacity bit needed to handle restart use case
+	removeFilter(els[first], opts);
+
+	// stretch slides
+	if (opts.fit) {
+		if (!opts.aspect) {
+	        if (opts.width)
+	            $slides.width(opts.width);
+	        if (opts.height && opts.height != 'auto')
+	            $slides.height(opts.height);
+		} else {
+			$slides.each(function(){
+				var $slide = $(this);
+				var ratio = (opts.aspect === true) ? $slide.width()/$slide.height() : opts.aspect;
+				if( opts.width && $slide.width() != opts.width ) {
+					$slide.width( opts.width );
+					$slide.height( opts.width / ratio );
+				}
+
+				if( opts.height && $slide.height() < opts.height ) {
+					$slide.height( opts.height );
+					$slide.width( opts.height * ratio );
+				}
+			});
+		}
+	}
+
+	if (opts.center && ((!opts.fit) || opts.aspect)) {
+		$slides.each(function(){
+			var $slide = $(this);
+			$slide.css({
+				"margin-left": opts.width ?
+					((opts.width - $slide.width()) / 2) + "px" :
+					0,
+				"margin-top": opts.height ?
+					((opts.height - $slide.height()) / 2) + "px" :
+					0
+			});
+		});
+	}
+
+	if (opts.center && !opts.fit && !opts.slideResize) {
+		$slides.each(function(){
+			var $slide = $(this);
+			$slide.css({
+				"margin-left": opts.width ? ((opts.width - $slide.width()) / 2) + "px" : 0,
+				"margin-top": opts.height ? ((opts.height - $slide.height()) / 2) + "px" : 0
+			});
+		});
+	}
+		
+	// stretch container
+	var reshape = opts.containerResize && !$cont.innerHeight();
+	if (reshape) { // do this only if container has no size http://tinyurl.com/da2oa9
+		var maxw = 0, maxh = 0;
+		for(var j=0; j < els.length; j++) {
+			var $e = $(els[j]), e = $e[0], w = $e.outerWidth(), h = $e.outerHeight();
+			if (!w) w = e.offsetWidth || e.width || $e.attr('width');
+			if (!h) h = e.offsetHeight || e.height || $e.attr('height');
+			maxw = w > maxw ? w : maxw;
+			maxh = h > maxh ? h : maxh;
+		}
+		if (maxw > 0 && maxh > 0)
+			$cont.css({width:maxw+'px',height:maxh+'px'});
+	}
+
+	var pauseFlag = false;  // https://github.com/malsup/cycle/issues/44
+	if (opts.pause)
+		$cont.bind('mouseenter.cycle', function(){
+			pauseFlag = true;
+			this.cyclePause++;
+			triggerPause(cont, true);
+		}).bind('mouseleave.cycle', function(){
+				if (pauseFlag)
+					this.cyclePause--;
+				triggerPause(cont, true);
+		});
+
+	if (supportMultiTransitions(opts) === false)
+		return false;
+
+	// apparently a lot of people use image slideshows without height/width attributes on the images.
+	// Cycle 2.50+ requires the sizing info for every slide; this block tries to deal with that.
+	var requeue = false;
+	options.requeueAttempts = options.requeueAttempts || 0;
+	$slides.each(function() {
+		// try to get height/width of each slide
+		var $el = $(this);
+		this.cycleH = (opts.fit && opts.height) ? opts.height : ($el.height() || this.offsetHeight || this.height || $el.attr('height') || 0);
+		this.cycleW = (opts.fit && opts.width) ? opts.width : ($el.width() || this.offsetWidth || this.width || $el.attr('width') || 0);
+
+		if ( $el.is('img') ) {
+			// sigh..  sniffing, hacking, shrugging...  this crappy hack tries to account for what browsers do when
+			// an image is being downloaded and the markup did not include sizing info (height/width attributes);
+			// there seems to be some "default" sizes used in this situation
+			var loadingIE	= ($.browser.msie  && this.cycleW == 28 && this.cycleH == 30 && !this.complete);
+			var loadingFF	= ($.browser.mozilla && this.cycleW == 34 && this.cycleH == 19 && !this.complete);
+			var loadingOp	= ($.browser.opera && ((this.cycleW == 42 && this.cycleH == 19) || (this.cycleW == 37 && this.cycleH == 17)) && !this.complete);
+			var loadingOther = (this.cycleH === 0 && this.cycleW === 0 && !this.complete);
+			// don't requeue for images that are still loading but have a valid size
+			if (loadingIE || loadingFF || loadingOp || loadingOther) {
+				if (o.s && opts.requeueOnImageNotLoaded && ++options.requeueAttempts < 100) { // track retry count so we don't loop forever
+					log(options.requeueAttempts,' - img slide not loaded, requeuing slideshow: ', this.src, this.cycleW, this.cycleH);
+					setTimeout(function() {$(o.s,o.c).cycle(options);}, opts.requeueTimeout);
+					requeue = true;
+					return false; // break each loop
+				}
+				else {
+					log('could not determine size of image: '+this.src, this.cycleW, this.cycleH);
+				}
+			}
+		}
+		return true;
+	});
+
+	if (requeue)
+		return false;
+
+	opts.cssBefore = opts.cssBefore || {};
+	opts.cssAfter = opts.cssAfter || {};
+	opts.cssFirst = opts.cssFirst || {};
+	opts.animIn = opts.animIn || {};
+	opts.animOut = opts.animOut || {};
+
+	$slides.not(':eq('+first+')').css(opts.cssBefore);
+	$($slides[first]).css(opts.cssFirst);
+
+	if (opts.timeout) {
+		opts.timeout = parseInt(opts.timeout,10);
+		// ensure that timeout and speed settings are sane
+		if (opts.speed.constructor == String)
+			opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed,10);
+		if (!opts.sync)
+			opts.speed = opts.speed / 2;
+		
+		var buffer = opts.fx == 'none' ? 0 : opts.fx == 'shuffle' ? 500 : 250;
+		while((opts.timeout - opts.speed) < buffer) // sanitize timeout
+			opts.timeout += opts.speed;
+	}
+	if (opts.easing)
+		opts.easeIn = opts.easeOut = opts.easing;
+	if (!opts.speedIn)
+		opts.speedIn = opts.speed;
+	if (!opts.speedOut)
+		opts.speedOut = opts.speed;
+
+	opts.slideCount = els.length;
+	opts.currSlide = opts.lastSlide = first;
+	if (opts.random) {
+		if (++opts.randomIndex == els.length)
+			opts.randomIndex = 0;
+		opts.nextSlide = opts.randomMap[opts.randomIndex];
+	}
+	else if (opts.backwards)
+		opts.nextSlide = opts.startingSlide === 0 ? (els.length-1) : opts.startingSlide-1;
+	else
+		opts.nextSlide = opts.startingSlide >= (els.length-1) ? 0 : opts.startingSlide+1;
+
+	// run transition init fn
+	if (!opts.multiFx) {
+		var init = $.fn.cycle.transitions[opts.fx];
+		if ($.isFunction(init))
+			init($cont, $slides, opts);
+		else if (opts.fx != 'custom' && !opts.multiFx) {
+			log('unknown transition: ' + opts.fx,'; slideshow terminating');
+			return false;
+		}
+	}
+
+	// fire artificial events
+	var e0 = $slides[first];
+	if (!opts.skipInitializationCallbacks) {
+		if (opts.before.length)
+			opts.before[0].apply(e0, [e0, e0, opts, true]);
+		if (opts.after.length)
+			opts.after[0].apply(e0, [e0, e0, opts, true]);
+	}
+	if (opts.next)
+		$(opts.next).bind(opts.prevNextEvent,function(){return advance(opts,1);});
+	if (opts.prev)
+		$(opts.prev).bind(opts.prevNextEvent,function(){return advance(opts,0);});
+	if (opts.pager || opts.pagerAnchorBuilder)
+		buildPager(els,opts);
+
+	exposeAddSlide(opts, els);
+
+	return opts;
+}
+
+// save off original opts so we can restore after clearing state
+function saveOriginalOpts(opts) {
+	opts.original = { before: [], after: [] };
+	opts.original.cssBefore = $.extend({}, opts.cssBefore);
+	opts.original.cssAfter  = $.extend({}, opts.cssAfter);
+	opts.original.animIn	= $.extend({}, opts.animIn);
+	opts.original.animOut   = $.extend({}, opts.animOut);
+	$.each(opts.before, function() { opts.original.before.push(this); });
+	$.each(opts.after,  function() { opts.original.after.push(this); });
+}
+
+function supportMultiTransitions(opts) {
+	var i, tx, txs = $.fn.cycle.transitions;
+	// look for multiple effects
+	if (opts.fx.indexOf(',') > 0) {
+		opts.multiFx = true;
+		opts.fxs = opts.fx.replace(/\s*/g,'').split(',');
+		// discard any bogus effect names
+		for (i=0; i < opts.fxs.length; i++) {
+			var fx = opts.fxs[i];
+			tx = txs[fx];
+			if (!tx || !txs.hasOwnProperty(fx) || !$.isFunction(tx)) {
+				log('discarding unknown transition: ',fx);
+				opts.fxs.splice(i,1);
+				i--;
+			}
+		}
+		// if we have an empty list then we threw everything away!
+		if (!opts.fxs.length) {
+			log('No valid transitions named; slideshow terminating.');
+			return false;
+		}
+	}
+	else if (opts.fx == 'all') {  // auto-gen the list of transitions
+		opts.multiFx = true;
+		opts.fxs = [];
+		for (var p in txs) {
+			if (txs.hasOwnProperty(p)) {
+				tx = txs[p];
+				if (txs.hasOwnProperty(p) && $.isFunction(tx))
+					opts.fxs.push(p);
+			}
+		}
+	}
+	if (opts.multiFx && opts.randomizeEffects) {
+		// munge the fxs array to make effect selection random
+		var r1 = Math.floor(Math.random() * 20) + 30;
+		for (i = 0; i < r1; i++) {
+			var r2 = Math.floor(Math.random() * opts.fxs.length);
+			opts.fxs.push(opts.fxs.splice(r2,1)[0]);
+		}
+		debug('randomized fx sequence: ',opts.fxs);
+	}
+	return true;
+}
+
+// provide a mechanism for adding slides after the slideshow has started
+function exposeAddSlide(opts, els) {
+	opts.addSlide = function(newSlide, prepend) {
+		var $s = $(newSlide), s = $s[0];
+		if (!opts.autostopCount)
+			opts.countdown++;
+		els[prepend?'unshift':'push'](s);
+		if (opts.els)
+			opts.els[prepend?'unshift':'push'](s); // shuffle needs this
+		opts.slideCount = els.length;
+
+		// add the slide to the random map and resort
+		if (opts.random) {
+			opts.randomMap.push(opts.slideCount-1);
+			opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+		}
+
+		$s.css('position','absolute');
+		$s[prepend?'prependTo':'appendTo'](opts.$cont);
+
+		if (prepend) {
+			opts.currSlide++;
+			opts.nextSlide++;
+		}
+
+		if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
+			clearTypeFix($s);
+
+		if (opts.fit && opts.width)
+			$s.width(opts.width);
+		if (opts.fit && opts.height && opts.height != 'auto')
+			$s.height(opts.height);
+		s.cycleH = (opts.fit && opts.height) ? opts.height : $s.height();
+		s.cycleW = (opts.fit && opts.width) ? opts.width : $s.width();
+
+		$s.css(opts.cssBefore);
+
+		if (opts.pager || opts.pagerAnchorBuilder)
+			$.fn.cycle.createPagerAnchor(els.length-1, s, $(opts.pager), els, opts);
+
+		if ($.isFunction(opts.onAddSlide))
+			opts.onAddSlide($s);
+		else
+			$s.hide(); // default behavior
+	};
+}
+
+// reset internal state; we do this on every pass in order to support multiple effects
+$.fn.cycle.resetState = function(opts, fx) {
+	fx = fx || opts.fx;
+	opts.before = []; opts.after = [];
+	opts.cssBefore = $.extend({}, opts.original.cssBefore);
+	opts.cssAfter  = $.extend({}, opts.original.cssAfter);
+	opts.animIn	= $.extend({}, opts.original.animIn);
+	opts.animOut   = $.extend({}, opts.original.animOut);
+	opts.fxFn = null;
+	$.each(opts.original.before, function() { opts.before.push(this); });
+	$.each(opts.original.after,  function() { opts.after.push(this); });
+
+	// re-init
+	var init = $.fn.cycle.transitions[fx];
+	if ($.isFunction(init))
+		init(opts.$cont, $(opts.elements), opts);
+};
+
+// this is the main engine fn, it handles the timeouts, callbacks and slide index mgmt
+function go(els, opts, manual, fwd) {
+	var p = opts.$cont[0], curr = els[opts.currSlide], next = els[opts.nextSlide];
+
+	// opts.busy is true if we're in the middle of an animation
+	if (manual && opts.busy && opts.manualTrump) {
+		// let manual transitions requests trump active ones
+		debug('manualTrump in go(), stopping active transition');
+		$(els).stop(true,true);
+		opts.busy = 0;
+		clearTimeout(p.cycleTimeout);
+	}
+
+	// don't begin another timeout-based transition if there is one active
+	if (opts.busy) {
+		debug('transition active, ignoring new tx request');
+		return;
+	}
+
+
+	// stop cycling if we have an outstanding stop request
+	if (p.cycleStop != opts.stopCount || p.cycleTimeout === 0 && !manual)
+		return;
+
+	// check to see if we should stop cycling based on autostop options
+	if (!manual && !p.cyclePause && !opts.bounce &&
+		((opts.autostop && (--opts.countdown <= 0)) ||
+		(opts.nowrap && !opts.random && opts.nextSlide < opts.currSlide))) {
+		if (opts.end)
+			opts.end(opts);
+		return;
+	}
+
+	// if slideshow is paused, only transition on a manual trigger
+	var changed = false;
+	if ((manual || !p.cyclePause) && (opts.nextSlide != opts.currSlide)) {
+		changed = true;
+		var fx = opts.fx;
+		// keep trying to get the slide size if we don't have it yet
+		curr.cycleH = curr.cycleH || $(curr).height();
+		curr.cycleW = curr.cycleW || $(curr).width();
+		next.cycleH = next.cycleH || $(next).height();
+		next.cycleW = next.cycleW || $(next).width();
+
+		// support multiple transition types
+		if (opts.multiFx) {
+			if (fwd && (opts.lastFx === undefined || ++opts.lastFx >= opts.fxs.length))
+				opts.lastFx = 0;
+			else if (!fwd && (opts.lastFx === undefined || --opts.lastFx < 0))
+				opts.lastFx = opts.fxs.length - 1;
+			fx = opts.fxs[opts.lastFx];
+		}
+
+		// one-time fx overrides apply to:  $('div').cycle(3,'zoom');
+		if (opts.oneTimeFx) {
+			fx = opts.oneTimeFx;
+			opts.oneTimeFx = null;
+		}
+
+		$.fn.cycle.resetState(opts, fx);
+
+		// run the before callbacks
+		if (opts.before.length)
+			$.each(opts.before, function(i,o) {
+				if (p.cycleStop != opts.stopCount) return;
+				o.apply(next, [curr, next, opts, fwd]);
+			});
+
+		// stage the after callacks
+		var after = function() {
+			opts.busy = 0;
+			$.each(opts.after, function(i,o) {
+				if (p.cycleStop != opts.stopCount) return;
+				o.apply(next, [curr, next, opts, fwd]);
+			});
+			if (!p.cycleStop) {
+				// queue next transition
+				queueNext();
+			}
+		};
+
+		debug('tx firing('+fx+'); currSlide: ' + opts.currSlide + '; nextSlide: ' + opts.nextSlide);
+		
+		// get ready to perform the transition
+		opts.busy = 1;
+		if (opts.fxFn) // fx function provided?
+			opts.fxFn(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+		else if ($.isFunction($.fn.cycle[opts.fx])) // fx plugin ?
+			$.fn.cycle[opts.fx](curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+		else
+			$.fn.cycle.custom(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+	}
+	else {
+		queueNext();
+	}
+
+	if (changed || opts.nextSlide == opts.currSlide) {
+		// calculate the next slide
+		var roll;
+		opts.lastSlide = opts.currSlide;
+		if (opts.random) {
+			opts.currSlide = opts.nextSlide;
+			if (++opts.randomIndex == els.length) {
+				opts.randomIndex = 0;
+				opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+			}
+			opts.nextSlide = opts.randomMap[opts.randomIndex];
+			if (opts.nextSlide == opts.currSlide)
+				opts.nextSlide = (opts.currSlide == opts.slideCount - 1) ? 0 : opts.currSlide + 1;
+		}
+		else if (opts.backwards) {
+			roll = (opts.nextSlide - 1) < 0;
+			if (roll && opts.bounce) {
+				opts.backwards = !opts.backwards;
+				opts.nextSlide = 1;
+				opts.currSlide = 0;
+			}
+			else {
+				opts.nextSlide = roll ? (els.length-1) : opts.nextSlide-1;
+				opts.currSlide = roll ? 0 : opts.nextSlide+1;
+			}
+		}
+		else { // sequence
+			roll = (opts.nextSlide + 1) == els.length;
+			if (roll && opts.bounce) {
+				opts.backwards = !opts.backwards;
+				opts.nextSlide = els.length-2;
+				opts.currSlide = els.length-1;
+			}
+			else {
+				opts.nextSlide = roll ? 0 : opts.nextSlide+1;
+				opts.currSlide = roll ? els.length-1 : opts.nextSlide-1;
+			}
+		}
+	}
+	if (changed && opts.pager)
+		opts.updateActivePagerLink(opts.pager, opts.currSlide, opts.activePagerClass);
+	
+	function queueNext() {
+		// stage the next transition
+		var ms = 0, timeout = opts.timeout;
+		if (opts.timeout && !opts.continuous) {
+			ms = getTimeout(els[opts.currSlide], els[opts.nextSlide], opts, fwd);
+         if (opts.fx == 'shuffle')
+            ms -= opts.speedOut;
+      }
+		else if (opts.continuous && p.cyclePause) // continuous shows work off an after callback, not this timer logic
+			ms = 10;
+		if (ms > 0)
+			p.cycleTimeout = setTimeout(function(){ go(els, opts, 0, !opts.backwards); }, ms);
+	}
+}
+
+// invoked after transition
+$.fn.cycle.updateActivePagerLink = function(pager, currSlide, clsName) {
+   $(pager).each(function() {
+       $(this).children().removeClass(clsName).eq(currSlide).addClass(clsName);
+   });
+};
+
+// calculate timeout value for current transition
+function getTimeout(curr, next, opts, fwd) {
+	if (opts.timeoutFn) {
+		// call user provided calc fn
+		var t = opts.timeoutFn.call(curr,curr,next,opts,fwd);
+		while (opts.fx != 'none' && (t - opts.speed) < 250) // sanitize timeout
+			t += opts.speed;
+		debug('calculated timeout: ' + t + '; speed: ' + opts.speed);
+		if (t !== false)
+			return t;
+	}
+	return opts.timeout;
+}
+
+// expose next/prev function, caller must pass in state
+$.fn.cycle.next = function(opts) { advance(opts,1); };
+$.fn.cycle.prev = function(opts) { advance(opts,0);};
+
+// advance slide forward or back
+function advance(opts, moveForward) {
+	var val = moveForward ? 1 : -1;
+	var els = opts.elements;
+	var p = opts.$cont[0], timeout = p.cycleTimeout;
+	if (timeout) {
+		clearTimeout(timeout);
+		p.cycleTimeout = 0;
+	}
+	if (opts.random && val < 0) {
+		// move back to the previously display slide
+		opts.randomIndex--;
+		if (--opts.randomIndex == -2)
+			opts.randomIndex = els.length-2;
+		else if (opts.randomIndex == -1)
+			opts.randomIndex = els.length-1;
+		opts.nextSlide = opts.randomMap[opts.randomIndex];
+	}
+	else if (opts.random) {
+		opts.nextSlide = opts.randomMap[opts.randomIndex];
+	}
+	else {
+		opts.nextSlide = opts.currSlide + val;
+		if (opts.nextSlide < 0) {
+			if (opts.nowrap) return false;
+			opts.nextSlide = els.length - 1;
+		}
+		else if (opts.nextSlide >= els.length) {
+			if (opts.nowrap) return false;
+			opts.nextSlide = 0;
+		}
+	}
+
+	var cb = opts.onPrevNextEvent || opts.prevNextClick; // prevNextClick is deprecated
+	if ($.isFunction(cb))
+		cb(val > 0, opts.nextSlide, els[opts.nextSlide]);
+	go(els, opts, 1, moveForward);
+	return false;
+}
+
+function buildPager(els, opts) {
+	var $p = $(opts.pager);
+	$.each(els, function(i,o) {
+		$.fn.cycle.createPagerAnchor(i,o,$p,els,opts);
+	});
+	opts.updateActivePagerLink(opts.pager, opts.startingSlide, opts.activePagerClass);
+}
+
+$.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
+	var a;
+	if ($.isFunction(opts.pagerAnchorBuilder)) {
+		a = opts.pagerAnchorBuilder(i,el);
+		debug('pagerAnchorBuilder('+i+', el) returned: ' + a);
+	}
+	else
+		a = '<a href="#">'+(i+1)+'</a>';
+		
+	if (!a)
+		return;
+	var $a = $(a);
+	// don't reparent if anchor is in the dom
+	if ($a.parents('body').length === 0) {
+		var arr = [];
+		if ($p.length > 1) {
+			$p.each(function() {
+				var $clone = $a.clone(true);
+				$(this).append($clone);
+				arr.push($clone[0]);
+			});
+			$a = $(arr);
+		}
+		else {
+			$a.appendTo($p);
+		}
+	}
+
+	opts.pagerAnchors =  opts.pagerAnchors || [];
+	opts.pagerAnchors.push($a);
+	
+	var pagerFn = function(e) {
+		e.preventDefault();
+		opts.nextSlide = i;
+		var p = opts.$cont[0], timeout = p.cycleTimeout;
+		if (timeout) {
+			clearTimeout(timeout);
+			p.cycleTimeout = 0;
+		}
+		var cb = opts.onPagerEvent || opts.pagerClick; // pagerClick is deprecated
+		if ($.isFunction(cb))
+			cb(opts.nextSlide, els[opts.nextSlide]);
+		go(els,opts,1,opts.currSlide < i); // trigger the trans
+//		return false; // <== allow bubble
+	};
+	
+	if ( /mouseenter|mouseover/i.test(opts.pagerEvent) ) {
+		$a.hover(pagerFn, function(){/* no-op */} );
+	}
+	else {
+		$a.bind(opts.pagerEvent, pagerFn);
+	}
+	
+	if ( ! /^click/.test(opts.pagerEvent) && !opts.allowPagerClickBubble)
+		$a.bind('click.cycle', function(){return false;}); // suppress click
+	
+	var cont = opts.$cont[0];
+	var pauseFlag = false; // https://github.com/malsup/cycle/issues/44
+	if (opts.pauseOnPagerHover) {
+		$a.hover(
+			function() { 
+				pauseFlag = true;
+				cont.cyclePause++; 
+				triggerPause(cont,true,true);
+			}, function() { 
+				if (pauseFlag)
+					cont.cyclePause--; 
+				triggerPause(cont,true,true);
+			} 
+		);
+	}
+};
+
+// helper fn to calculate the number of slides between the current and the next
+$.fn.cycle.hopsFromLast = function(opts, fwd) {
+	var hops, l = opts.lastSlide, c = opts.currSlide;
+	if (fwd)
+		hops = c > l ? c - l : opts.slideCount - l;
+	else
+		hops = c < l ? l - c : l + opts.slideCount - c;
+	return hops;
+};
+
+// fix clearType problems in ie6 by setting an explicit bg color
+// (otherwise text slides look horrible during a fade transition)
+function clearTypeFix($slides) {
+	debug('applying clearType background-color hack');
+	function hex(s) {
+		s = parseInt(s,10).toString(16);
+		return s.length < 2 ? '0'+s : s;
+	}
+	function getBg(e) {
+		for ( ; e && e.nodeName.toLowerCase() != 'html'; e = e.parentNode) {
+			var v = $.css(e,'background-color');
+			if (v && v.indexOf('rgb') >= 0 ) {
+				var rgb = v.match(/\d+/g);
+				return '#'+ hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
+			}
+			if (v && v != 'transparent')
+				return v;
+		}
+		return '#ffffff';
+	}
+	$slides.each(function() { $(this).css('background-color', getBg(this)); });
+}
+
+// reset common props before the next transition
+$.fn.cycle.commonReset = function(curr,next,opts,w,h,rev) {
+	$(opts.elements).not(curr).hide();
+	if (typeof opts.cssBefore.opacity == 'undefined')
+		opts.cssBefore.opacity = 1;
+	opts.cssBefore.display = 'block';
+	if (opts.slideResize && w !== false && next.cycleW > 0)
+		opts.cssBefore.width = next.cycleW;
+	if (opts.slideResize && h !== false && next.cycleH > 0)
+		opts.cssBefore.height = next.cycleH;
+	opts.cssAfter = opts.cssAfter || {};
+	opts.cssAfter.display = 'none';
+	$(curr).css('zIndex',opts.slideCount + (rev === true ? 1 : 0));
+	$(next).css('zIndex',opts.slideCount + (rev === true ? 0 : 1));
+};
+
+// the actual fn for effecting a transition
+$.fn.cycle.custom = function(curr, next, opts, cb, fwd, speedOverride) {
+	var $l = $(curr), $n = $(next);
+	var speedIn = opts.speedIn, speedOut = opts.speedOut, easeIn = opts.easeIn, easeOut = opts.easeOut;
+	$n.css(opts.cssBefore);
+	if (speedOverride) {
+		if (typeof speedOverride == 'number')
+			speedIn = speedOut = speedOverride;
+		else
+			speedIn = speedOut = 1;
+		easeIn = easeOut = null;
+	}
+	var fn = function() {
+		$n.animate(opts.animIn, speedIn, easeIn, function() {
+			cb();
+		});
+	};
+	$l.animate(opts.animOut, speedOut, easeOut, function() {
+		$l.css(opts.cssAfter);
+		if (!opts.sync) 
+			fn();
+	});
+	if (opts.sync) fn();
+};
+
+// transition definitions - only fade is defined here, transition pack defines the rest
+$.fn.cycle.transitions = {
+	fade: function($cont, $slides, opts) {
+		$slides.not(':eq('+opts.currSlide+')').css('opacity',0);
+		opts.before.push(function(curr,next,opts) {
+			$.fn.cycle.commonReset(curr,next,opts);
+			opts.cssBefore.opacity = 0;
+		});
+		opts.animIn	   = { opacity: 1 };
+		opts.animOut   = { opacity: 0 };
+		opts.cssBefore = { top: 0, left: 0 };
+	}
+};
+
+$.fn.cycle.ver = function() { return ver; };
+
+// override these globally if you like (they are all optional)
+$.fn.cycle.defaults = {
+    activePagerClass: 'activeSlide', // class name used for the active pager link
+    after:            null,     // transition callback (scope set to element that was shown):  function(currSlideElement, nextSlideElement, options, forwardFlag)
+    allowPagerClickBubble: false, // allows or prevents click event on pager anchors from bubbling
+    animIn:           null,     // properties that define how the slide animates in
+    animOut:          null,     // properties that define how the slide animates out
+    aspect:           false,    // preserve aspect ratio during fit resizing, cropping if necessary (must be used with fit option)
+    autostop:         0,        // true to end slideshow after X transitions (where X == slide count)
+    autostopCount:    0,        // number of transitions (optionally used with autostop to define X)
+    backwards:        false,    // true to start slideshow at last slide and move backwards through the stack
+    before:           null,     // transition callback (scope set to element to be shown):     function(currSlideElement, nextSlideElement, options, forwardFlag)
+    center:           null,     // set to true to have cycle add top/left margin to each slide (use with width and height options)
+    cleartype:        !$.support.opacity,  // true if clearType corrections should be applied (for IE)
+    cleartypeNoBg:    false,    // set to true to disable extra cleartype fixing (leave false to force background color setting on slides)
+    containerResize:  1,        // resize container to fit largest slide
+    continuous:       0,        // true to start next transition immediately after current one completes
+    cssAfter:         null,     // properties that defined the state of the slide after transitioning out
+    cssBefore:        null,     // properties that define the initial state of the slide before transitioning in
+    delay:            0,        // additional delay (in ms) for first transition (hint: can be negative)
+    easeIn:           null,     // easing for "in" transition
+    easeOut:          null,     // easing for "out" transition
+    easing:           null,     // easing method for both in and out transitions
+    end:              null,     // callback invoked when the slideshow terminates (use with autostop or nowrap options): function(options)
+    fastOnEvent:      0,        // force fast transitions when triggered manually (via pager or prev/next); value == time in ms
+    fit:              0,        // force slides to fit container
+    fx:               'fade',   // name of transition effect (or comma separated names, ex: 'fade,scrollUp,shuffle')
+    fxFn:             null,     // function used to control the transition: function(currSlideElement, nextSlideElement, options, afterCalback, forwardFlag)
+    height:           'auto',   // container height (if the 'fit' option is true, the slides will be set to this height as well)
+    manualTrump:      true,     // causes manual transition to stop an active transition instead of being ignored
+    metaAttr:         'cycle',  // data- attribute that holds the option data for the slideshow
+    next:             null,     // element, jQuery object, or jQuery selector string for the element to use as event trigger for next slide
+    nowrap:           0,        // true to prevent slideshow from wrapping
+    onPagerEvent:     null,     // callback fn for pager events: function(zeroBasedSlideIndex, slideElement)
+    onPrevNextEvent:  null,     // callback fn for prev/next events: function(isNext, zeroBasedSlideIndex, slideElement)
+    pager:            null,     // element, jQuery object, or jQuery selector string for the element to use as pager container
+    pagerAnchorBuilder: null,   // callback fn for building anchor links:  function(index, DOMelement)
+    pagerEvent:       'click.cycle', // name of event which drives the pager navigation
+    pause:            0,        // true to enable "pause on hover"
+    pauseOnPagerHover: 0,       // true to pause when hovering over pager link
+    prev:             null,     // element, jQuery object, or jQuery selector string for the element to use as event trigger for previous slide
+    prevNextEvent:    'click.cycle',// event which drives the manual transition to the previous or next slide
+    random:           0,        // true for random, false for sequence (not applicable to shuffle fx)
+    randomizeEffects: 1,        // valid when multiple effects are used; true to make the effect sequence random
+    requeueOnImageNotLoaded: true, // requeue the slideshow if any image slides are not yet loaded
+    requeueTimeout:   250,      // ms delay for requeue
+    rev:              0,        // causes animations to transition in reverse (for effects that support it such as scrollHorz/scrollVert/shuffle)
+    shuffle:          null,     // coords for shuffle animation, ex: { top:15, left: 200 }
+    skipInitializationCallbacks: false, // set to true to disable the first before/after callback that occurs prior to any transition
+    slideExpr:        null,     // expression for selecting slides (if something other than all children is required)
+    slideResize:      1,        // force slide width/height to fixed size before every transition
+    speed:            1000,     // speed of the transition (any valid fx speed value)
+    speedIn:          null,     // speed of the 'in' transition
+    speedOut:         null,     // speed of the 'out' transition
+    startingSlide:    undefined,// zero-based index of the first slide to be displayed
+    sync:             1,        // true if in/out transitions should occur simultaneously
+    timeout:          4000,     // milliseconds between slide transitions (0 to disable auto advance)
+    timeoutFn:        null,     // callback for determining per-slide timeout value:  function(currSlideElement, nextSlideElement, options, forwardFlag)
+    updateActivePagerLink: null,// callback fn invoked to update the active pager link (adds/removes activePagerClass style)
+    width:            null      // container width (if the 'fit' option is true, the slides will be set to this width as well)
+};
+
+})(jQuery);
+
+
+/*!
+ * jQuery Cycle Plugin Transition Definitions
+ * This script is a plugin for the jQuery Cycle Plugin
+ * Examples and documentation at: http://malsup.com/jquery/cycle/
+ * Copyright (c) 2007-2010 M. Alsup
+ * Version:	 2.73
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ */
+(function($) {
+"use strict";
+
+//
+// These functions define slide initialization and properties for the named
+// transitions. To save file size feel free to remove any of these that you
+// don't need.
+//
+$.fn.cycle.transitions.none = function($cont, $slides, opts) {
+	opts.fxFn = function(curr,next,opts,after){
+		$(next).show();
+		$(curr).hide();
+		after();
+	};
+};
+
+// not a cross-fade, fadeout only fades out the top slide
+$.fn.cycle.transitions.fadeout = function($cont, $slides, opts) {
+	$slides.not(':eq('+opts.currSlide+')').css({ display: 'block', 'opacity': 1 });
+	opts.before.push(function(curr,next,opts,w,h,rev) {
+		$(curr).css('zIndex',opts.slideCount + (rev !== true ? 1 : 0));
+		$(next).css('zIndex',opts.slideCount + (rev !== true ? 0 : 1));
+	});
+	opts.animIn.opacity = 1;
+	opts.animOut.opacity = 0;
+	opts.cssBefore.opacity = 1;
+	opts.cssBefore.display = 'block';
+	opts.cssAfter.zIndex = 0;
+};
+
+// scrollUp/Down/Left/Right
+$.fn.cycle.transitions.scrollUp = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden');
+	opts.before.push($.fn.cycle.commonReset);
+	var h = $cont.height();
+	opts.cssBefore.top = h;
+	opts.cssBefore.left = 0;
+	opts.cssFirst.top = 0;
+	opts.animIn.top = 0;
+	opts.animOut.top = -h;
+};
+$.fn.cycle.transitions.scrollDown = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden');
+	opts.before.push($.fn.cycle.commonReset);
+	var h = $cont.height();
+	opts.cssFirst.top = 0;
+	opts.cssBefore.top = -h;
+	opts.cssBefore.left = 0;
+	opts.animIn.top = 0;
+	opts.animOut.top = h;
+};
+$.fn.cycle.transitions.scrollLeft = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden');
+	opts.before.push($.fn.cycle.commonReset);
+	var w = $cont.width();
+	opts.cssFirst.left = 0;
+	opts.cssBefore.left = w;
+	opts.cssBefore.top = 0;
+	opts.animIn.left = 0;
+	opts.animOut.left = 0-w;
+};
+$.fn.cycle.transitions.scrollRight = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden');
+	opts.before.push($.fn.cycle.commonReset);
+	var w = $cont.width();
+	opts.cssFirst.left = 0;
+	opts.cssBefore.left = -w;
+	opts.cssBefore.top = 0;
+	opts.animIn.left = 0;
+	opts.animOut.left = w;
+};
+$.fn.cycle.transitions.scrollHorz = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden').width();
+	opts.before.push(function(curr, next, opts, fwd) {
+		if (opts.rev)
+			fwd = !fwd;
+		$.fn.cycle.commonReset(curr,next,opts);
+		opts.cssBefore.left = fwd ? (next.cycleW-1) : (1-next.cycleW);
+		opts.animOut.left = fwd ? -curr.cycleW : curr.cycleW;
+	});
+	opts.cssFirst.left = 0;
+	opts.cssBefore.top = 0;
+	opts.animIn.left = 0;
+	opts.animOut.top = 0;
+};
+$.fn.cycle.transitions.scrollVert = function($cont, $slides, opts) {
+	$cont.css('overflow','hidden');
+	opts.before.push(function(curr, next, opts, fwd) {
+		if (opts.rev)
+			fwd = !fwd;
+		$.fn.cycle.commonReset(curr,next,opts);
+		opts.cssBefore.top = fwd ? (1-next.cycleH) : (next.cycleH-1);
+		opts.animOut.top = fwd ? curr.cycleH : -curr.cycleH;
+	});
+	opts.cssFirst.top = 0;
+	opts.cssBefore.left = 0;
+	opts.animIn.top = 0;
+	opts.animOut.left = 0;
+};
+
+// slideX/slideY
+$.fn.cycle.transitions.slideX = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$(opts.elements).not(curr).hide();
+		$.fn.cycle.commonReset(curr,next,opts,false,true);
+		opts.animIn.width = next.cycleW;
+	});
+	opts.cssBefore.left = 0;
+	opts.cssBefore.top = 0;
+	opts.cssBefore.width = 0;
+	opts.animIn.width = 'show';
+	opts.animOut.width = 0;
+};
+$.fn.cycle.transitions.slideY = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$(opts.elements).not(curr).hide();
+		$.fn.cycle.commonReset(curr,next,opts,true,false);
+		opts.animIn.height = next.cycleH;
+	});
+	opts.cssBefore.left = 0;
+	opts.cssBefore.top = 0;
+	opts.cssBefore.height = 0;
+	opts.animIn.height = 'show';
+	opts.animOut.height = 0;
+};
+
+// shuffle
+$.fn.cycle.transitions.shuffle = function($cont, $slides, opts) {
+	var i, w = $cont.css('overflow', 'visible').width();
+	$slides.css({left: 0, top: 0});
+	opts.before.push(function(curr,next,opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,true,true);
+	});
+	// only adjust speed once!
+	if (!opts.speedAdjusted) {
+		opts.speed = opts.speed / 2; // shuffle has 2 transitions
+		opts.speedAdjusted = true;
+	}
+	opts.random = 0;
+	opts.shuffle = opts.shuffle || {left:-w, top:15};
+	opts.els = [];
+	for (i=0; i < $slides.length; i++)
+		opts.els.push($slides[i]);
+
+	for (i=0; i < opts.currSlide; i++)
+		opts.els.push(opts.els.shift());
+
+	// custom transition fn (hat tip to Benjamin Sterling for this bit of sweetness!)
+	opts.fxFn = function(curr, next, opts, cb, fwd) {
+		if (opts.rev)
+			fwd = !fwd;
+		var $el = fwd ? $(curr) : $(next);
+		$(next).css(opts.cssBefore);
+		var count = opts.slideCount;
+		$el.animate(opts.shuffle, opts.speedIn, opts.easeIn, function() {
+			var hops = $.fn.cycle.hopsFromLast(opts, fwd);
+			for (var k=0; k < hops; k++) {
+				if (fwd)
+					opts.els.push(opts.els.shift());
+				else
+					opts.els.unshift(opts.els.pop());
+			}
+			if (fwd) {
+				for (var i=0, len=opts.els.length; i < len; i++)
+					$(opts.els[i]).css('z-index', len-i+count);
+			}
+			else {
+				var z = $(curr).css('z-index');
+				$el.css('z-index', parseInt(z,10)+1+count);
+			}
+			$el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() {
+				$(fwd ? this : curr).hide();
+				if (cb) cb();
+			});
+		});
+	};
+	$.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
+};
+
+// turnUp/Down/Left/Right
+$.fn.cycle.transitions.turnUp = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,false);
+		opts.cssBefore.top = next.cycleH;
+		opts.animIn.height = next.cycleH;
+		opts.animOut.width = next.cycleW;
+	});
+	opts.cssFirst.top = 0;
+	opts.cssBefore.left = 0;
+	opts.cssBefore.height = 0;
+	opts.animIn.top = 0;
+	opts.animOut.height = 0;
+};
+$.fn.cycle.transitions.turnDown = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,false);
+		opts.animIn.height = next.cycleH;
+		opts.animOut.top   = curr.cycleH;
+	});
+	opts.cssFirst.top = 0;
+	opts.cssBefore.left = 0;
+	opts.cssBefore.top = 0;
+	opts.cssBefore.height = 0;
+	opts.animOut.height = 0;
+};
+$.fn.cycle.transitions.turnLeft = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,true);
+		opts.cssBefore.left = next.cycleW;
+		opts.animIn.width = next.cycleW;
+	});
+	opts.cssBefore.top = 0;
+	opts.cssBefore.width = 0;
+	opts.animIn.left = 0;
+	opts.animOut.width = 0;
+};
+$.fn.cycle.transitions.turnRight = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,true);
+		opts.animIn.width = next.cycleW;
+		opts.animOut.left = curr.cycleW;
+	});
+	$.extend(opts.cssBefore, { top: 0, left: 0, width: 0 });
+	opts.animIn.left = 0;
+	opts.animOut.width = 0;
+};
+
+// zoom
+$.fn.cycle.transitions.zoom = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,false,true);
+		opts.cssBefore.top = next.cycleH/2;
+		opts.cssBefore.left = next.cycleW/2;
+		$.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
+		$.extend(opts.animOut, { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 });
+	});
+	opts.cssFirst.top = 0;
+	opts.cssFirst.left = 0;
+	opts.cssBefore.width = 0;
+	opts.cssBefore.height = 0;
+};
+
+// fadeZoom
+$.fn.cycle.transitions.fadeZoom = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,false);
+		opts.cssBefore.left = next.cycleW/2;
+		opts.cssBefore.top = next.cycleH/2;
+		$.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
+	});
+	opts.cssBefore.width = 0;
+	opts.cssBefore.height = 0;
+	opts.animOut.opacity = 0;
+};
+
+// blindX
+$.fn.cycle.transitions.blindX = function($cont, $slides, opts) {
+	var w = $cont.css('overflow','hidden').width();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts);
+		opts.animIn.width = next.cycleW;
+		opts.animOut.left   = curr.cycleW;
+	});
+	opts.cssBefore.left = w;
+	opts.cssBefore.top = 0;
+	opts.animIn.left = 0;
+	opts.animOut.left = w;
+};
+// blindY
+$.fn.cycle.transitions.blindY = function($cont, $slides, opts) {
+	var h = $cont.css('overflow','hidden').height();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts);
+		opts.animIn.height = next.cycleH;
+		opts.animOut.top   = curr.cycleH;
+	});
+	opts.cssBefore.top = h;
+	opts.cssBefore.left = 0;
+	opts.animIn.top = 0;
+	opts.animOut.top = h;
+};
+// blindZ
+$.fn.cycle.transitions.blindZ = function($cont, $slides, opts) {
+	var h = $cont.css('overflow','hidden').height();
+	var w = $cont.width();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts);
+		opts.animIn.height = next.cycleH;
+		opts.animOut.top   = curr.cycleH;
+	});
+	opts.cssBefore.top = h;
+	opts.cssBefore.left = w;
+	opts.animIn.top = 0;
+	opts.animIn.left = 0;
+	opts.animOut.top = h;
+	opts.animOut.left = w;
+};
+
+// growX - grow horizontally from centered 0 width
+$.fn.cycle.transitions.growX = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,true);
+		opts.cssBefore.left = this.cycleW/2;
+		opts.animIn.left = 0;
+		opts.animIn.width = this.cycleW;
+		opts.animOut.left = 0;
+	});
+	opts.cssBefore.top = 0;
+	opts.cssBefore.width = 0;
+};
+// growY - grow vertically from centered 0 height
+$.fn.cycle.transitions.growY = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,false);
+		opts.cssBefore.top = this.cycleH/2;
+		opts.animIn.top = 0;
+		opts.animIn.height = this.cycleH;
+		opts.animOut.top = 0;
+	});
+	opts.cssBefore.height = 0;
+	opts.cssBefore.left = 0;
+};
+
+// curtainX - squeeze in both edges horizontally
+$.fn.cycle.transitions.curtainX = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,false,true,true);
+		opts.cssBefore.left = next.cycleW/2;
+		opts.animIn.left = 0;
+		opts.animIn.width = this.cycleW;
+		opts.animOut.left = curr.cycleW/2;
+		opts.animOut.width = 0;
+	});
+	opts.cssBefore.top = 0;
+	opts.cssBefore.width = 0;
+};
+// curtainY - squeeze in both edges vertically
+$.fn.cycle.transitions.curtainY = function($cont, $slides, opts) {
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,false,true);
+		opts.cssBefore.top = next.cycleH/2;
+		opts.animIn.top = 0;
+		opts.animIn.height = next.cycleH;
+		opts.animOut.top = curr.cycleH/2;
+		opts.animOut.height = 0;
+	});
+	opts.cssBefore.height = 0;
+	opts.cssBefore.left = 0;
+};
+
+// cover - curr slide covered by next slide
+$.fn.cycle.transitions.cover = function($cont, $slides, opts) {
+	var d = opts.direction || 'left';
+	var w = $cont.css('overflow','hidden').width();
+	var h = $cont.height();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts);
+		if (d == 'right')
+			opts.cssBefore.left = -w;
+		else if (d == 'up')
+			opts.cssBefore.top = h;
+		else if (d == 'down')
+			opts.cssBefore.top = -h;
+		else
+			opts.cssBefore.left = w;
+	});
+	opts.animIn.left = 0;
+	opts.animIn.top = 0;
+	opts.cssBefore.top = 0;
+	opts.cssBefore.left = 0;
+};
+
+// uncover - curr slide moves off next slide
+$.fn.cycle.transitions.uncover = function($cont, $slides, opts) {
+	var d = opts.direction || 'left';
+	var w = $cont.css('overflow','hidden').width();
+	var h = $cont.height();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,true,true);
+		if (d == 'right')
+			opts.animOut.left = w;
+		else if (d == 'up')
+			opts.animOut.top = -h;
+		else if (d == 'down')
+			opts.animOut.top = h;
+		else
+			opts.animOut.left = -w;
+	});
+	opts.animIn.left = 0;
+	opts.animIn.top = 0;
+	opts.cssBefore.top = 0;
+	opts.cssBefore.left = 0;
+};
+
+// toss - move top slide and fade away
+$.fn.cycle.transitions.toss = function($cont, $slides, opts) {
+	var w = $cont.css('overflow','visible').width();
+	var h = $cont.height();
+	opts.before.push(function(curr, next, opts) {
+		$.fn.cycle.commonReset(curr,next,opts,true,true,true);
+		// provide default toss settings if animOut not provided
+		if (!opts.animOut.left && !opts.animOut.top)
+			$.extend(opts.animOut, { left: w*2, top: -h/2, opacity: 0 });
+		else
+			opts.animOut.opacity = 0;
+	});
+	opts.cssBefore.left = 0;
+	opts.cssBefore.top = 0;
+	opts.animIn.left = 0;
+};
+
+// wipe - clip animation
+$.fn.cycle.transitions.wipe = function($cont, $slides, opts) {
+	var w = $cont.css('overflow','hidden').width();
+	var h = $cont.height();
+	opts.cssBefore = opts.cssBefore || {};
+	var clip;
+	if (opts.clip) {
+		if (/l2r/.test(opts.clip))
+			clip = 'rect(0px 0px '+h+'px 0px)';
+		else if (/r2l/.test(opts.clip))
+			clip = 'rect(0px '+w+'px '+h+'px '+w+'px)';
+		else if (/t2b/.test(opts.clip))
+			clip = 'rect(0px '+w+'px 0px 0px)';
+		else if (/b2t/.test(opts.clip))
+			clip = 'rect('+h+'px '+w+'px '+h+'px 0px)';
+		else if (/zoom/.test(opts.clip)) {
+			var top = parseInt(h/2,10);
+			var left = parseInt(w/2,10);
+			clip = 'rect('+top+'px '+left+'px '+top+'px '+left+'px)';
+		}
+	}
+
+	opts.cssBefore.clip = opts.cssBefore.clip || clip || 'rect(0px 0px 0px 0px)';
+
+	var d = opts.cssBefore.clip.match(/(\d+)/g);
+	var t = parseInt(d[0],10), r = parseInt(d[1],10), b = parseInt(d[2],10), l = parseInt(d[3],10);
+
+	opts.before.push(function(curr, next, opts) {
+		if (curr == next) return;
+		var $curr = $(curr), $next = $(next);
+		$.fn.cycle.commonReset(curr,next,opts,true,true,false);
+		opts.cssAfter.display = 'block';
+
+		var step = 1, count = parseInt((opts.speedIn / 13),10) - 1;
+		(function f() {
+			var tt = t ? t - parseInt(step * (t/count),10) : 0;
+			var ll = l ? l - parseInt(step * (l/count),10) : 0;
+			var bb = b < h ? b + parseInt(step * ((h-b)/count || 1),10) : h;
+			var rr = r < w ? r + parseInt(step * ((w-r)/count || 1),10) : w;
+			$next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' });
+			(step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none');
+		})();
+	});
+	$.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
+	opts.animIn	   = { left: 0 };
+	opts.animOut   = { left: 0 };
+};
+
+})(jQuery);
diff --git a/themes/greydragon_old/js/ui.support.js b/themes/greydragon_old/js/ui.support.js
new file mode 100644
index 0000000..59fde3a
--- /dev/null
+++ b/themes/greydragon_old/js/ui.support.js
@@ -0,0 +1,80 @@
+/*
+* Grey Dragon Theme: JS support 
+* Copyright (c) 2007-2011 Serge Dosyukov
+* Dual licensed under the MIT and GPL licenses.
+*/
+
+jQuery.fn.extend({
+  scrollTo: function(a, b) { },
+
+  myAjaxLoginSubmit: function() {
+    $('form#g-login-form').one('submit', function() {
+      $(this).ajaxSubmit({
+        dataType: 'json', 
+        success: function(data) {
+          if (data.result == 'error') {
+            $('#g-login').html(data.form);
+            $().myAjaxLoginSubmit();
+          } else {
+            // object
+            alert(typeof(data));
+            Shadowbox.close(); 
+            window.location.reload(); 
+          }
+        }
+      }); 
+      return false;
+    });
+  },
+
+  myAjaxSubmit: function() {
+    $('form').one('submit', function() {
+      try {
+        $(this).ajaxSubmit({
+          success: function(data) {
+            // object
+            // alert(typeof(data));
+            if (data.result == 'error') {
+              $('#sb-content form').html(data.form);
+              $().myAjaxSubmit();
+            } else {
+              Shadowbox.close();
+              if (data.reload) {
+                window.location.reload();
+              }
+            }
+          }
+        });
+      } catch (e) { 
+        window.location.reload();
+      }
+
+      return false;
+    });
+  },
+
+  theme_ready: function() {
+    // Initialize dialogs
+    $(".g-dialog-link").gallery_dialog();
+
+    // Initialize short forms
+    $(".g-short-form").gallery_short_form();
+
+    try {
+      $(".g-message-block").fadeOut(10000);
+      $(".g-ajax-link").gallery_ajax();
+    } catch (e) { }
+
+    $("#g-site-menu>ul>li>ul").show();
+    $("#g-login-menu").show();
+    $(".g-context-menu").show();
+  }
+});
+
+function onMiniSlideShowReady() {
+  $("#g-rootpage-link").css("background-image", "none");
+}
+
+$(document).ready(function() {
+  $().theme_ready();
+});
diff --git a/themes/greydragon_old/libraries/MY_Theme_View.php b/themes/greydragon_old/libraries/MY_Theme_View.php
new file mode 100644
index 0000000..09d8da3
--- /dev/null
+++ b/themes/greydragon_old/libraries/MY_Theme_View.php
@@ -0,0 +1,902 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+class Theme_View extends Theme_View_Core {
+
+  protected $viewmode = "default";
+  protected $toolbar_large = FALSE;
+  protected $paginator_album;
+  protected $paginator_photo;
+  protected $sidebarvisible;
+  protected $sidebarallowed;
+  protected $sidebar_hideguest = FALSE;
+  protected $logopath;
+  protected $favicon = "lib/images/favicon.ico";
+  protected $appletouchicon;
+  protected $album_descmode = "hide";
+  protected $disablephotopage = FALSE;
+  protected $hidecontextmenu = FALSE;
+  protected $thumb_ratio = "";
+  protected $thumb_descmode_a = "overlay";
+  protected $thumb_descmode = "overlay";
+  protected $photo_descmode = "overlay_top";
+  protected $thumb_imgalign = "top";
+  protected $thumb_metamode = "default";
+  protected $is_blockheader_visible = TRUE;
+  protected $is_photometa_visible = FALSE;
+  protected $disable_seosupport = FALSE;
+  protected $mainmenu_position = "bottom-left";
+  protected $breadcrumbs_position = "bottom-right";
+  protected $breadcrumbs_showinroot = FALSE;
+  protected $copyright = null;
+  protected $show_guest_menu = FALSE;
+  protected $loginmenu_position = "default";
+  protected $visible_title_length = 15;
+  protected $title_source = "default";
+  protected $desc_allowbbcode = FALSE;
+  protected $enable_pagecache = FALSE;
+  protected $flex_rows = FALSE;
+  protected $photo_popupbox = "default";
+  protected $custom_css_path = "";
+  protected $thumb_inpage = FALSE;
+  protected $thumb_random = FALSE;
+  protected $row_count = 3;
+  protected $column_count = 3;
+
+  protected $crop_factor = -1;
+  protected $crop_class = "";
+  protected $_thumb_size_x = 200;
+  protected $_thumb_size_y = 200;
+  protected $allow_root_page = FALSE;
+  protected $show_root_page = FALSE;
+  protected $show_root_desc = TRUE;
+  protected $root_feed = "gallery/latest";
+  protected $root_cyclemode = "fade";
+  protected $root_delay = 15;
+  protected $root_description;
+  protected $permalinks = array("enter" => "?root=no", "root" => "?root=yes");
+
+  protected $last_update = 0;
+
+  protected $colorpack = "greydragon";
+  protected $framepack = "greydragon";
+  protected $themename = "";
+  protected $themeversion = "";
+  protected $themecss = array();
+
+  protected $is_rtl = FALSE;
+
+  protected function ensurevalue($value, $default) {
+    if ((!isset($value)) or ($value == "")):
+      return $default;
+    else:
+      return $value;
+    endif;
+  }
+
+  protected function ensureoptionsvalue($key, $default) {
+    return ($this->ensurevalue(module::get_var("th_greydragon", $key), $default));
+  }
+
+  public function read_session_cmdparam($cmd, $cookie, $issession, $default) {
+    try {
+      $_cmd = $_GET[$cmd]; 
+    } catch (Exception $e) {
+    };
+
+    if (isset($_cmd)):
+      $_var = strtolower($_cmd);
+      $_from_cmd = TRUE;
+      if ($_var == "default"):
+        $_var = $default;
+      endif;
+    else:
+      $_from_cmd = FALSE;
+      if ($cookie):
+        try { 
+          $_var = $_COOKIE[$cookie];
+        } catch (Exception $e) {
+        };
+      endif;
+    endif;
+
+    if (!isset($_var)):
+      $_var = $default;
+    endif;
+
+    if ($issession):
+      if ($_from_cmd):
+        setcookie($cookie, $_var, 0);
+      endif;
+    else:
+      setcookie($cookie, $_var, time() + 31536000);
+    endif;
+
+    return $_var;
+  }
+
+  public function load_sessioninfo() {
+    // Sidebar position is kept for 360 days. Can be changed via url
+    $this->sidebarallowed = $this->ensureoptionsvalue("sidebar_allowed", "any");
+    $_sb_visible = $this->ensureoptionsvalue("sidebar_visible", "right");
+
+    if ($this->sidebarallowed == "default"):
+      $this->sidebarallowed = $_sb_visible;
+      $this->sidebarvisible = $_sb_visible;
+    else:
+      $this->sidebarvisible = $this->read_session_cmdparam("sb", "gd_sidebar_pos", FALSE, $_sb_visible);
+    endif;
+    $this->colorpack = $this->read_session_cmdparam("colorpack", "gd_colorpack", TRUE,  $this->ensureoptionsvalue("color_pack", "greydragon"));
+    $this->framepack = $this->read_session_cmdparam("framepack", "gd_framepack", TRUE, $this->ensureoptionsvalue("frame_pack", "greydragon"));
+    $this->viewmode  = $this->read_session_cmdparam("viewmode", "gd_viewmode",  TRUE, $this->ensureoptionsvalue("viewmode", "default"));
+    $this->is_rtl    = $this->read_session_cmdparam("is_rtl", "gd_rtl", TRUE, "no") == "yes";
+		$this->thumb_ratio = $this->read_session_cmdparam("ratio", "gd_ratio", TRUE, $this->ensureoptionsvalue("thumb_ratio", "photo"));
+
+    if ($this->ensureoptionsvalue("allow_root_page", FALSE)):
+      $_root = $this->read_session_cmdparam("root", "gd_rootpage", TRUE, "yes"); 
+
+      $this->show_root_page = ($_root == "yes");
+      $this->allow_root_page = TRUE;
+
+      if ($this->show_root_page):
+        $item = $this->item();
+        if (($item) && ($item->id == item::root()->id)):
+          if (($this->sidebarvisible == "left") or ($this->sidebarvisible == "right")):
+            $this->sidebarvisible = "bottom";
+          endif;
+        else:
+          $this->show_root_page = FALSE;
+          setcookie("gd_rootpage", "no", 0);
+        endif;
+
+        if ($this->ensureoptionsvalue("hide_root_sidebar", FALSE)):
+          $this->sidebarallowed = "none";
+          $this->sidebarvisible = "none";
+        endif;
+      endif;
+    endif;
+
+    $this->sidebarvisible = $this->ensurevalue($this->sidebarvisible, "right");
+
+    switch ($this->sidebarallowed):
+      case "default":
+        break;
+      case "right":
+        $this->sidebarvisible = "right";
+        break;
+      case "left": 
+        $this->sidebarvisible = "left";
+        break;
+      case "bottom": 
+        $this->sidebarvisible = "bottom";
+        break;
+      case "top": 
+        $this->sidebarvisible = "top";
+        break;
+    endswitch;
+
+    if ($this->item()):
+      if ($this->ensureoptionsvalue("sidebar_albumonly", FALSE)):
+        if (!$this->item()->is_album()):
+          $this->sidebarvisible = "none";
+          $this->sidebarallowed = "none";
+        endif;
+      endif;
+    endif;
+
+    $this->sidebar_hideguest = $this->ensureoptionsvalue("sidebar_hideguest", FALSE);
+    if ((identity::active_user()->guest) & ($this->sidebar_hideguest)):
+      $this->sidebarvisible = "none";
+      $this->sidebarallowed = "none";
+    endif;
+
+    if (($this->page_subtype == "login") || ($this->page_subtype == "reauthenticate") || ($this->page_subtype == "error")): 
+      $this->sidebarvisible = "none";
+      $this->sidebarallowed = "none";
+    endif;
+
+    $this->last_update = $this->ensureoptionsvalue("last_update", time());
+    $this->toolbar_large = $this->ensureoptionsvalue("toolbar_large", FALSE);
+    $this->row_count = $this->ensureoptionsvalue("row_count", 3);
+    $this->column_count = $this->ensureoptionsvalue("column_count", 3);
+    $this->logopath = $this->ensureoptionsvalue("logo_path", url::file("lib/images/logo.png"));
+    $this->favicon = $this->ensurevalue(module::get_var("gallery", "favicon_url"), url::file("lib/images/favicon.ico"));
+    $this->appletouchicon = module::get_var("gallery", "apple_touch_icon_url");
+    $this->horizontal_crop = $this->ensureoptionsvalue("horizontal_crop", FALSE);
+    $this->album_descmode = $this->ensureoptionsvalue("album_descmode", "hide");
+    $this->disablephotopage = $this->ensureoptionsvalue("disablephotopage", FALSE);
+    $this->hidecontextmenu = $this->ensureoptionsvalue("hidecontextmenu", FALSE);
+    $this->visible_title_length = module::get_var("gallery", "visible_title_length", 15);
+    $this->title_source = $this->ensureoptionsvalue("title_source", "default");
+    $this->thumb_descmode_a = $this->ensureoptionsvalue("thumb_descmode_a", "overlay");
+    $this->thumb_descmode = $this->ensureoptionsvalue("thumb_descmode", "overlay");
+    $this->photo_descmode = $this->ensureoptionsvalue("photo_descmode", "overlay_top");
+
+    $this->thumb_random = $this->ensureoptionsvalue("thumb_random", FALSE);
+    $this->thumb_imgalign = $this->ensureoptionsvalue("thumb_imgalign", "top");
+    if (module::is_active("info")):
+      $this->thumb_metamode = $this->ensureoptionsvalue("thumb_metamode", "default");
+      $this->is_photometa_visible = (!$this->ensureoptionsvalue("hide_photometa", TRUE));
+    else:
+      $this->thumb_metamode = "hide";
+      $this->is_photometa_visible = FALSE;
+    endif;
+    $this->disable_seosupport = $this->ensureoptionsvalue("disable_seosupport", FALSE);
+    $this->is_blockheader_visible = (!$this->ensureoptionsvalue("hide_blockheader", FALSE));
+
+    $this->mainmenu_position = $this->ensureoptionsvalue("mainmenu_position", "default");
+    $this->show_guest_menu = $this->ensureoptionsvalue("show_guest_menu", FALSE);
+    $this->breadcrumbs_position = $this->ensureoptionsvalue("breadcrumbs_position", "default");
+    $this->breadcrumbs_showinroot = $this->ensureoptionsvalue("breadcrumbs_showinroot", FALSE);
+    $this->desc_allowbbcode = $this->ensureoptionsvalue("desc_allowbbcode", FALSE);
+
+    $this->loginmenu_position = $this->ensureoptionsvalue("loginmenu_position", "default");
+    $this->copyright = $this->ensureoptionsvalue("copyright", null);
+    $this->paginator_album = $this->ensureoptionsvalue("paginator_album", "top");
+    $this->paginator_photo = $this->ensureoptionsvalue("paginator_photo", "top");
+    $this->enable_pagecache = $this->ensureoptionsvalue("enable_pagecache", FALSE);
+    $this->flex_rows = $this->ensureoptionsvalue("flex_rows", FALSE);
+    $this->show_root_desc = !$this->ensureoptionsvalue("hide_root_desc", FALSE);
+    $this->root_feed = $this->ensureoptionsvalue("root_feed", "gallery/latest");
+  	$this->root_cyclemode = $this->ensureoptionsvalue("root_cyclemode", "fade");
+    $this->root_delay = $this->ensureoptionsvalue("root_delay", "15");
+    $this->root_description = module::get_var("th_greydragon", "root_description");
+    if ($this->ensureoptionsvalue("use_permalinks", FALSE)):
+      $this->permalinks = array("enter" => "enter", "root" => "root");
+    endif;
+    if (((module::is_active("shadowbox")) and (module::info("shadowbox"))) 
+        or ((module::is_active("fancybox")) and (module::info("fancybox")))
+        or ((module::is_active("colorbox")) and (module::info("colorbox")))
+       ):
+      $this->photo_popupbox = $this->ensureoptionsvalue("photo_popupbox", "default");
+    else:
+      $this->photo_popupbox = "none";
+    endif;
+
+    try {
+      $theme_info = new ArrayObject(parse_ini_file(THEMEPATH . "greydragon/theme.info"), ArrayObject::ARRAY_AS_PROPS);
+      $this->themename = $theme_info->name;
+      $this->themeversion = $theme_info->version;
+    } catch (Exception $e) {
+      $this->themename = "Grey Dragon Theme";
+      $this->themeversion = "2.7.+";
+    }
+
+    $this->custom_css_path = $this->ensureoptionsvalue("custom_css_path", "");
+
+    switch ($this->thumb_ratio):
+      /* case "square":
+        $this->crop_factor = 1;
+        $this->thumb_type = 'g-thumbtype-sqr';
+        break;
+      */
+      case "digital":
+        $this->crop_factor = 4/3;
+        $this->thumb_type = 'g-thumbtype-dgt';
+        break;
+      case "digital_ex":
+        $this->crop_factor = 4/3;
+        $this->thumb_type = 'g-thumbtype-dgt';
+        $this->_thumb_size_x = 300;
+        break;
+      case "film":
+        $this->crop_factor = 3/2;
+        $this->thumb_type = 'g-thumbtype-flm';
+        break;
+      case "film_ex":
+        $this->crop_factor = 3/2;
+        $this->thumb_type = 'g-thumbtype-flm';
+        $this->_thumb_size_x = 300;
+        break;
+      case "wide":
+        $this->crop_factor = 16/9;
+        $this->thumb_type = 'g-thumbtype-wd';
+        break;
+      case "wide_ex":
+        $this->crop_factor = 16/9;
+        $this->thumb_type = 'g-thumbtype-wd';
+        $this->_thumb_size_x = 300;
+        break;
+      case "photo_ex":
+        $this->crop_factor = 1;
+        $this->thumb_type = 'g-thumbtype-sqr';
+        $this->_thumb_size_x = 300;
+        break;
+      case "photo":
+      default:
+        $this->crop_factor = 1;
+        $this->thumb_type = 'g-thumbtype-sqr';
+        break;
+    endswitch;
+
+    $this->_thumb_size_y = intval($this->_thumb_size_x / $this->crop_factor);
+
+    if (($this->sidebarvisible == "none") or ($this->sidebarvisible == "bottom") or ($this->sidebarvisible == "top") ):
+      $this->thumb_inpage = $this->ensureoptionsvalue("thumb_inpage", FALSE);
+    endif;                 
+  }
+
+  public function is_sidebarallowed($align) {
+    return (($this->sidebarallowed == "any") or ($this->sidebarallowed == $align));
+  }
+
+  public function custom_header() {
+    if (Kohana::find_file('views', "header.html", FALSE)):
+      return new View("header.html"); 
+    endif;
+  }
+
+  public function custom_footer() {
+    if (Kohana::find_file('views', "footer.html", FALSE)):
+      return new View("footer.html"); 
+    endif;
+  }
+
+  public function get_item_title($item, $allowbbcode = FALSE, $limit_title_length = 0) {
+    if (!$item)
+      return "";
+
+    if ($item->is_album()):
+      $title = $item->title;
+    else:
+      switch ($this->title_source):
+	      case "description":
+	        $title = $item->description;
+	        break;
+	      case "no-filename":
+	        $title = $item->title;
+	        $filename = $item->name;
+
+	        if (strcasecmp($title, $filename) == 0):
+	          $title = "";
+	        else:
+		        if (defined('PATHINFO_FILENAME')):
+	  	        $filename = pathinfo($filename, PATHINFO_FILENAME);
+		        elseif (strstr($item->filename, '.')):
+		          $filename = substr($filename, 0, strrpos($filename, '.'));
+		        endif; 
+
+		        if (strcasecmp($title, $filename) == 0):
+		          $title = "";
+		        else:
+			        $filename = item::convert_filename_to_title($filename); // Normalize filename to title format 
+		  	      if (strcasecmp($title, $filename) == 0)
+	  	  	      $title = "";
+						endif;
+					endif;
+	        break;
+	      default:
+	        $title = $item->title;
+	        break;
+	    endswitch;
+	  endif;
+
+    $title = html::purify($title);
+    if ($allowbbcode):
+      $title = $this->bb2html($title, 1);
+    else:
+      $title = $this->bb2html($title, 2);
+    endif;
+
+    if ($limit_title_length):
+      $title = text::limit_chars($title, $limit_title_length);
+    endif;
+
+    if ($title === "")
+      $title = t(ucfirst($item->type)) . " " . $item->id;
+
+    return $title;
+  }
+
+  public function breadcrumb_menu($theme, $parents) {
+    $content = "";
+    if ($this->breadcrumbs_position == "hide"):
+    elseif ($this->item() and (!empty($parents) or (empty($parents) and $this->breadcrumbs_showinroot))):
+      $content .= '<ul class="g-breadcrumbs g-' . $this->breadcrumbs_position . '">';
+      $i = 0;
+      if (!empty($parents)):
+        foreach ($parents as $parent):
+          $content .= '<li ' . (($i == 0)? " class=\"g-first\"" : null) . '>';
+          $content .= (($i > 0)? " :: " : null );
+          $content .= '<a href="' . $parent->url($parent == $this->item()->parent() ? "show={$this->item()->id}" : null) . '">';
+          $content .= $this->get_item_title($parent, FALSE, $this->visible_title_length);
+          $content .= '</a></li>';
+          $i++;
+        endforeach;
+      endif;
+      $content .= '<li class="g-active ' . (($i == 0)? " g-first" : null) . '"> '. (($i > 0)? " :: " : null ) . $this->get_item_title($this->item(), FALSE, $this->visible_title_length) . '</li>';
+      $content .= '</ul>';
+    endif;
+
+    return $content;
+  }
+
+  protected function sidebar_menu_item($type, $url, $caption, $css) {
+    if (!$this->is_sidebarallowed($type)):
+      return "";
+    endif;
+
+    $iscurrent = ($this->sidebarvisible == $type);
+    $content_menu = '<li>'; 
+    if (!$iscurrent):
+      $content_menu .= '<a title="' . $caption . '" href="' . $url . '?sb=' . $type . '" rel="nofollow">';
+    endif;
+    $content_menu .= '<span class="ui-icon g-sidebar-' . $css;
+    if ($iscurrent):
+      $content_menu .= ' g-current';
+    endif;
+    $content_menu .= '">' . $caption . '</span>';
+    if (!$iscurrent):
+      $content_menu .= '</a>';
+    endif;
+
+    return $content_menu . '</li>';
+  }
+
+  public function sidebar_menu($url) {
+    if ($this->sidebarallowed != "any"):
+      return "";
+    endif;
+    if ($this->page_subtype == "profile"):
+      return "";
+    endif;
+
+    $content_menu  = $this->sidebar_menu_item("left", $url, t("Sidebar Left"), "left");
+    $content_menu .= $this->sidebar_menu_item("top", $url, t("Sidebar Top"), "top");
+    $content_menu .= $this->sidebar_menu_item("none", $url, t("No Sidebar"), "full");
+    $content_menu .= $this->sidebar_menu_item("bottom", $url, t("Sidebar Bottom"), "bottom");
+    $content_menu .= $this->sidebar_menu_item("right", $url, t("Sidebar Right"), "right");
+    return '<ul id="g-viewformat">' . $content_menu . '</ul>';
+  }
+
+  public function add_paginator($position, $isalbum = TRUE) {
+    if ($isalbum):
+      $check = (($this->paginator_album == "both") or ($this->paginator_album == $position));
+    else:
+      $check = (($this->paginator_photo == "both") or ($this->paginator_photo == $position));
+    endif;
+
+    if ($check):
+      return ($this->paginator());
+    else:
+      return "";
+    endif;
+  }
+
+  public function get_bodyclass() {
+    $body_class = "";
+    if ($this->is_rtl):
+      $body_class = "rtl";
+    endif;
+    if ($this->toolbar_large):
+      $body_class .= " g-toolbar-large";
+    endif;
+    if ($this->viewmode == "mini"):
+      $body_class .= " viewmode-mini";
+    endif;
+		$body_class .= " g-sidebar-" . $this->sidebarvisible;
+
+    switch ($this->column_count):
+      case 5:    
+        $body_class .= " g-column-5";
+        break;
+      case 4:    
+        $body_class .= " g-column-4";
+        break;
+      case 2:
+        $body_class .= " g-column-2";
+        break;
+      case -1:
+        $body_class .= " g-column-flex";
+        break;
+      case 3:
+      default:
+        $body_class .= " g-column-3";
+        break;
+    endswitch;
+
+
+    switch ($this->thumb_ratio):
+      case "digital_ex":
+      case "film_ex":
+      case "wide_ex":
+      case "photo_ex":
+        $body_class .= ' g-extended';
+        break;
+      default:
+        break;
+    endswitch;
+
+    $body_class .= " g-" . $this->framepack;
+    return 'class="' . trim($body_class) . '"';
+  }
+
+  public function get_thumb_link($item) {
+		if ($item->is_album()):
+		  return "";
+		endif;
+    if (item::viewable($item)):
+   	  if (access::can("view_full", $item)):
+   			$direct_link = $item->file_url();
+   		else:
+   			$direct_link = $item->resize_url();
+      endif;
+      return '<a title="' . $this->get_item_title($item) . '" style="display: none;" class="g-sb-preview" rel="g-preview" href="' . $direct_link . '">&nbsp;</a>';
+    else:
+  	  return "";
+		endif;
+  }
+
+  public function get_thumb_element($item, $addcontext = FALSE, $linkonly = FALSE) {
+    $thumb_item = $item;
+    if ($this->thumb_random):
+      if ($item->is_album() && ($rnd = item::random_query()->where("parent_id", "=", $item->id)->find()) && $rnd->loaded()):
+        $thumb_item = $rnd;
+      endif;
+    endif;
+
+    $item_class = $item->is_album() ? "g-album" : "g-photo";
+    $content = '<li id="g-item-id-' . $item->id . '" class="g-item ' . $item_class . ' ' . $this->thumb_type;
+    if ($item->is_album()):
+    	$_thumb_descmode = $this->thumb_descmode_a;
+		else:
+    	$_thumb_descmode = $this->thumb_descmode;
+		endif;
+
+    $content .= ($_thumb_descmode == "bottom")? " g-expanded" : " g-default";
+
+    if ($thumb_item->has_thumb()):
+      $is_portrait = ($thumb_item->thumb_height > $thumb_item->thumb_width);
+      $_shift = "";
+      switch ($this->thumb_imgalign):
+        case "center":
+          if (($this->crop_factor == 1) and (!$is_portrait)): 
+            $_shift = 'style="margin-top: ' . intval(($this->_thumb_size_y - $thumb_item->thumb_height) / 2) . 'px;"';
+          elseif ($this->crop_factor > 0): 
+            $_shift = 'style="margin-top: -' . intval(($thumb_item->thumb_height - $this->_thumb_size_y) / 2) . 'px;"';
+          endif;
+          break;
+        case "bottom":
+          if (($this->crop_factor == 1) and (!$is_portrait)): 
+            $_shift = 'style="margin-top: ' . intval($this->_thumb_size_y - $thumb_item->thumb_height) . 'px;"';
+          elseif ($this->crop_factor > 0): 
+            $_shift = 'style="margin-top: -' . intval($thumb_item->thumb_height - $this->_thumb_size_y) . 'px;"';
+          endif;
+          break;
+        case "fit":
+          break;
+        case "top":
+        default:
+          break;
+      endswitch;
+    else:
+      $is_portrait = FALSE;
+      $_shift = 'style="margin-top: 0px;"';
+    endif;
+
+    $content .= ($is_portrait)? " g-portrait" : " g-landscape";
+    $content .= '">' . $this->thumb_top($item);
+
+    $content .= '<div class="g-thumbslide">';
+		$thumb_content = '<p class="g-thumbcrop">';
+
+		$use_direct_link = (($this->disablephotopage) && (!$item->is_album())); 
+		$class_name = "g-thumblink";
+		if ($use_direct_link):
+			$class_name .= ' g-sb-preview" rel="g-preview';
+		  if (access::can("view_full", $item)):
+				$direct_link = $item->file_url();
+			else:
+				$direct_link = $item->resize_url();
+			endif;
+		else:
+			$direct_link = $item->url();
+		endif;
+
+    if ($use_direct_link && module::is_active("exif") && module::info("exif")): 
+      $thumb_content .= '<a class="g-meta-exif-link g-dialog-link" href="' . url::site("exif/show/{$item->id}") . '" title="' . t("Photo details")->for_html_attr() . '">&nbsp;</a>';
+    endif;
+
+    $thumb_content .= '<a title="' . $this->get_item_title($item) . '" '. $_shift . ' class="' . $class_name . '" href="' . $direct_link . '">';
+    if ($thumb_item->has_thumb()):
+      if (($this->crop_factor > 1) && ($this->thumb_imgalign == "fit")):
+      	if ($thumb_item->thumb_height > $this->_thumb_size_y):
+      		if ($is_portrait):
+      			$_max = $this->_thumb_size_y;
+      		else:
+	      	  $_max = intval($this->_thumb_size_x * ($this->_thumb_size_y / $thumb_item->thumb_height));
+	      	endif;
+	      else:
+	        $_max = $this->_thumb_size_x;
+        endif;
+      	$_max = min($thumb_item->thumb_width, $_max);
+        $thumb_content .= $thumb_item->thumb_img(array(), $_max);
+      else:
+        $thumb_content .= $thumb_item->thumb_img();
+      endif;
+    else:
+      $thumb_content .= '<img title="No Image" alt="No Image" src="' . $this->url("images/missing-img.png") . '"/>';
+    endif;
+    $thumb_content .= '</a></p>';
+
+    if (($this->thumb_metamode != "hide") and ($_thumb_descmode == "overlay_bottom")):
+      $_thumb_metamode = "merged";
+    else:
+	    $_thumb_metamode = $this->thumb_metamode;
+    endif;
+
+    if (($_thumb_descmode == "overlay") or ($_thumb_descmode == "overlay_top") or ($_thumb_descmode == "overlay_bottom")):
+      $thumb_content .= '<ul class="g-description ';
+      if ($_thumb_descmode == "overlay_top"):
+        $thumb_content .= 'g-overlay-top';
+      endif;
+      if ($_thumb_descmode == "overlay_bottom"):
+        $thumb_content .= 'g-overlay-bottom';
+      endif;
+      $thumb_content .= '"><li class="g-title">' . $this->get_item_title($item, FALSE, $this->visible_title_length) . '</li>';
+      if ($_thumb_metamode == "merged"):                                                    
+        $thumb_content .= $this->thumb_info($item);
+      endif;
+      $thumb_content .= '</ul>';
+    endif;
+
+    if (($_thumb_metamode == "default") and ($_thumb_descmode != "overlay_bottom")): 
+      $thumb_content .= '<ul class="g-metadata">' . $this->thumb_info($item) . '</ul>';
+    endif;
+
+    if ($_thumb_descmode == "bottom"):
+      $thumb_content .= '<ul class="g-description">';
+      $thumb_content .= '<li class="g-title">' . $this->get_item_title($item) . '</li>';
+      if ($_thumb_metamode == "merged"): 
+        $thumb_content .= $this->thumb_info($item);
+      endif;
+      $thumb_content .= '</ul>';
+    endif;
+
+    if ($addcontext):
+      $_text = $this->context_menu($item, "#g-item-id-{$item->id} .g-thumbnail");
+      $thumb_content .= (stripos($_text, '<li>'))? $_text : null;
+    endif;
+
+		try {
+	    $view = new View("frame.html");
+	    $view->thumb_content = $thumb_content;
+	    $content .= $view;
+    } catch (Exception $e) {
+			$content .= $thumb_content;
+    }
+
+    $content .= '</div>';
+    $content .= $this->thumb_bottom($item);
+    $content .= '</li>';
+
+    return $content;
+  }
+
+  public function get_block_html($module) {
+    $active = block_manager::get_active("site_sidebar");
+    $result = "";
+    foreach ($active as $id => $desc) {
+      if (($desc[0] == $module) and (method_exists("$desc[0]_block", "get"))) {
+        $block = call_user_func(array("$desc[0]_block", "get"), $desc[1], $this);
+        if (!empty($block)) {
+          $block->id = $id;
+          $block->css_id = $block->css_id . "-inline";
+          $result .= $block;
+        }
+      }
+    }
+    return $result;
+  }
+
+  public function css_link($file, $direct = FALSE) {
+    if (!$direct):
+      $file = $this->url("css/" . $file);
+    endif;
+    return "\n<link rel=\"stylesheet\" href=\"" . $file . "\" type=\"text/css\" media=\"screen,print,projection\" />\n";
+  }
+
+  public function custom_css_inject($direct) {
+    $_css = $this->custom_css_path;
+    if ($_css != ""):
+      $_fileonly = (stripos($_css, '/') === FALSE);
+
+      if ($_fileonly):
+        if (!$direct):
+          return $this->css($_css);
+        endif;
+      else:
+        if ($direct):
+          return $this->css_link($_css, TRUE);
+        endif;
+      endif;
+    else:
+      return "";
+    endif;
+  }
+
+  public function theme_js_inject() {
+    $js = "";
+    if ($this->show_root_page):
+      $js .= $this->script("jquery.cycle.js");
+    endif;
+//    $js .= $this->script("jquery.touchslider.js");
+    $js .= $this->script("ui.support.js");
+    return $js;
+  }
+
+  public function theme_css_inject() {
+    $css  = $this->css("screen.css");
+    $css .= $this->css("colors.css");
+    $css .= $this->css("frame.css");
+    $css .= $this->custom_css_inject(FALSE);
+    return $css;
+  }
+
+  public function credits() {
+    if (module::get_var("gallery", "show_credits")):
+      $version_string = SafeString::of_safe_html('Gallery ' . gallery::VERSION);
+      return '<ul id="g-credits">'
+        . '<li class="g-branding"><a id="g-gallery-logo" href="http://gallery.menalto.com" title="' . $version_string . '"></a>'
+        . '<a id="g-theme-logo" href="http://codex.gallery2.org/Gallery3:Themes:greydragon" target="_blank" title="' . $this->themename . ' ' . $this->themeversion . ' (' . $this->colorpack . ')"></a></li>'
+        . gallery_theme::credits()
+        . '</ul>';
+    else:
+      return '';
+    endif;
+  }
+
+  // $mode: bit 1 - use mix mode ($mode in [1, 3]), bit 2 - strips bbcode ($mode in [2, 3])
+  public function bb2html($text, $mode) {
+    // Syntax Sample:
+    // --------------
+    // [img]http://elouai.com/images/star.gif[/img]
+    // [url="http://elouai.com"]eLouai[/url]
+    // [size="25"]HUGE[/size]
+    // [color="red"]RED[/color]
+    // [b]bold[/b]
+    // [i]italic[/i]
+    // [u]underline[/u]
+    // [list][*]item[*]item[*]item[/list]
+    // [code]value="123";[/code]
+    // [quote]John said yadda yadda yadda[/quote]
+  
+    static $bbcode_mappings = array(
+      "#\\[b\\](.*?)\\[/b\\]#" => "<strong>$1</strong>",
+      "#\\[i\\](.*?)\\[/i\\]#" => "<em>$1</em>",
+      "#\\[u\\](.*?)\\[/u\\]#" => "<u>$1</u>",
+      "#\\[s\\](.*?)\\[/s\\]#" => "<strike>$1</strike>",
+      "#\\[o\\](.*?)\\[/o\\]#" => "<overline>$1</overline>",
+      "#\\[url\\](.*?)\[/url\\]#" => "<a href=\"$1\">$1</a>",
+      "#\\[url=(.*?)\\](.*?)\[/url\\]#" => "<a href=\"$1\" target=\"_blank\">$2</a>",
+      "#\\[mail=(.*?)\\](.*?)\[/mail\\]#" => "<a href=\"mailto:$1\" target=\"_blank\">$2</a>",
+      "#\\[img\\](.*?)\\[/img\\]#" => "<img src=\"$1\" alt=\"\" />",
+      "#\\[img=(.*?)\\](.*?)\[/img\\]#" => "<img src=\"$1\" alt=\"$2\" />",
+      "#\\[quote\\](.*?)\\[/quote\\]#" => "<blockquote><p>$1</p></blockquote>",
+      "#\\[code\\](.*?)\\[/code\\]#" => "<pre>$1</pre>",
+      "#\\[size=([^\\[]*)\\]([^\\[]*)\\[/size\\]#" => "<span style=\"font-size: $1;\">$2</span>",
+      "#\\[color=([^\\[]*)\\]([^\\[]*)\\[/color\\]#" => "<span style=\"color: $1;\">$2</span>",
+      "#\\[class=([^\\[]*)\\]([^\\[]*)\\[/class\\]#" => "<span class=\"$1\">$2</span>",
+      "#\\[center\\](.*?)\\[/center\\]#" => "<div style=\"text-align: center;\">$1</div>",
+      "#\\[list\\](.*?)\\[/list\\]#" => "<ul>$1</ul>",
+      "#\\[ul\\](.*?)\\[/ul\\]#" => "<ul>$1</ul>",
+      "#\\[li\\](.*?)\\[/li\\]#" => "<li>$1</li>",
+    );
+  
+    static $bbcode_strip = '|[[\/\!]*?[^\[\]]*?]|si'; 
+
+    if (($mode == 1) or ($mode == 3)):
+      $newtext = str_replace("&lt;", "<", $text); 
+      $newtext = str_replace("&gt;", ">", $newtext); 
+      $newtext = str_replace("&quot;", "\"", $newtext); 
+    else:
+	    // Replace any html brackets with HTML Entities to prevent executing HTML or script 
+      $newtext = str_replace("<", "&lt;", $text); 
+      $newtext = str_replace(">", "&gt;", $newtext); 
+      $newtext = str_replace("&amp;quot;", "&quot;", $newtext); 
+    endif;
+
+    // Convert new line chars to html <br /> tags 
+    $newtext = nl2br($newtext);  
+
+    if (strpos($text, "[") !== false):
+      if (($mode == 2) or ($mode == 3)):
+        $newtext = preg_replace($bbcode_strip, '', $newtext);
+      else:
+        $newtext = preg_replace(array_keys($bbcode_mappings), array_values($bbcode_mappings), $newtext);
+      endif;
+    endif;
+
+    return stripslashes($newtext);  //stops slashing, useful when pulling from db
+  }
+
+  function curl_get_file_contents($url) {
+    $curl = curl_init();
+    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+    curl_setopt($curl, CURLOPT_URL, $url);
+    $contents = curl_exec($curl);
+    curl_close($curl);
+ 
+    if ($contents):
+    	return $contents;
+    else:
+    	return FALSE;
+    endif;
+  }
+
+  function valid_url($str) {
+  	return ( ! preg_match('/^(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i', $str)) ? FALSE : TRUE;
+  }
+
+  function get_slideshow_list($limit = 10) {
+		if( ! function_exists('simplexml_load_string'))
+			throw new Kohana_User_Exception('Feed Error', 'SimpleXML must be installed!');
+
+		$items = array();
+		$host = 'http://' . $_SERVER['SERVER_NAME'] . '/';
+
+		$feed_url = $this->root_feed;
+	  if (!$this->valid_url($feed_url)):
+	    $feed_url = $host . $feed_url;
+	  endif;
+
+	  $use_file_load = ($this->valid_url($feed_url)) || is_file($feed_url); 
+
+	  $er = error_reporting(0);
+		// Try to get feed directly
+		try {
+	    try {
+	      if ($use_file_load):
+	    		$feed = simplexml_load_file($feed_url, 'SimpleXMLElement', LIBXML_NOCDATA);
+	      else:
+	    		$feed = simplexml_load_string($feed_url, 'SimpleXMLElement', LIBXML_NOCDATA);
+	      endif;
+	    } catch (Exception $e) {
+			}
+	  } catch (Exception $e) {
+	  };
+
+		if (isset($feed) && ($feed)):
+			// Direct load worked fine
+		else:
+			// Direct load did not work, let's try CURL (URL file-access is disabled ?)
+	    try {
+        $file = $this->curl_get_file_contents($feed_url);
+      	if ($file):
+        	$feed = simplexml_load_string($file, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
+      	endif;
+    	} catch (Exception $e) {
+    	};
+		endif;
+  	error_reporting($er);
+
+  	if (isset($feed) && ($feed)):
+			$feed = isset($feed->channel) ? $feed->channel->xpath("//media:content[contains(@url, 'var/resizes')]") : array();
+			$i = 0;
+			foreach ($feed as $item):
+				if ($limit > 0 AND $i++ === $limit)
+					break;
+    		$items[] = (array) $item;
+			endforeach;
+		endif;
+		return $items;
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/themes/greydragon_old/module.info b/themes/greydragon_old/module.info
new file mode 100644
index 0000000..4a65e8c
--- /dev/null
+++ b/themes/greydragon_old/module.info
@@ -0,0 +1,9 @@
+name        = "GreyDragon Shared"
+description = "Shared content for modules from GreyDragon. Need to be activated.<br />Version 1.3 | By <a href=http://blog.dragonsoft.us>Serguei Dosyukov</a>"
+version     = 13
+author_name = "Serguei Dosyukov"
+author_url  = "http://blog.dragonsoft.us/gallery-3/"
+info_url    = ""
+discuss_url = ""
+
+
diff --git a/themes/greydragon_old/theme.info b/themes/greydragon_old/theme.info
new file mode 100644
index 0000000..f2718e4
--- /dev/null
+++ b/themes/greydragon_old/theme.info
@@ -0,0 +1,11 @@
+name        = "Grey Dragon Theme"
+description = "A Crisp flexible theme with support of Color Packs and minimized on JS overhead"
+version     = 3.2.2
+author      = "2010-2012 Serguei Dosyukov"
+site        = 1
+admin       = 0
+author_name = "Serguei Dosyukov"
+author_url  = "http://blog.dragonsoft.us/gallery-3/"
+info_url    = "http://codex.gallery2.org/Gallery3:Themes:greydragon";
+discuss_url = "http://gallery.menalto.com/forum_theme_greydragon"
+vote        = "http://gallery.menalto.com/gallery/g3demosites/";
diff --git a/themes/greydragon_old/thumbnail.png b/themes/greydragon_old/thumbnail.png
new file mode 100644
index 0000000..4b80eca
Binary files /dev/null and b/themes/greydragon_old/thumbnail.png differ
diff --git a/themes/greydragon_old/views/album.html.php b/themes/greydragon_old/views/album.html.php
new file mode 100644
index 0000000..d371cae
--- /dev/null
+++ b/themes/greydragon_old/views/album.html.php
@@ -0,0 +1,68 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<div id="g-album-header">
+  <?= $theme->album_top() ?>
+  <h1><?= $theme->get_item_title($item, TRUE) ?> <?= ($theme->item()->id != item::root()->id && 0 < count($item->children())) ? t("(%count Bilder)", array("count"=>count($item->children()))) : ""?></h1>
+</div>
+
+<?= $theme->add_paginator("top"); ?>
+
+<? if (($theme->album_descmode == "top") and ($item->description)): ?>
+  <div id="g-info"><div class="g-description"><?= $theme->bb2html(html::purify($item->description), 1); ?></div></div>
+<? endif; ?>
+
+<div class="g-album-grid-container">
+<ul id="g-album-grid">
+<?
+  if (count($children)):
+		$siblings = $item->children();
+		if (($theme->disablephotopage) && (count($siblings) > count($children))):
+			$j = 0;
+			foreach ($siblings as $i => $sibling):
+				if ($sibling->rand_key == $children[$j]->rand_key):
+					echo $theme->get_thumb_element($sibling, !$theme->hidecontextmenu);
+					if ($j + 1 < count($children)):
+						$j++;
+					endif;
+				else:
+					echo $theme->get_thumb_link($sibling);
+				endif;
+			endforeach;
+		else:         
+			foreach ($children as $i => $child):
+				echo $theme->get_thumb_element($child, !$theme->hidecontextmenu);
+			endforeach;
+		endif;
+	else:
+    if ($user->admin || access::can("add", $item)):
+      $addurl = url::site("uploader/index/$item->id"); ?>
+      <li><?= t("There aren't any photos here yet! <a %attrs>Add some</a>.", array("attrs" => html::mark_clean("href=\"$addurl\" class=\"g-dialog-link\""))) ?></li>
+    <? else: ?>
+      <li><?= t("There aren't any photos here yet!") ?></li>
+    <? endif; ?>
+<? endif; ?>
+</ul>
+</div>
+
+<? if (($theme->album_descmode == "bottom") and ($item->description)): ?>
+  <div id="g-info"><div class="g-description"><?= $theme->bb2html(html::purify($item->description), 1) ?></div></div>
+<? endif; ?>
+<?= $theme->album_bottom() ?>
+
+<?= $theme->add_paginator("bottom"); ?>
diff --git a/themes/greydragon_old/views/block.html.php b/themes/greydragon_old/views/block.html.php
new file mode 100644
index 0000000..e9d1a85
--- /dev/null
+++ b/themes/greydragon_old/views/block.html.php
@@ -0,0 +1,29 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<? if ($anchor): ?>
+<a name="<?= $anchor ?>"></a>
+<? endif ?>
+<div id="<?= $css_id ?>" class="g-block">
+  <? if (isset($theme) and ($theme->is_blockheader_visible)): ?>
+  <h2><?= $title ?></h2>
+  <? endif ?>
+  <div class="g-block-content">
+    <?= $content ?>
+  </div>
+</div>
diff --git a/themes/greydragon_old/views/calpage.html.php b/themes/greydragon_old/views/calpage.html.php
new file mode 100644
index 0000000..c87d2c9
--- /dev/null
+++ b/themes/greydragon_old/views/calpage.html.php
@@ -0,0 +1,257 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<!DOCTYPE html >
+<? $theme->load_sessioninfo(); ?>
+<html <?= $theme->html_attributes() ?> xml:lang="en" lang="en" <?= ($theme->is_rtl)? "dir=rtl" : null; ?> >
+<?
+  $item = $theme->item();
+  if (($theme->enable_pagecache) and (isset($item))):
+    // Page will expire in 60 seconds
+    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 60).'GMT');  
+    header("Cache-Control: public");
+    header("Cache-Control: post-check=3600, pre-check=43200", false);
+    header("Content-Type: text/html; charset=UTF-8");
+    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
+  endif;
+?>
+<!-- <?= $theme->themename ?> v.<?= $theme->themeversion ?> (<?= $theme->colorpack ?> : <?= $theme->framepack ?>) - Copyright (c) 2009-2012 Serguei Dosyukov - All Rights Reserved -->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<? $theme->start_combining("script,css") ?>
+<? if ($page_title): ?>
+<?   $_title = $page_title ?> 
+<? else: ?>
+<?   if ($theme->item()): ?>
+<?     $_title = $theme->get_item_title($theme->item()); ?>
+<?   elseif ($theme->tag()): ?>
+<?     $_title = t("Photos tagged with %tag_title", array("tag_title" => $theme->bb2html($theme->tag()->name, 2))) ?>
+<?   else: /* Not an item, not a tag, no page_title specified.  Help! */ ?>
+<?     $_title = $theme->bb2html(item::root()->title, 2); ?>
+<?   endif ?>
+<? endif ?>
+<title><?= $_title ?></title>
+<? if ($theme->disable_seosupport): ?>
+<meta name="robots" content="noindex, nofollow, noarchive" />
+<meta name="googlebot" content="noindex, nofollow, noarchive, nosnippet, noodp, noimageindex, notranslate" />
+<meta name="slurp" content="noindex, nofollow, noarchive, nosnippet, noodp, noydir" />
+<meta name="msnbot" content="noindex, nofollow, noarchive, nosnippet, noodp" />
+<meta name="teoma" content="noindex, nofollow, noarchive" />
+<? endif; ?>
+<!-- Internet Explorer 9 Meta tags : Start -->
+<meta name="application-name" content="<?= $_title; ?>" />
+<meta name="msapplication-tooltip" content="<?= t("Start"); ?> <?= $_title; ?>" />
+<meta name="msapplication-starturl" content="<?= item::root()->url() ?>" />
+<? if ($theme->allow_root_page): ?>
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Page") ?>; action-uri=<?= item::root()->url(); ?><?= $theme->permalinks["root"]; ?>; icon-uri=favicon.ico" />
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Album") ?>; action-uri=<?= item::root()->url(); ?><?= $theme->permalinks["enter"]; ?>; icon-uri=favicon.ico" />
+<? else: ?>
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Album") ?>; action-uri=<?= item::root()->url(); ?>; icon-uri=favicon.ico" />
+<? endif; ?>
+<? if (identity::active_user()->admin): ?>
+<meta name="msapplication-task-separator" content="gallery3-greydragon" />
+<meta name="msapplication-task" content="name=<?= t("Admin") ?>: <?= t("Dashboard") ?>; action-uri=<?= url::site("admin"); ?>; icon-uri=favicon.ico" />
+<? endif; ?>
+<!-- Internet Explorer 9 Meta tags : End -->
+
+<link rel="shortcut icon" href="<?= $theme->favicon ?>" type="image/x-icon" />
+<? if ($theme->appletouchicon): ?>
+<link rel="apple-touch-icon" href="<?= $theme->appletouchicon; ?>"/>
+<? endif; ?>
+<?= $theme->script("json2-min.js") ?>
+<?= $theme->script("jquery.js") ?>
+<?= $theme->script("jquery.form.js") ?>
+<?= $theme->script("jquery-ui.js") ?>
+<?= $theme->script("gallery.common.js") ?>
+<? /* MSG_CANCEL is required by gallery.dialog.js */ ?>
+<script type="text/javascript">
+  var MSG_CANCEL = <?= t('Cancel')->for_js() ?>;
+</script>
+<?= $theme->script("gallery.ajax.js"); ?>
+<?= $theme->script("gallery.dialog.js"); ?>
+
+<? /* These are page specific but they get combined */ ?>
+<? if ($theme->page_subtype == "photo"): ?>
+<?=  $theme->script("jquery.scrollTo.js"); ?>
+<? elseif ($theme->page_subtype == "movie"): ?>
+<?=  $theme->script("flowplayer.js") ?>
+<? endif ?>
+
+<?= $theme->head() ?>
+
+<? // Theme specific CSS/JS goes last so that it can override module CSS/JS ?>
+<?= $theme->theme_js_inject(); ?>
+<?= $theme->theme_css_inject(); ?>
+<?= $theme->get_combined("css");          // LOOKING FOR YOUR CSS? It's all been combined into the link ?>
+<?= $theme->custom_css_inject(TRUE); ?>
+<?= $theme->get_combined("script")        // LOOKING FOR YOUR JAVASCRIPT? It's all been combined into the link ?>
+
+<? if ($theme->thumb_inpage): ?>
+<style type="text/css"> 
+  #g-column-bottom #g-thumbnav-block, #g-column-top #g-thumbnav-block { display: none; } 
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position == "bar")): ?>
+  html { margin-top: 30px !important; }
+<? endif; ?>
+</style>
+<? endif; ?>
+</head>
+<? if ($theme->item()):
+     $item = $theme->item();
+   else:
+     $item = item::root();
+   endif; ?>                             
+<body <?= $theme->body_attributes() ?><?= ($theme->show_root_page)? ' id="g-rootpage"' : null; ?> <?= $theme->get_bodyclass(); ?>>
+<?= $theme->page_top() ?>
+<?= $theme->site_status() ?>
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position == "bar")): ?>
+  <div id="g-site-menu" class="g-<?= $theme->mainmenu_position; ?>">
+  <?= $theme->site_menu($theme->item() ? "#g-item-id-{$theme->item()->id}" : "") ?>
+  </div>
+<? endif; ?>
+<div id="g-header">
+  <?= $theme->header_top() ?>
+<? if ($theme->viewmode != "mini"): ?>
+<? if ($header_text = module::get_var("gallery", "header_text")): ?>
+<span id="g-header-text"><?=  $theme->bb2html($header_text, 1) ?></span>
+<? else: ?>
+  <a id="g-logo" href="<?= item::root()->url() ?><?= ($theme->allow_root_page)? $theme->permalinks["root"] : null; ?>" title="<?= t("go back to the Gallery home")->for_html_attr() ?>">
+    <img alt="<?= t("Gallery logo: Your photos on your web site")->for_html_attr() ?>" src="<?= $theme->logopath ?>" />
+  </a>
+<?   endif; ?>
+<? endif; ?>
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position != "bar")): ?>
+  <div id="g-site-menu" class="g-<?= $theme->mainmenu_position; ?>">
+  <?= $theme->site_menu($theme->item() ? "#g-item-id-{$theme->item()->id}" : "") ?>
+  </div>
+<? endif ?>
+
+  <?= $theme->messages() ?>
+<?= $theme->header_bottom() ?>
+
+<? if ($theme->loginmenu_position == "header"): ?>
+  <?= $theme->user_menu() ?>
+<? endif ?>
+<? if (empty($parents)): ?>
+<?= $theme->breadcrumb_menu($theme, null); ?>
+<? else: ?>
+    <?= $theme->breadcrumb_menu($theme, $parents); ?>
+  <? endif; ?>
+<?= $theme->custom_header(); ?>
+</div>
+<? if (($theme->page_subtype != "login") and ($theme->page_subtype != "reauthenticate") and ($theme->sidebarvisible == "top")): ?>
+<div id="g-column-top">
+  <?= new View("sidebar.html") ?>
+</div>
+<? endif; ?>
+<div id="g-main">
+  <div id="g-main-in">
+    <? if (!$theme->show_root_page): ?>
+    <?= $theme->sidebar_menu($item->url()) ?>
+    <div id="g-view-menu" class="g-buttonset<?= ($theme->sidebarallowed!="any")? " g-buttonset-shift" : null; ?>">
+    <? if ($page_subtype == "album"):?>
+      <?= $theme->album_menu() ?>
+    <? elseif ($page_subtype == "photo") : ?>
+      <?= $theme->photo_menu() ?>
+    <? elseif ($page_subtype == "movie") : ?>
+      <?= $theme->movie_menu() ?>
+    <? elseif ($page_subtype == "tag") : ?>
+      <?= $theme->tag_menu() ?>
+    <? endif ?>
+    </div>
+    <? endif; ?>
+  <? switch ($theme->sidebarvisible):
+       case "left":
+         echo '<div id="g-column-left">';
+         $closediv = TRUE;
+         break;
+       case "none":
+     case "top":
+       case "bottom":
+         if (($theme->thumb_inpage) and ($page_subtype == "photo")):
+           echo '<div id="g-column-right">';
+           $closediv = TRUE;
+         else:
+           $closediv = FALSE;
+         endif;
+         break;
+       default:
+         echo '<div id="g-column-right">';
+         $closediv = TRUE;
+         break;
+   endswitch; ?>
+<? if (($theme->page_subtype != "login") and ($theme->page_subtype != "reauthenticate")): ?>
+<?   if (($theme->sidebarvisible == "none") or ($theme->sidebarvisible == "bottom") or ($theme->sidebarvisible == "top")): ?>
+<?     if (($theme->thumb_inpage) and ($page_subtype == "photo")): ?>
+<?=      '<div class="g-toolbar"><h1>&nbsp;</h1></div>'; ?>
+<?=      $theme->get_block_html("thumbnav"); ?>
+<?     endif; ?>
+<?   else: ?>
+<?=    new View("sidebar.html") ?>
+<?   endif; ?>
+<? endif ?>
+<?= ($closediv)? "</div>" : null; ?>
+
+<? switch ($theme->sidebarvisible):
+     case "left":
+       echo '<div id="g-column-centerright">';
+       break;
+     case "none":
+     case "top":
+     case "bottom":
+       if (($theme->thumb_inpage) and ($page_subtype == "photo")):
+         echo '<div id="g-column-centerleft">';
+       else:
+         echo '<div id="g-column-centerfull">';
+       endif;
+       break;
+     default:
+       echo '<div id="g-column-centerleft">';
+       break;
+   endswitch;
+
+   if ($theme->show_root_page):
+     echo new View("rootpage.html");
+   else:
+     echo $content;
+   endif; ?>
+    </div> 
+  </div>
+</div>
+<? if (($theme->page_subtype != "login") and ($theme->page_subtype != "reauthenticate") and ($theme->sidebarvisible == "bottom")): ?>
+<div id="g-column-bottom">
+  <?= new View("sidebar.html") ?>
+</div>
+<? endif; ?>
+<div id="g-footer">
+<? if ($theme->viewmode != "mini"): ?>
+<?= $theme->footer() ?>
+<? if ($footer_text = module::get_var("gallery", "footer_text")): ?>
+<span id="g-footer-text"><?=  $theme->bb2html($footer_text, 1) ?></span>
+<? endif ?>
+  <?= $theme->credits() ?>
+  <ul id="g-footer-rightside"><li><?= $theme->copyright ?></li></ul>
+<? if ($theme->loginmenu_position == "default"): ?>
+  <?= $theme->user_menu() ?>
+<?   endif; ?>
+<? endif; ?>
+<?= $theme->custom_footer(); ?>
+</div>
+<?= $theme->page_bottom() ?>
+</body>
+</html>
diff --git a/themes/greydragon_old/views/dynamic.html.php b/themes/greydragon_old/views/dynamic.html.php
new file mode 100644
index 0000000..a749d1c
--- /dev/null
+++ b/themes/greydragon_old/views/dynamic.html.php
@@ -0,0 +1,38 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<? if (!isset($title)):
+    $title = "";
+   endif;
+?>
+<div id="g-album-header">
+  <div id="g-album-header-buttons">
+    <?= $theme->dynamic_top() ?>
+  </div>
+  <h1><?= html::clean($title) ?></h1>
+</div>
+<?= $theme->add_paginator("top"); ?>
+<div class="g-album-grid-container">
+<ul id="g-album-grid">
+  <? foreach ($children as $i => $child): ?>
+    <?= $theme->get_thumb_element($child) ?>
+  <? endforeach ?>
+</ul>
+</div>
+<?= $theme->dynamic_bottom() ?>
+<?= $theme->add_paginator("bottom"); ?>
diff --git a/themes/greydragon_old/views/exif_sidebar.html.php b/themes/greydragon_old/views/exif_sidebar.html.php
new file mode 100644
index 0000000..e31adf2
--- /dev/null
+++ b/themes/greydragon_old/views/exif_sidebar.html.php
@@ -0,0 +1,18 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
diff --git a/themes/greydragon_old/views/gd_admin_include.html.php b/themes/greydragon_old/views/gd_admin_include.html.php
new file mode 100644
index 0000000..73962cb
--- /dev/null
+++ b/themes/greydragon_old/views/gd_admin_include.html.php
@@ -0,0 +1,180 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<style>   
+  @import "<?= url::file("modules/greydragon/css/gd_common.css"); ?>";
+</style>
+
+<script>
+  $(document).ready( function() { 
+    $('form').submit( function() { $('input[type=submit]', this).attr('disabled', 'disabled'); });
+    
+    var objAutoUpdate = $('#g-autoupdate-config');
+    var objAutoHidden = $('input[name="g_auto_delay"]');
+    var objAutoEdit   = $('#g-auto-delay-edit');
+    function showSidebar(){ objAutoEdit.val(objAutoHidden.val());	objAutoUpdate.slideDown('fast', function() { objAutoUpdate.addClass('visible'); }); };
+    function hideSidebar(){ objAutoHidden.val(objAutoEdit.val());	objAutoUpdate.slideUp('fast',   function() { objAutoUpdate.removeClass('visible'); }); };
+
+		objAutoEdit.keyup( function() { objAutoHidden.val($(this).val());	});
+		objAutoEdit.keydown(function(event) {       
+			// Allow: backspace, delete, tab and escape 
+      if ( event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 ||  
+        // Allow: Ctrl+A 
+        (event.keyCode == 65 && event.ctrlKey === true) ||  
+        // Allow: home, end, left, right 
+        (event.keyCode >= 35 && event.keyCode <= 39)) { 
+          // let it happen, don't do anything 
+          return; 
+      } else { 
+        // Ensure that it is a number and stop the keypress 
+        if ((event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105 )) { 
+          event.preventDefault();  
+        }    
+      } 
+    }); 
+ 
+    $('.g-link-autoupdate').click(function(e){ e.preventDefault(); if ( objAutoUpdate.hasClass('visible') ){ hideSidebar(); } else { showSidebar(); }});
+  });
+</script>
+
+<?
+
+function isCurlInstalled() {
+	if (in_array('curl', get_loaded_extensions())) {
+		return true;
+	}	else {
+		return false;
+	}
+} 
+
+// -1 - cannot get version info
+// 0 - current
+// + - newer is avaialble, version is returned
+function checkVersionInfo($downloadid, $version) {
+  if (!isset($downloadid)):
+    return -1;
+  endif;
+
+  try {                                                                                        
+    $call = "http://blog.dragonsoft.us/downloadversion/" . $downloadid; 
+    $ch = curl_init();
+    curl_setopt($ch, CURLOPT_URL, $call);
+    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
+    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
+    curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
+    $output=curl_exec($ch);
+    $json = json_decode($output);
+  
+    if ($json->id == $downloadid):
+      $newversion = $json->version;
+      if ($json->version > $version):
+        return $json->version;
+      else:
+        return 0;
+      endif;      
+    else:
+      return -1;
+    endif;
+  } catch (Exception $e) {
+    return -1;
+  }
+}
+
+if ($is_module):
+  $admin_info = new ArrayObject(parse_ini_file(MODPATH   . $name . "/module.info"), ArrayObject::ARRAY_AS_PROPS);
+  $version = number_format($admin_info->version / 10, 1, '.', '');
+  $lastupdate = module::get_var($name, "last_update", time());
+	$checkInDays = module::get_var($name, "auto_delay", 30);
+else:
+  $admin_info = new ArrayObject(parse_ini_file(THEMEPATH . $name . "/theme.info"), ArrayObject::ARRAY_AS_PROPS);
+  $version = $admin_info->version;
+  $lastupdate = module::get_var("th_" . $name, "last_update", time());
+	$checkInDays = module::get_var("th_" . $name, "auto_delay", 30);
+endif;
+
+if (isCurlInstalled() && ($checkInDays > 0) && ((time() - $lastupdate) > ($checkInDays * 24 * 60 * 60))): // Check version every N days
+  $admin_info2 = new ArrayObject(parse_ini_file(MODPATH   . "greydragon/module.info"), ArrayObject::ARRAY_AS_PROPS);
+  $version2 = number_format($admin_info2->version / 10, 1, '.', '');
+  
+  $versionCheck  = checkVersionInfo($downloadid, $version);
+  $versionCheck2 = checkVersionInfo(15, $version2);
+  
+  if (($versionCheck == 0) && ($versionCheck2 == 0)):
+    if ($is_module):
+      module::set_var($name, "last_update", time());
+    else:
+      module::set_var("th_" . $name, "last_update", time());
+    endif;
+  endif;
+else:
+  $versionCheck = 0;
+  $versionCheck2 = 0;
+endif;
+?>
+
+<div id="gd-admin-header">
+  <div id="gd-admin-title"><?= t($admin_info->name) ?> - <?= $version ?></div>
+  <div id="gd-admin-hlinks">
+    <ul style="float: right;"><li><a href="http://blog.dragonsoft.us/gallery-3/" target="_blank"><?= t("Home") ?></a>&nbsp;|&nbsp;</li>
+      <? if (isset($admin_info->discuss_url)): ?>
+      <li><a href="<?= $admin_info->discuss_url;  ?>" target="_blank"><?= t("Support") ?></a>&nbsp;|&nbsp;</li>
+      <? endif; ?>
+      <? if (isset($admin_info->info_url)): ?>
+	      <li><a href="<?= $admin_info->info_url; ?>" target="_blank"><?= t("Download") ?></a>&nbsp;|&nbsp;</li>
+      <? endif; ?>
+      <? if (isset($admin_info->vote)): ?>
+	      <li><a href="<?= $admin_info->vote;     ?>" target="_blank"><?= t("Vote") ?></a>&nbsp;|&nbsp;</li>
+      <? endif; ?>
+      <li><a href="http://twitter.com/greydragon_th" target="_blank" title="<?= t("Follow Us on Twitter") ?>"><?= t("Follow Us") ?></a>&nbsp;|&nbsp;</li>
+      <li><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9MWBSVJMWMJEU" target="_blank" ><?= t("Coffee Fund") ?></a>&nbsp;|&nbsp;</li>
+      <li><a href="#" class="g-link-autoupdate" <?= (isCurlInstalled())? null : "disabled=\"disabled\""; ?> ><?= t("Auto Update"); ?></a></li>
+    </ul>
+  </div>
+</div>
+<div id="g-autoupdate-config">
+  <ul><li><?= t("Check every"); ?>&nbsp;&nbsp;</li>
+    <li><input id="g-auto-delay-edit" type="text" size="2" value="30"></li>
+    <li><?=t("days (set to 0 to disable)"); ?></li>
+<? if (($versionCheck == 0) && ($versionCheck2 == 0)): ?>
+    <li>&nbsp;&nbsp;|&nbsp;&nbsp;<?= t("Last check:"); ?>&nbsp;<?= date("Y-m-d H:i:s", $lastupdate); ?></li>
+<? endif; ?>  
+  </ul>
+</div>
+
+<? if ($versionCheck == -1): ?>
+  <div id="gd-admin-version"><?= t("Version check is incomplete. No version information has been found."); ?> <?= $versionCheck; ?> : <?= $downloadid; ?></div>
+<? elseif ($versionCheck == 0): ?>
+<? else: ?>
+  <div id="gd-admin-version"><?= t("Newer version") ?> <?= $versionCheck; ?> <?= t("is available. Click Download link for more info.") ?></div>
+<? endif; ?>
+<? if (($versionCheck2 == -1) || ($versionCheck2 == 0)): ?>
+<? else: ?>
+  <div id="gd-admin-version-2"><?= t("Newer version") ?> <?= $versionCheck2; ?> <?= t("of GreyDragon Shared Module is available. Click") . ' <a href="http://codex.gallery2.org/Gallery3:Modules:greydragon" target="_blank">' . t("here") . '</a> ' . t("for more info.") ?></div>
+<? endif; ?>
+<div id="g-admin-container">
+<? if (isset($help)): ?>
+	<div class="column1">
+	  <?= $form ?>
+	</div>
+	<div class="column2">
+    <?= $help ?>
+	</div>
+<? else: ?>
+  <?= $form ?>
+<? endif; ?>
+</div>
diff --git a/themes/greydragon_old/views/info_block.html.php b/themes/greydragon_old/views/info_block.html.php
new file mode 100644
index 0000000..16c7015
--- /dev/null
+++ b/themes/greydragon_old/views/info_block.html.php
@@ -0,0 +1,29 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<? if (array_key_exists("description", $metadata)): ?>
+<?   $metadata["description"]["value"] = $theme->bb2html($metadata["description"]["value"], 1) ?>
+<? endif; ?>
+
+<ul class="g-metadata">
+  <? foreach($metadata as $info): ?>
+  <li>
+    <strong class="caption"><?= $info["label"] ?></strong> <?= $info["value"] ?>
+  </li>
+  <? endforeach; ?>
+</ul>
diff --git a/themes/greydragon_old/views/movie.html.php b/themes/greydragon_old/views/movie.html.php
new file mode 100644
index 0000000..5043f6f
--- /dev/null
+++ b/themes/greydragon_old/views/movie.html.php
@@ -0,0 +1,38 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<div id="g-item">
+  <?= $theme->photo_top() ?>
+
+  <div id="g-info">
+    <h1><?= $theme->get_item_title($item, TRUE); ?></h1>
+    <div class="g-hideitem"><?= $theme->bb2html(html::purify($item->description), 1) ?></div>
+  </div>
+
+  <?= $theme->add_paginator("top"); ?>
+
+  <div id="g-movie">
+    <?= $theme->resize_top($item) ?>
+    <?=  $item->movie_img(array("class" => "g-movie", "id" => "g-item-id-{$item->id}")); ?>
+    <?= $theme->resize_bottom($item) ?>
+  </div>
+
+  <?= $theme->add_paginator("bottom"); ?>
+
+  <?= $theme->photo_bottom() ?>
+</div>
diff --git a/themes/greydragon_old/views/no_sidebar.html.php b/themes/greydragon_old/views/no_sidebar.html.php
new file mode 100644
index 0000000..eac82d6
--- /dev/null
+++ b/themes/greydragon_old/views/no_sidebar.html.php
@@ -0,0 +1,19 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<!-- No blocks -->
diff --git a/themes/greydragon_old/views/page.html.php b/themes/greydragon_old/views/page.html.php
new file mode 100644
index 0000000..6c5ff65
--- /dev/null
+++ b/themes/greydragon_old/views/page.html.php
@@ -0,0 +1,259 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+
+<!DOCTYPE html >
+<? $theme->load_sessioninfo(); ?>
+<html <?= $theme->html_attributes() ?> xml:lang="en" lang="en" <?= ($theme->is_rtl)? "dir=rtl" : null; ?> >
+<?
+  $item = $theme->item();
+  if (($theme->enable_pagecache) and (isset($item))):
+    // Page will expire in 60 seconds
+    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 60).'GMT');  
+    header("Cache-Control: public");
+    header("Cache-Control: post-check=3600, pre-check=43200", false);
+    header("Content-Type: text/html; charset=UTF-8");
+    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
+  endif;
+?>
+<!-- <?= $theme->themename ?> v.<?= $theme->themeversion ?> (<?= $theme->colorpack ?> : <?= $theme->framepack ?>) - Copyright (c) 2009-2012 Serguei Dosyukov - All Rights Reserved -->
+<!-- <?= $theme->page_subtype ?> -->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+<? $theme->start_combining("script,css") ?>
+<? if ($page_title): ?>
+<?   $_title = $page_title ?> 
+<? else: ?>
+<?   if ($theme->item()): ?>
+<?     $_title = $theme->get_item_title($theme->item()); ?>
+<?   elseif ($theme->tag()): ?>
+<?     $_title = t("Photos tagged with %tag_title", array("tag_title" => $theme->bb2html($theme->tag()->name, 2))) ?>
+<?   else: /* Not an item, not a tag, no page_title specified.  Help! */ ?>
+<?     $_title = $theme->bb2html(item::root()->title, 2); ?>
+<?   endif ?>
+<? endif ?>
+<title><?= $_title ?></title>
+<? if ($theme->disable_seosupport): ?>
+<meta name="robots" content="noindex, nofollow, noarchive" />
+<meta name="googlebot" content="noindex, nofollow, noarchive, nosnippet, noodp, noimageindex, notranslate" />
+<meta name="slurp" content="noindex, nofollow, noarchive, nosnippet, noodp, noydir" />
+<meta name="msnbot" content="noindex, nofollow, noarchive, nosnippet, noodp" />
+<meta name="teoma" content="noindex, nofollow, noarchive" />
+<? endif; ?>
+
+<!-- Internet Explorer 9 Meta tags : Start -->
+<meta name="application-name" content="<?= $_title; ?>" />
+<meta name="msapplication-tooltip" content="<?= t("Start"); ?> <?= $_title; ?>" />
+<meta name="msapplication-starturl" content="<?= item::root()->url() ?>" />                                                     
+<? if ($theme->allow_root_page): ?>
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Page") ?>; action-uri=<?= item::root()->url(); ?><?= $theme->permalinks["root"]; ?>; icon-uri=favicon.ico" />
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Album") ?>; action-uri=<?= item::root()->url(); ?><?= $theme->permalinks["enter"]; ?>; icon-uri=favicon.ico" />
+<? else: ?>
+<meta name="msapplication-task" content="name=<?= t("Gallery") ?>: <?= t("Root Album") ?>; action-uri=<?= item::root()->url(); ?>; icon-uri=favicon.ico" />
+<? endif; ?>
+<? if (identity::active_user()->admin): ?>
+<meta name="msapplication-task-separator" content="gallery3-greydragon" />
+<meta name="msapplication-task" content="name=<?= t("Admin") ?>: <?= t("Dashboard") ?>; action-uri=<?= url::site("admin"); ?>; icon-uri=favicon.ico" />
+<? endif; ?>
+<!-- Internet Explorer 9 Meta tags : End -->
+<link rel="shortcut icon" href="<?= $theme->favicon ?>" type="image/x-icon" />
+<? if ($theme->appletouchicon): ?>
+<link rel="apple-touch-icon" href="<?= $theme->appletouchicon; ?>"/>
+<? endif; ?>
+<?= $theme->script("json2-min.js"); ?>
+<?= $theme->script("jquery.js"); ?>
+<?= $theme->script("jquery.form.js") ?>
+<?= $theme->script("jquery-ui.js") ?>
+<?= $theme->script("gallery.common.js") ?>
+<? /* MSG_CANCEL is required by gallery.dialog.js */ ?>
+<script type="text/javascript">
+  var MSG_CANCEL = <?= t('Cancel')->for_js() ?>;
+</script>
+
+<?= $theme->script("gallery.dialog.js"); ?>
+
+<? /* These are page specific but they get combined */ ?>
+<? if ($theme->page_subtype == "photo"): ?>
+<?=  $theme->script("jquery.scrollTo.js"); ?>
+<? elseif ($theme->page_subtype == "movie"): ?>
+<?=  $theme->script("flowplayer.js") ?>
+<? endif ?>
+
+<?= $theme->head() ?>
+
+<? // Theme specific CSS/JS goes last so that it can override module CSS/JS ?>
+<?= $theme->theme_js_inject(); ?>
+<?= $theme->theme_css_inject(); ?>
+<?= $theme->get_combined("css");          // LOOKING FOR YOUR CSS? It's all been combined into the link ?>
+<?= $theme->custom_css_inject(TRUE); ?>
+<?= $theme->get_combined("script")        // LOOKING FOR YOUR JAVASCRIPT? It's all been combined into the link ?>
+
+<? if ($theme->thumb_inpage): ?>
+<style type="text/css"> 
+  #g-column-bottom #g-thumbnav-block, #g-column-top #g-thumbnav-block { display: none; } 
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position == "bar")): ?>
+  html { margin-top: 30px !important; }
+<? endif; ?>
+</style>
+<? endif; ?>
+</head>
+<? if ($theme->item()):
+     $item = $theme->item();
+   else:
+     $item = item::root();
+   endif; ?>
+<body <?= $theme->body_attributes() ?><?= ($theme->show_root_page)? ' id="g-rootpage"' : null; ?> <?= $theme->get_bodyclass(); ?>>
+<?= $theme->page_top() ?>                               
+<?= $theme->site_status() ?>
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position == "bar")): ?>
+  <div id="g-site-menu" class="g-<?= $theme->mainmenu_position; ?>">
+  <?= $theme->site_menu($theme->item() ? "#g-item-id-{$theme->item()->id}" : "") ?>
+  </div>
+<? endif; ?>
+<div id="g-header">
+<?= $theme->header_top() ?>
+<? if ($theme->viewmode != "mini"): ?>
+<?   if ($header_text = module::get_var("gallery", "header_text")): ?>
+<span id="g-header-text"><?=  $theme->bb2html($header_text, 1) ?></span>
+<?   else: ?>                                                                         
+  <a id="g-logo" href="<?= item::root()->url() ?><?= ($theme->allow_root_page)? $theme->permalinks["root"] : null; ?>" title="<?= t("go back to the Gallery home")->for_html_attr() ?>">
+    <img alt="<?= t("Gallery logo: Your photos on your web site")->for_html_attr() ?>" src="<?= $theme->logopath ?>" />
+  </a>
+<?   endif; ?>
+<? endif; ?>
+<? if (((!$user->guest) or ($theme->show_guest_menu)) and ($theme->mainmenu_position != "bar")): ?>
+  <div id="g-site-menu" class="g-<?= $theme->mainmenu_position; ?>">
+  <?= $theme->site_menu($theme->item() ? "#g-item-id-{$theme->item()->id}" : "") ?>
+  </div>
+<? endif ?>
+
+<?= $theme->messages() ?>
+<?= $theme->header_bottom() ?>
+
+<? if ($theme->loginmenu_position == "header"): ?>
+<?=  $theme->user_menu() ?>
+<? endif ?>
+<? if (empty($parents)): ?>
+<?= $theme->breadcrumb_menu($theme, null); ?>
+<? else: ?>
+<?= $theme->breadcrumb_menu($theme, $parents); ?>
+<? endif; ?>
+<?= $theme->custom_header(); ?>
+</div>
+<? if (($theme->page_subtype != "login") and ($theme->page_subtype != "reauthenticate") and ($theme->sidebarvisible == "top")): ?>
+<div id="g-column-top">
+  <?= new View("sidebar.html") ?>
+</div>
+<? endif; ?>
+<div id="g-main">
+  <div id="g-main-in">
+<?  if (!$theme->show_root_page): ?>
+    <?= $theme->sidebar_menu($item->url()) ?>
+    <div id="g-view-menu" class="g-buttonset<?= ($theme->sidebarallowed != "any")? " g-buttonset-shift" : null; ?>">
+<?    if ($page_subtype == "album"): ?>
+      <?= $theme->album_menu() ?>
+<?    elseif ($page_subtype == "photo") : ?>
+      <?= $theme->photo_menu() ?>
+<?    elseif ($page_subtype == "movie") : ?>
+      <?= $theme->movie_menu() ?>
+<?    elseif ($page_subtype == "tag") : ?>
+      <?= $theme->tag_menu() ?>
+<?    endif ?>
+    </div>
+<?  endif; ?>
+<? switch ($theme->sidebarvisible):
+     case "left":
+       echo '<div id="g-column-left">';
+       $closediv = TRUE;
+       break;
+     case "none":
+     case "top":
+     case "bottom":
+       if (($theme->thumb_inpage) and ($page_subtype == "photo")):
+         echo '<div id="g-column-right">';
+         $closediv = TRUE;
+       else:
+         $closediv = FALSE;
+       endif;
+       break;
+     default:
+       echo '<div id="g-column-right">';
+       $closediv = TRUE;
+       break;
+   endswitch; ?>
+<? if (($theme->page_subtype != "login") && ($theme->page_subtype != "reauthenticate")): ?>
+<?   if (($theme->sidebarvisible == "none") || ($theme->sidebarvisible == "bottom") || ($theme->sidebarvisible == "top")): ?>
+<?     if (($theme->thumb_inpage) and ($page_subtype == "photo")): ?>
+<?=      '<div class="g-toolbar"><h1>&nbsp;</h1></div>'; ?>
+<?=      $theme->get_block_html("thumbnav"); ?>
+<?     endif; ?>
+<?   else: ?>
+<?=    new View("sidebar.html") ?>
+<?   endif; ?>
+<? endif ?>
+<?= ($closediv)? "</div>" : null; ?>
+
+<? switch ($theme->sidebarvisible):
+     case "left":
+       echo '<div id="g-column-centerright">';
+       break;
+     case "none":
+     case "top":
+     case "bottom":
+       if (($theme->thumb_inpage) and ($page_subtype == "photo")):
+         echo '<div id="g-column-centerleft">';
+       else:
+         echo '<div id="g-column-centerfull">';
+       endif;
+       break;
+     default:
+       echo '<div id="g-column-centerleft">';
+       break;
+   endswitch;
+
+   if ($theme->show_root_page):
+     echo new View("rootpage.html");
+   else:
+     echo $content;
+   endif; ?>
+    </div> 
+  </div>
+</div>
+<? if (($theme->page_subtype != "login") and ($theme->page_subtype != "reauthenticate") and ($theme->sidebarvisible == "bottom")): ?>
+<div id="g-column-bottom">
+  <?= new View("sidebar.html") ?>
+</div>
+<? endif; ?>
+<div id="g-footer">
+<? if ($theme->viewmode != "mini"): ?>
+<?=  $theme->footer() ?>
+<?   if ($footer_text = module::get_var("gallery", "footer_text")): ?>
+<span id="g-footer-text"><?=  $theme->bb2html($footer_text, 1) ?></span>
+<?   endif ?>
+  <?= $theme->credits() ?>
+  <ul id="g-footer-rightside"><li><?= $theme->copyright ?></li></ul>
+<?   if ($theme->loginmenu_position == "default"): ?>
+  <?= $theme->user_menu() ?>
+<?   endif; ?>
+<? endif; ?>
+<?= $theme->custom_footer(); ?>
+</div>
+<?= $theme->page_bottom() ?>
+</body>
+</html>
diff --git a/themes/greydragon_old/views/paginator.html.php b/themes/greydragon_old/views/paginator.html.php
new file mode 100644
index 0000000..5d7a7d6
--- /dev/null
+++ b/themes/greydragon_old/views/paginator.html.php
@@ -0,0 +1,194 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+// This is a generic paginator for album, photo and movie pages.  Depending on the page type,
+// there are different sets of variables available.  With this data, you can make a paginator
+// that lets you say "You're viewing photo 5 of 35", or "You're viewing photos 10 - 18 of 37"
+// for album views.
+//
+// Available variables for all page types:
+//   $page_type               - "collection", "item", or "other"
+//   $page_subtype            - "album", "movie", "photo", "tag", etc.
+//   $previous_page_url       - the url to the previous page, if there is one
+//   $next_page_url           - the url to the next page, if there is one
+//   $total                   - the total number of photos in this album
+//
+// Available for the "collection" page types:
+//   $page                    - what page number we're on
+//   $max_pages               - the maximum page number
+//   $page_size               - the page size
+//   $first_page_url          - the url to the first page, or null if we're on the first page
+//   $last_page_url           - the url to the last page, or null if we're on the last page
+//   $first_visible_position  - the position number of the first visible photo on this page
+//   $last_visible_position   - the position number of the last visible photo on this page
+//
+// Available for "item" page types:
+//   $position                - the position number of this photo
+//
+?>
+
+<?
+  $_pagelist = array();
+
+  switch ($page_type) {
+    case "collection":
+      if (isset($item)):
+        $parent = $item->parent();
+      endif;
+      $current_page = $page;
+      $total_pages = $max_pages;
+      // Prepare page url list
+      for ($i = 1; $i <= $total_pages; $i++):
+        $_pagelist[$i] = url::site(url::merge(array("page" => $i)));
+      endfor;
+      break;
+    case "item":
+      if (isset($item)):
+        $parent = $item->parent();
+      endif;
+
+      if (isset($position)):
+        $current_page = $position; 
+      else:
+        $current_page = 1;
+      endif;
+
+      $total_pages = $total;
+      if (isset($parent)):
+        $siblings = $parent->children();
+        for ($i = 1; $i <= $total; $i++):
+          $_pagelist[$i] = $siblings[$i-1]->url();
+        endfor;
+      endif;
+      break;
+    default:
+      $current_page = 1;
+      $total_pages = 1;
+      $_pagelist[1] = url::site();
+      break;
+  }
+
+  if ($total_pages <= 1):
+    $pagination_msg = "&nbsp;";
+  else:
+    $pagination_msg = t("Page:") . ' ';
+    if ($total_pages < 13):
+      for ($i = 1; $i <= $total_pages; $i++):
+        if ($i == $current_page):
+          $pagination_msg .= '<span>' . t($i) . '</span>';
+        else:                                                                
+          $pagination_msg .= '<span><a href="' . $_pagelist[$i] . '" title="' . t("Page") . ' ' . t($i) . '">' . t($i) . '</a></span>';
+        endif;
+        if ($i < $total_pages):
+          $pagination_msg .= '&middot;'; 
+        endif;
+      endfor;
+    elseif ($current_page < 9):
+      for ($i = 1; $i <= 10; $i++):
+        if ($i == $current_page): 
+          $pagination_msg .= '<span>' . t($i) . '</span>';
+        else:
+          $pagination_msg .= '<span><a href="' . $_pagelist[$i] . '" title="' . t("Page") . ' ' . t($i) . '">' . t($i) . '</a></span>';
+        endif;
+        if ($i < 10):
+          $pagination_msg .= '&middot;'; 
+        endif;
+      endfor;
+      
+      $pagination_msg .= '&hellip;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[$total_pages - 1] . '" title="' . t("Page") . ' ' . t($total_pages - 1) . '">' . t($total_pages - 1) . '</a></span>';
+      $pagination_msg .= '&middot;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[$total_pages] . '" title="' . t("Page") . ' ' . t($total_pages) . '">' . t($total_pages) . '</a></span>';
+
+    elseif ($current_page > $total_pages - 8):
+      $pagination_msg .= '<span><a href="' . $_pagelist[1] . '" title="' . t("Page") . ' ' . t(1) . '">' . t(1) . '</a></span>';
+      $pagination_msg .= '&middot;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[2] . '" title="' . t("Page") . ' ' . t(2) . '">' . t(2) . '</a></span>';
+      $pagination_msg .= '&hellip;';
+
+      for ($i = $total_pages - 9; $i <= $total_pages; $i++):
+        if ($i == $current_page): 
+          $pagination_msg .= '<span>' . t($i) . '</span>';
+        else:
+          $pagination_msg .= '<span><a href="' . $_pagelist[$i] . '" title="' . t("Page") . ' ' . t($i) . '">' . t($i) . '</a></span>';
+        endif;
+        if ($i < $total_pages):
+          $pagination_msg .= '&middot;';
+        endif;
+      endfor;
+
+    else:
+      $pagination_msg .= '<span><a href="' . $_pagelist[1] . '" title="' . t("Page") . ' ' . t(1) . '">' . t(1) . '</a></span>';
+      $pagination_msg .= '&middot;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[2] . '" title="' . t("Page") . ' ' . t(2) . '">' . t(2) . '</a></span>';
+      $pagination_msg .= '&hellip;';
+
+      for ($i = $current_page - 5; $i <= $current_page + 5; $i++):
+        if ($i == $current_page): 
+          $pagination_msg .= '<span>' . t($i) . '</span>';
+        else:
+          $pagination_msg .= '<span><a href="' . $_pagelist[$i] . '" title="' . t("Page") . ' ' . t($i) . '">' . t($i) . '</a></span>';
+        endif;
+        if ($i < $current_page + 5):
+          $pagination_msg .= '&middot;';
+        endif;
+      endfor;
+
+      $pagination_msg .= '&hellip;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[$total_pages - 1] . '" title="' . t("Page") . ' ' . t($total_pages - 1) . '">' . t($total_pages - 1) . '</a></span>';
+      $pagination_msg .= '&middot;';
+      $pagination_msg .= '<span><a href="' . $_pagelist[$total_pages] . '" title="' . t("Page") . ' ' . t($total_pages) . '">' . t($total_pages) . '</a></span>';
+    endif;
+  endif; 
+?>
+
+<ul class="g-paginator">
+  <li class="g-pagination"><?= $pagination_msg ?></li>   
+  <li class="g-navigation">
+  <? if ($current_page > 1): ?>
+    <a title="<?= t("first") ?>" id="g-navi-first" href="<?= $_pagelist[1] ?>"><span class="ui-icon ui-icon-first">&nbsp;</span></a>
+  <? else: ?>
+    <span class="ui-icon ui-icon-first-d">&nbsp;</span>
+  <? endif ?>
+
+  <? if (isset($previous_page_url)): ?>
+    <a title="<?= t("previous") ?>" id="g-navi-prev" href="<?= $previous_page_url ?>"><span class="ui-icon ui-icon-prev">&nbsp;</span></a>
+  <? else: ?>
+    <span class="ui-icon ui-icon-prev-d">&nbsp;</span>
+  <? endif ?>
+
+  <? if (isset($parent)): ?>
+    <a title="<?= t("up") ?>" id="g-navi-parent" href="<?= $parent->url("show={$item->id}"); ?>"><span class="ui-icon ui-icon-parent">&nbsp;</span></a>
+  <? else: ?>
+    <span class="ui-icon ui-icon-parent-d">&nbsp;</span>
+  <? endif ?>
+
+  <? if (isset($next_page_url)): ?>
+    <a title="<?= t("next") ?>" class="ui-right" id="g-navi-next" href="<?= $next_page_url ?>"><span class="ui-icon ui-icon-next">&nbsp;</span></a>
+  <? else: ?>
+    <span class="ui-icon ui-icon-next-d">&nbsp;</span>
+  <? endif ?>
+
+  <? if ($current_page < $total_pages): ?>
+      <a title="<?= t("last") ?>" class="ui-right" id="g-navi-last" href="<?= $_pagelist[$total_pages] ?>"><span class="ui-icon ui-icon-last">&nbsp;</span></a>
+  <? else: ?>
+    <span class="ui-icon ui-icon-last-d">&nbsp;</span>
+  <? endif ?>
+  </li>
+</ul>
\ No newline at end of file
diff --git a/themes/greydragon_old/views/photo.html.php b/themes/greydragon_old/views/photo.html.php
new file mode 100644
index 0000000..453dd85
--- /dev/null
+++ b/themes/greydragon_old/views/photo.html.php
@@ -0,0 +1,124 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?
+  if ($theme->desc_allowbbcode):
+    $_description = $theme->bb2html($item->description, 1);
+  else:
+    $_description = nl2br(html::purify($item->description));
+  endif;
+
+  if ($theme->is_photometa_visible):
+    $_description .= '<ul class="g-metadata">' . $theme->thumb_info($item) . '</ul>';
+  endif;
+
+  switch ($theme->photo_popupbox):
+    case "preview":
+      $include_list = FALSE;
+      $include_single = TRUE;
+      break;
+    case "none":
+      $include_list = FALSE;
+      $include_single = FALSE;
+      break;
+    default:
+      $include_list = TRUE;
+      $include_single = TRUE;
+      break;
+  endswitch;
+?>  
+
+<div id="g-item">
+  <? $_title = $theme->get_item_title($item, TRUE); ?>
+  <div id="g-info">
+    <h1><?= $_title ?></h1>
+  </div>
+  <?= $theme->add_paginator("top", FALSE); ?>
+  <?= $theme->photo_top() ?>
+  <? if (($theme->photo_descmode == "top") and ($_description)): ?>
+    <div id="g-info"><div class="g-description"><?= $_description ?></div></div>
+  <? endif; ?>
+  <div id="g-photo">
+    <?= $theme->resize_top($item) ?>
+    <? $_resizewidth = $item->resize_width;
+       $siblings = $item->parent()->children(); ?>
+    <div class="g-resize" style="margin-left: -<?= intval($_resizewidth / 2); ?>px; ">
+    <? $script  = "<script type=\"text/javascript\">\n";
+       $script .= "$(document).ready(function() {\n";
+       $script .= "  if (document.images) {\n";
+       for ($i = 0; ($i <= count($siblings) - 1); $i++):
+         if ($siblings[$i]->rand_key == $item->rand_key): ?>
+           <a style="<?= ($siblings[$i]->rand_key == $item->rand_key)? "display: static;" : "display: none;"; ?>" title="<?= $theme->get_item_title($item); ?>" <?= ($include_single)? "class=\"g-sb-preview\"" : "target=_blank;"; ?> <?= ($include_list)? "rel=\"g-preview\"" : null; ?> href="<?= (access::can("view_full", $item))? $item->file_url() : $item->resize_url(); ?>">
+           <?= $item->resize_img(array("id" => "g-item-id-{$item->id}", "class" => "g-resize", "alt" => $_title)) ?>
+           </a>
+      <?  if ($i < count($siblings) - 1):
+            $script  .= "    var image_preload_n = new Image();\n    image_preload_n.src = \"" . $siblings[$i+1]->resize_url() . "\";\n"; 
+          endif;
+          if ($i > 0):
+            $script  .= "    var image_preload_p = new Image();\n    image_preload_p.src = \"" . $siblings[$i-1]->resize_url() . "\";\n"; 
+          endif;
+        else:
+        if ($include_list): ?>
+          <? if (!$siblings[$i]->is_album()): ?>
+          <a title="<?= $theme->get_item_title($siblings[$i]); ?>" class="g-sb-preview g-hide" rel="g-preview" href="<?= (access::can("view_full", $siblings[$i]))? $siblings[$i]->file_url() : $siblings[$i]->resize_url(); ?>">&nbsp;</a>
+          <? endif; ?>  
+        <? endif; ?>
+      <? endif; ?>
+    <? endfor; ?>
+    <? $script  .= "  }\n});\n</script>\n"; ?>
+    <? $_align = "";
+       $_more = FALSE;
+       if ($_description):
+         switch ($theme->photo_descmode):
+           case "overlay_top":
+             $_align = "g-align-top";
+             $_more = TRUE;
+             break;
+           case "overlay_bottom":
+             $_align = "g-align-bottom";
+             $_more = TRUE;
+             break;
+           case "overlay_top_s":
+             $_align = "g-align-top g-align-static";
+             break;
+           case "overlay_bottom_s":
+             $_align = "g-align-bottom g-align-static";
+             break;
+           default:
+             break;
+         endswitch;
+       endif; ?>
+  <?  if ($_align): ?>
+    <?  if ($_more): ?>
+      <span class="g-more <?= $_align ?>"><?= t("More") ?></span>
+    <? endif ?>
+      <div class="g-description <?= $_align; ?>" style="width: <?= $_resizewidth - 20; ?>px;" >
+        <strong><?= $_title ?></strong>
+        <?= $_description ?>
+      </div>
+    <? endif ?>
+    </div>
+    <?= $theme->resize_bottom($item) ?>
+  </div>
+  <? if (($theme->photo_descmode == "bottom") and ($_description)): ?>
+    <div id="g-info"><div class="g-description"><?= $_description ?></div></div>
+  <? endif; ?>
+  <?= $theme->add_paginator("bottom", FALSE); ?>
+  <?= $theme->photo_bottom() ?>
+</div>
+<?= $script ?>
\ No newline at end of file
diff --git a/themes/greydragon_old/views/rootpage.html.php b/themes/greydragon_old/views/rootpage.html.php
new file mode 100644
index 0000000..bcb5fa8
--- /dev/null
+++ b/themes/greydragon_old/views/rootpage.html.php
@@ -0,0 +1,59 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<? 
+  $link_url = item::root()->url();
+  if ($theme->allow_root_page):            
+    $link_url .= $theme->permalinks["enter"];
+  endif;
+  if ($theme->show_root_desc):
+  	if ($theme->root_description):
+  		$root_text = $theme->root_description;
+  	elseif (isset($item)):
+	    $root_text = $item->description;
+  	endif;
+	  if ($root_text): 
+	    ?><div id="g-rootpage-quote"><?= $theme->bb2html($root_text, 1); ?></div><?
+	  endif; 
+	endif;
+
+	$slideshow_list = $theme->get_slideshow_list();
+	$first = TRUE;
+?>
+<div id="g-rootpage-roll"<?= ($root_text)? null : ' class="g-full"'; ?>>
+	<span><a href="<?= $link_url ?>"><?= t("Click to Enter") ?></a></span>
+	<div id="g-rootpage-slideshow">
+  	<? foreach ($slideshow_list as $entry): ?>
+  		<? $attr = $entry["@attributes"]; ?>
+	  <div class="slider-item" style="width: <?= $attr['width']; ?>px; height: <?= $attr["height"]; ?>px; display: <?= ($first)? "block" : "none"; ?>; position: absolute; z-index: 10; opacity: <?= ($first)? "1" : "0"; ?>;">
+  	  <a href="<?= $link_url; ?>"><img width="<?= $attr["width"]; ?>" height="<?= $attr["height"]; ?>" alt="" src="<?= $attr["url"]; ?>" border="0"/></a>
+	  </div>
+		  <? $first = FALSE; ?>
+	  <? endforeach ?>
+	</div>	
+</div>
+<? if (count($slideshow_list) > 0): ?>
+<script type="text/javascript">
+  $(document).ready(function() {
+    $('#g-rootpage-slideshow').cycle({
+        fx: '<?= $theme->root_cyclemode; ?>'
+      , timeout: <?= $theme->root_delay * 1000; ?>
+    });
+  });
+</script>
+<? endif; ?>
\ No newline at end of file
diff --git a/themes/greydragon_old/views/rootpage.html.php_fix b/themes/greydragon_old/views/rootpage.html.php_fix
new file mode 100644
index 0000000..cfe61d2
--- /dev/null
+++ b/themes/greydragon_old/views/rootpage.html.php_fix
@@ -0,0 +1,46 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<? 
+  $link_url = item::root()->url();
+  if ($theme->allow_root_page):
+    $link_url .= $theme->permalinks["enter"];
+  endif;
+  if ($theme->show_root_desc):
+  	if ($theme->root_description):
+  		$root_text = $theme->root_description;
+  	elseif (isset($item)):
+	    $root_text = $item->description;
+  	endif;
+	  if ($root_text): 
+	    ?><div id="g-rootpage-quote"><?= $theme->bb2html($root_text, 1); ?></div><?
+	  endif; 
+	endif;
+?>
+<div id="g-rootpage-roll"<?= ($root_text)? null : ' class="g-full"'; ?>>
+<object type="application/x-shockwave-flash" data="<?= url::file("modules/imageblockex/player/minislideshow.swf"); ?>" width="100%" height="100%">
+<param name="movie" value="<?= url::file("modules/imageblockex/player/minislideshow.swf"); ?>" />
+<param name="FlashVars" value="xmlUrl=<?= $theme->root_feed; ?>&amp;delay=<?= $theme->root_delay; ?>&amp;showControls=false&amp;altLink=<?= $link_url ?>&amp;showDropShadow=true&amp;useResizes=true&amp;useFull=true&amp;showLoader=false" />
+<param name="bgcolor" value="#1c242e" />
+<param name="wmode" value="transparent" />
+<param name="menu" value="false" />
+<param name="quality" value="high" />
+</object>
+<div id="g-rootpage-link" onclick="javascript:location='<?= $link_url ?>'" ></div>
+<span><a href="<?= $link_url ?>"><?= t("Click to Enter") ?></a></span>
+</div>
diff --git a/themes/greydragon_old/views/rss_block.html.php b/themes/greydragon_old/views/rss_block.html.php
new file mode 100644
index 0000000..00b9e9d
--- /dev/null
+++ b/themes/greydragon_old/views/rss_block.html.php
@@ -0,0 +1,30 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<ul id="g-feeds">
+<? foreach($feeds as $url => $title): ?>
+  <li style="clear: both;">
+    <span class="ui-icon-left">
+    <a href="<?= rss::url($url) ?>">
+      <span class="ui-icon ui-icon-signal-diag">&nbsp;</span>
+      <?= html::purify($title) ?>
+    </a>
+    </span>
+  </li>
+<? endforeach ?>
+</ul>
diff --git a/themes/greydragon_old/views/search.html.php b/themes/greydragon_old/views/search.html.php
new file mode 100644
index 0000000..dee48eb
--- /dev/null
+++ b/themes/greydragon_old/views/search.html.php
@@ -0,0 +1,35 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<div id="g-search-results">
+  <h1><?= t("Search Results for \"%term\"", array("term" => $q)) ?> </h1>
+
+  <?= $theme->add_paginator("top"); ?>
+  <div class="g-album-grid-container">
+  <ul id="g-album-grid">
+<? if (count($items)): ?>
+    <? foreach ($items as $item): ?>
+      <?= $theme->get_thumb_element($item) ?>
+    <? endforeach ?>
+<? else: ?>
+  <li><?= t("No results found for <b>%term</b>", array("term" => $q)) ?></li>
+<? endif; ?>
+  </ul>
+  </div>
+  <?= $theme->add_paginator("bottom"); ?>
+</div>
\ No newline at end of file
diff --git a/themes/greydragon_old/views/sidebar.html.php b/themes/greydragon_old/views/sidebar.html.php
new file mode 100644
index 0000000..03b2778
--- /dev/null
+++ b/themes/greydragon_old/views/sidebar.html.php
@@ -0,0 +1,27 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Grey Dragon Theme - a custom theme for Gallery 3
+ * This theme was designed and built by Serguei Dosyukov, whose blog you will find at http://blog.dragonsoft.us
+ * Copyright (C) 2009-2012 Serguei Dosyukov
+ *
+ * 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
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+?>
+<?= $theme->sidebar_top() ?>
+<div class="g-toolbar"><h1>&nbsp;</h1></div>
+<? if ((!$user->guest) || (!$theme->sidebar_hideguest)):
+     try { echo $theme->sidebar_blocks(); } catch (Exception $e) { } 
+   else:
+     echo "";
+   endif;
+?>
+<?= $theme->sidebar_bottom() ?>
diff --git a/themes/greydragon_old/views/user_profile.html.php b/themes/greydragon_old/views/user_profile.html.php
new file mode 100644
index 0000000..587eec2
--- /dev/null
+++ b/themes/greydragon_old/views/user_profile.html.php
@@ -0,0 +1,44 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+  $(document).ready(function() {
+    $("#g-profile-return").click(function(event) {
+      history.go(-1);
+      return false;
+    })
+  });
+</script>
+
+<div id="g-user-profile">
+  <h1><?= t("User profile: %name", array("name" => $user->display_name())) ?></h1>
+  <div id="g-user-profile-operations">
+    <a id="g-profile-return" class="g-button ui-state-default ui-corner-all" href="#">
+      <?= t("Return") ?>
+    </a>
+<? if ($editable): ?>
+    <a class="g-button ui-state-default ui-corner-all g-dialog-link" href="<?= url::site("form/edit/users/{$user->id}") ?>">
+      <?= t("Edit") ?>
+    </a>
+    <a class="g-button ui-state-default ui-corner-all g-dialog-link" href="<?= url::site("users/form_change_email/{$user->id}") ?>">
+      <?= t("Change email") ?>
+    </a>
+    <a class="g-button ui-state-default ui-corner-all g-dialog-link" href="<?= url::site("users/form_change_password/{$user->id}") ?>">
+      <?= t("Change password") ?>
+    </a>
+<? endif ?>
+<? if ($contactable): ?>
+    <a class="g-button ui-state-default ui-corner-all g-dialog-link"
+       href="<?= url::site("user_profile/contact/{$user->id}") ?>">
+      <?= t("Contact") ?>
+    </a>
+<? endif ?>
+  </div>
+  <img src="<?= $user->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>"
+     alt="<?= html::clean_attribute($user->display_name()) ?>"
+     class="g-avatar g-left" width="40" height="40" />
+<? foreach ($info_parts as $info): ?>
+  <div class="g-block">
+    <h2><?= html::purify($info->title) ?></h2>
+    <div class="g-block-content"><?= $info->view ?></div>
+  </div>
+<? endforeach ?>
+</div>
diff --git a/themes/wind/css/fix-ie.css b/themes/wind/css/fix-ie.css
new file mode 100644
index 0000000..0633ff0
--- /dev/null
+++ b/themes/wind/css/fix-ie.css
@@ -0,0 +1,59 @@
+/**
+ * Fix display in IE 6, 7, and 8
+ */
+
+#g-banner {
+  z-index: 2;
+  zoom: 1;
+}
+
+#g-sidebar {
+  overflow: hidden;
+}
+
+#g-photo,
+#g-movie {
+	zoom: 1;
+}
+
+#g-photo .g-context-menu,
+#g-movie .g-context-menu {
+	width: 240px;
+}
+
+input.submit {
+  clear: none !important;
+  display: inline !important;
+}
+
+.g-short-form input.text,
+.g-short-form input.submit {
+  font-size: 1em;
+  line-height: 1em;
+  padding: .38em .3em;
+}
+
+#g-search-form input#q {
+  width: 300px;
+}
+
+#g-add-tag-form input.textbox {
+  width: 110px !important;
+}
+
+#g-add-tag-form input[type='submit'] {
+  padding: .3em 0 !important;
+}
+
+#g-dialog .g-cancel {
+  display: inline-block !important;
+  float: none !important;
+}
+
+.g-paginator .g-text-right {
+  width: 29%;
+}
+
+.g-paginator .ui-icon-right {
+  width: 60px;
+}
diff --git a/themes/wind/css/screen-rtl.css b/themes/wind/css/screen-rtl.css
new file mode 100644
index 0000000..e79f2c0
--- /dev/null
+++ b/themes/wind/css/screen-rtl.css
@@ -0,0 +1,333 @@
+/**
+ * Gallery 3 Wind Theme Right-to-Left Screen Styles
+ */
+
+.rtl {
+  direction: rtl;
+}
+
+#g-header,
+#g-content,
+#g-sidebar,
+#g-footer,
+caption,
+th,
+#g-dialog,
+.g-context-menu li a,
+.g-message-box li,
+#g-site-status li {
+  text-align: right;
+}
+
+.g-text-right {
+  text-align: left;
+}
+
+/* Lists ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-text li,
+.g-text li {
+  margin-left: 0;
+  margin-right: 1em;
+}
+
+/* Messages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-error,
+.g-info,
+.g-success,
+.g-warning,
+#g-add-photos-status .g-success,
+#g-add-photos-status .g-error {
+  background-position: center right;
+  padding-right: 30px !important;
+}
+
+form li.g-error,
+form li.g-info,
+form li.g-success,
+form li.g-warning {
+  padding-right: 0 !important;
+}
+
+.g-left,
+.g-inline li,
+#g-content #g-album-grid .g-item,
+.sf-menu li,
+.g-breadcrumbs li,
+.g-paginator li,
+.g-buttonset li,
+.ui-icon-left .ui-icon,
+.g-short-form li,
+form ul ul li,
+input[type="submit"],
+input[type="reset"],
+input.checkbox,
+input[type=checkbox],
+input.radio,
+input[type=radio] {
+  float: right;
+}
+
+.g-right,
+.ui-icon-right .ui-icon {
+  float: left;
+}
+
+.g-inline li {
+  margin-right: 1em;
+}
+
+.g-inline li.g-first {
+  margin-right: 0;
+}
+
+.g-breadcrumbs li {
+  background: transparent url('../images/ico-separator-rtl.gif') no-repeat scroll right center;
+  padding: 1em 18px 1em 8px;
+}
+
+.g-breadcrumbs .g-first {
+  background: none;
+  padding-right: 0;
+}
+
+input.checkbox {
+  margin-left: .4em;
+}
+
+#g-add-comment {
+  right: inherit;
+  left: 0;
+}
+
+.ui-icon-left .ui-icon {
+  margin-left: .2em;
+}
+
+.ui-icon-right .ui-icon {
+  margin-right: .2em;
+}
+
+/* RTL Corner radius ~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-buttonset .ui-corner-tl {
+  -moz-border-radius-topleft: 0;
+  -webkit-border-top-left-radius: 0;
+  border-top-left-radius: 0;
+  -moz-border-radius-topright: 5px !important;
+  -webkit-border-top-right-radius: 5px !important;
+  border-top-right-radius: 5px !important;
+}
+
+.g-buttonset .ui-corner-tr {
+  -moz-border-radius-topright: 0;
+  -webkit-border-top-right-radius: 0;
+  border-top-right-radius: 0;
+  -moz-border-radius-topleft: 5px !important;
+  -webkit-border-top-left-radius: 5px !important;
+  border-top-left-radius: 5px !important;
+}
+
+.g-buttonset .ui-corner-bl {
+  -moz-border-radius-bottomleft: 0;
+  -webkit-border-bottom-left-radius: 0;
+  border-bottom-left-radius: 0;
+  -moz-border-radius-bottomright: 5px !important;
+  -webkit-border-bottom-right-radius: 5px !important;
+  border-bottom-right-radius: 5px !important;
+}
+
+.g-buttonset .ui-corner-br {
+  -moz-border-radius-bottomright: 0;
+  -webkit-border-bottom-right-radius: 0;
+  border-bottom-right-radius: 0;
+  -moz-border-radius-bottomleft: 5px !important;
+  -webkit-border-bottom-left-radius: 5px !important;
+  border-bottom-left-radius: 5px !important;
+}
+
+.g-buttonset .ui-corner-right,
+.ui-progressbar .ui-corner-right {
+  -moz-border-radius-topright: 0;
+  -webkit-border-top-right-radius: 0;
+  border-top-right-radius: 0;
+  -moz-border-radius-topleft: 5px !important;
+  -webkit-border-top-left-radius: 5px !important;
+  border-top-left-radius: 5px !important;
+  -moz-border-radius-bottomright: 0;
+  -webkit-border-bottom-right-radius: 0;
+  border-bottom-right-radius: 0;
+  -moz-border-radius-bottomleft: 5px !important;
+  -webkit-border-bottom-left-radius: 5px !important;
+  border-bottom-left-radius: 5px !important;
+}
+
+.g-buttonset .ui-corner-left,
+.ui-progressbar .ui-corner-left {
+  -moz-border-radius-topleft: 0;
+  -webkit-border-top-left-radius: 0;
+  border-top-left-radius: 0;
+  -moz-border-radius-topright: 5px !important;
+  -webkit-border-top-right-radius: 5px !important;
+  border-top-right-radius: 5px !important;
+  -moz-border-radius-bottomleft: 0;
+  -webkit-border-bottom-left-radius: 0;
+  border-bottom-left-radius: 0;
+  -moz-border-radius-bottomright: 5px !important;
+  -webkit-border-bottom-right-radius: 5px !important;
+  border-bottom-right-radius: 5px !important;
+}
+
+/* RTL Superfish ~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.sf-menu a {
+  border-left: none;
+  border-right:1px solid #fff;
+}
+
+.sf-menu a.sf-with-ul {
+  padding-left: 2.25em;
+  padding-right: 1em;
+}
+
+.sf-sub-indicator {
+  left: .75em !important;
+  right: auto;
+  background: url('../../../lib/superfish/images/arrows-ffffff-rtl.png') no-repeat -10px -100px;
+}
+
+a > .sf-sub-indicator {
+  top: .8em;
+  background-position: -10px -100px;
+}
+
+a:focus > .sf-sub-indicator,
+a:hover > .sf-sub-indicator,
+a:active > .sf-sub-indicator,
+li:hover > a > .sf-sub-indicator,
+li.sfHover > a > .sf-sub-indicator {
+  background-position: 0 -100px;
+}
+
+.sf-menu ul .sf-sub-indicator {
+  background-position:  0 0;
+}
+
+.sf-menu ul a > .sf-sub-indicator {
+  background-position: -10px 0;
+}
+
+.sf-menu ul a:focus > .sf-sub-indicator,
+.sf-menu ul a:hover > .sf-sub-indicator,
+.sf-menu ul a:active > .sf-sub-indicator,
+.sf-menu ul li:hover > a > .sf-sub-indicator,
+.sf-menu ul li.sfHover > a > .sf-sub-indicator {
+  background-position: 0 0;
+}
+
+.sf-menu li:hover ul,
+.sf-menu li.sfHover ul {
+  right: 0;
+  left: auto;
+}
+
+ul.sf-menu li li:hover ul,
+ul.sf-menu li li.sfHover ul {
+  right: 12em;
+  left: auto;
+}
+ul.sf-menu li li li:hover ul,
+ul.sf-menu li li li.sfHover ul {
+  right: 12em;
+  left: auto;
+}
+
+.sf-shadow ul {
+  background:	url('../../../lib/superfish/images/shadow.png') no-repeat bottom left;
+  padding: 0 0 9px 8px;
+  border-top-right-radius: 0;
+  border-bottom-left-radius: 0;
+  -moz-border-radius-topright: 0;
+  -moz-border-radius-bottomleft: 0;
+  -webkit-border-top-right-radius: 0;
+  -webkit-border-bottom-left-radius: 0;
+  -moz-border-radius-topleft: 17px;
+  -moz-border-radius-bottomright: 17px;
+  -webkit-border-top-left-radius: 17px;
+  -webkit-border-bottom-right-radius: 17px;
+  border-top-left-radius: 17px;
+  border-bottom-right-radius: 17px;
+}
+
+/* RTL ThemeRoller ~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.ui-dialog .ui-dialog-titlebar {
+  padding: 0.5em 1em 0.3em 0.3em;
+}
+
+.ui-dialog .ui-dialog-title {
+  float: right;
+}
+
+.ui-dialog .ui-dialog-titlebar-close {
+  left: 0.3em;
+  right: auto;
+}
+
+/* RTL paginator ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-paginator .g-info {
+  width: 35%;
+}
+
+.g-paginator .g-text-right {
+  margin-left: 0;
+}
+
+.g-paginator .ui-icon-seek-end {
+  background-position: -80px -160px;
+}
+
+.g-paginator .ui-icon-seek-next {
+  background-position: -48px -160px;
+}
+
+.g-paginator .ui-icon-seek-prev {
+  background-position: -32px -160px;
+}
+
+.g-paginator .ui-icon-seek-first {
+  background-position: -64px -160px;
+}
+
+#g-header #g-login-menu,
+#g-header #g-quick-search-form {
+  clear: left;
+  float: left;
+}
+
+#g-header #g-login-menu li {
+  margin-left: 0;
+  padding-left: 0;
+  padding-right: 1.2em;
+}
+
+#g-site-menu {
+  left: auto;
+  right: 150px;
+}
+
+#g-view-menu #g-slideshow-link {
+  background-image: url('../images/ico-view-slideshow-rtl.png');
+}
+
+#g-sidebar .g-block-content {
+  padding-right: 1em;
+  padding-left: 0;
+}
+
+#g-footer #g-credits li {
+  padding-left: 1.2em !important;
+  padding-right: 0;
+}
diff --git a/themes/wind/css/screen.css b/themes/wind/css/screen.css
new file mode 100644
index 0000000..c644d70
--- /dev/null
+++ b/themes/wind/css/screen.css
@@ -0,0 +1,1066 @@
+/**
+ * Gallery 3 Wind Theme Screen Styles
+ *
+ * @requires YUI reset, font, grids CSS
+ *
+ * Sheet organization:
+ *   1)  Font sizes, base HTML elements
+ *   2)  Reusable content blocks
+ *   3)  Page layout containers
+ *   4)  Content blocks in specific layout containers
+ *   5)  States and interactions
+ *   6)  Positioning and order
+ *   7)  Navigation and menus
+ *   8)  jQuery and jQuery UI
+ */
+
+/** *******************************************************************
+ *  1) Font sizes, base HTML elements
+ **********************************************************************/
+
+body, html {
+  background-color: #ccc;
+  font-family: 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+}
+
+p {
+  margin-bottom: 1em;
+}
+
+em {
+  font-style: oblique;
+}
+
+h1, h2, h3, h4, h5, strong, th {
+  font-weight: bold;
+}
+
+h1 {
+  font-size: 1.7em;
+}
+
+#g-dialog h1 {
+  font-size: 1.1em;
+}
+
+h2 {
+  font-size: 1.4em;
+}
+
+#g-sidebar .g-block h2 {
+  font-size: 1.2em;
+}
+
+#g-sidebar .g-block li {
+  margin-bottom: .6em;
+}
+
+#g-content,
+#g-site-menu,
+h3 {
+  font-size: 1.2em;
+}
+
+#g-sidebar,
+.g-breadcrumbs {
+  font-size: .9em;
+}
+
+#g-banner,
+#g-footer,
+.g-message {
+  font-size: .8em;
+}
+
+#g-album-grid .g-item,
+#g-item #g-photo,
+#g-item #g-movie {
+  font-size: .7em;
+}
+
+/* Links ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+a,
+.g-menu a,
+#g-dialog a,
+.g-button,
+.g-button:hover,
+.g-button:active,
+a.ui-state-hover,
+input.ui-state-hover,
+button.ui-state-hover {
+  color: #5382bf !important;
+  cursor: pointer !important;
+  text-decoration: none;
+  -moz-outline-style: none;
+}
+
+a:hover,
+#g-dialog a:hover {
+  text-decoration: underline;
+}
+
+.g-menu a:hover {
+  text-decoration: none;
+}
+
+#g-dialog #g-action-status li {
+  width: 434px;
+  white-space: normal;
+  padding-left: 32px;
+}
+
+/* Lists ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+ul.g-text li,
+.g-text ul li {
+  list-style-type: disc;
+}
+
+ol.g-text li,
+.g-text ol li {
+  list-style-type: decimal;
+}
+
+.g-text li,
+.g-text li {
+  margin-left: 1em;
+}
+
+/* Forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+form {
+  margin: 0;
+}
+
+fieldset {
+  border: 1px solid #ccc;
+  padding: 0 1em .8em 1em;
+}
+
+#g-banner fieldset,
+#g-sidebar fieldset {
+  border: none;
+  padding: 0;
+}
+
+legend {
+  font-weight: bold;
+  margin: 0;
+  padding: 0 .2em;
+}
+
+#g-banner legend,
+#g-sidebar legend,
+input[type="hidden"] {
+  display: none;
+}
+
+input.textbox,
+input[type="text"],
+input[type="password"],
+textarea {
+  border: 1px solid #e8e8e8;
+  border-top-color: #ccc;
+  border-left-color: #ccc;
+  clear: both;
+  color: #333;
+  width: 50%;
+}
+
+textarea {
+  height: 12em;
+  width: 97%;
+}
+
+input:focus,
+input.textbox:focus,
+input[type=text]:focus,
+textarea:focus,
+option:focus {
+  background-color: #ffc;
+  color: #000;
+}
+
+input.checkbox,
+input[type=checkbox],
+input.radio,
+input[type=radio] {
+  float: left;
+  margin-right: .4em;
+}
+
+/* Form layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+form li {
+  margin: 0;
+  padding: 0 0 .2em 0;
+}
+
+form ul {
+  margin-top: 0;
+}
+
+form ul ul {
+  clear: both;
+}
+
+form ul ul li {
+  float: left;
+}
+
+input,
+select,
+textarea {
+  display: block;
+  clear: both;
+  padding: .2em;
+}
+
+input[type="submit"],
+input[type="reset"] {
+  display: inline;
+  clear: none;
+  float: left;
+}
+
+/* Forms in dialogs and panels ~~~~~~~~~ */
+
+#g-dialog ul li {
+  padding-bottom: .8em;
+}
+
+#g-dialog fieldset,
+#g-panel fieldset {
+  border: none;
+  padding: 0;
+}
+
+#g-panel legend {
+  display: none;
+}
+
+input[readonly] {
+  background-color: #F4F4FC;
+}
+
+#g-dialog input.textbox,
+#g-dialog input[type=text],
+#g-dialog input[type=password],
+#g-dialog textarea {
+  width: 97%;
+}
+
+/* Short forms ~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-short-form legend,
+.g-short-form label {
+  display: none;
+}
+
+.g-short-form fieldset {
+  border: none;
+  padding: 0;
+}
+
+.g-short-form li {
+  float: left;
+  margin: 0 !important;
+  padding: .4em 0;
+}
+
+.g-short-form .textbox,
+.g-short-form input[type=text] {
+  color: #666;
+  padding: .3em .6em;
+  width: 100%;
+}
+
+.g-short-form .textbox.g-error {
+  border: 1px solid #f00;
+  color: #f00;
+  padding-left: 24px;
+}
+
+.g-short-form .g-cancel {
+  display: block;
+  margin: .3em .8em;
+}
+
+#g-sidebar .g-short-form li {
+  padding-left: 0;
+  padding-right: 0;
+}
+
+/* Tables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+table {
+  width: 100%;
+}
+
+#g-content table {
+  margin: 1em 0;
+}
+
+caption,
+th {
+  text-align: left;
+}
+
+th,
+td {
+  border: none;
+  border-bottom: 1px solid #ccc;
+  padding: .5em;
+}
+
+td {
+  vertical-align: top;
+}
+
+/* Text ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-text-small {
+  font-size: .8em;
+}
+
+.g-text-big {
+  font-size: 1.2em;
+}
+
+.g-text-right {
+  text-align: right;
+}
+
+/** *******************************************************************
+ *  2) Reusable content blocks
+ *********************************************************************/
+
+.g-block h2 {
+  background-color: #e8e8e8;
+  padding: .3em .8em;
+}
+
+.g-block-content {
+  margin-top: 1em;
+}
+
+/** *******************************************************************
+ *  3) Page layout containers
+ *********************************************************************/
+
+/* Dimension and scale ~~~~~~~~~~~~~~~~~~~ */
+
+.g-one-quarter {
+  width: 25%;
+}
+
+.g-one-third {
+  width: 33%;
+}
+
+.g-one-half {
+  width: 50%;
+}
+
+.g-two-thirds {
+  width: 66%;
+}
+
+.g-three-quarters {
+  width: 75%;
+}
+
+.g-whole {
+  width: 100%;
+}
+
+/* View container ~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-view {
+  background-color: #fff;
+  border: 1px solid #ccc;
+  border-bottom: none;
+}
+
+/* Layout containers ~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-header {
+  margin-bottom: 1em;
+}
+
+#g-banner {
+  background-color: #e8e8e8;
+  border-bottom: 1px solid #ccc;
+  min-height: 5em;
+  padding: 1em 20px;
+  position: relative;
+}
+
+#g-content {
+  padding-left: 20px;
+  position: relative;
+  width: 696px;
+}
+
+#g-sidebar {
+  padding: 0 20px;
+  width: 220px;
+}
+
+#g-footer {
+  background-color: #e8e8e8;
+  border-top: 1px solid #ccc;
+  margin-top: 20px;
+  padding: 10px 20px;
+}
+
+/** *******************************************************************
+ *  4) Content blocks in specific layout containers
+ *********************************************************************/
+
+/* Header  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-banner #g-quick-search-form {
+  clear: right;
+  float: right;
+  margin-top: 1em;
+}
+
+#g-banner #g-quick-search-form input[type='text'] {
+  width: 17em;
+}
+
+#g-content .g-block h2 {
+  background-color: transparent;
+  padding-left: 0;
+}
+
+/* Sidebar  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-sidebar .g-block-content {
+  padding-left: 1em;
+}
+
+#g-sidebar #g-image-block {
+  overflow: hidden;
+}
+
+/* Album content ~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-content #g-album-grid {
+  margin: 1em 0;
+  position: relative;
+  z-index: 1;
+}
+
+#g-content #g-album-grid .g-item {
+  background-color: #fff;
+  border: 1px solid #fff;
+  float: left;
+  padding: .6em 8px;
+  position: relative;
+  text-align: center;
+  width: 213px;
+  z-index: 1;
+}
+
+#g-content #g-album-grid .g-item h2 {
+  margin: 5px 0;
+}
+
+#g-content .g-photo h2,
+#g-content .g-movie h2,
+#g-content .g-item .g-metadata {
+  display: none;
+  margin-bottom: .6em;
+}
+
+#g-content #g-album-grid .g-album {
+  background-color: #e8e8e8;
+}
+
+#g-content #g-album-grid .g-album h2 span.g-album {
+  background: transparent url('../images/ico-album.png') no-repeat top left;
+  display: inline-block;
+  height: 16px;
+  margin-right: 5px;
+  width: 16px;
+}
+
+#g-content #g-album-grid .g-hover-item {
+  border: 1px solid #000;
+  position: absolute !important;
+  z-index: 1000 !important;
+}
+
+#g-content .g-hover-item h2,
+#g-content .g-hover-item .g-metadata {
+  display: block;
+}
+
+#g-content #g-album-grid #g-place-holder {
+  position: relative;
+  visibility: hidden;
+  z-index: 1;
+}
+
+/* Search results ~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-content #g-search-results {
+  margin-top: 1em;
+  padding-top: 1em;
+}
+
+/* Individual photo content ~~~~~~~~~~~~~~ */
+
+#g-item {
+  position: relative;
+  width: 100%;
+}
+
+#g-item #g-photo,
+#g-item #g-movie {
+  padding: 2.2em 0;
+  position: relative;
+}
+
+#g-item img.g-resize,
+#g-item a.g-movie {
+  display: block;
+  margin: 0 auto;
+}
+
+/* Footer content ~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-footer #g-credits li {
+  padding-right: 1.2em;
+}
+
+/* In-line editing  ~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-in-place-edit-message {
+  background-color: #fff;
+}
+
+/* Permissions ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-edit-permissions-form td {
+  background-image: none;
+}
+
+#g-edit-permissions-form fieldset {
+  border: 1px solid #ccc;
+}
+
+#g-permissions .g-denied {
+  background-color: #fcc;
+}
+
+#g-permissions .g-allowed {
+  background-color: #cfc;
+}
+
+#g-permissions .g-breadcrumbs a {
+  border: 1px solid #fff;
+}
+
+#g-permissions .g-active a {
+  border: 1px solid #ddd;
+  background: #eee;
+}
+
+/** *******************************************************************
+ *  5) States and interactions
+ **********************************************************************/
+
+.g-active,
+.g-enabled,
+.g-available,
+.g-selected,
+.g-highlight {
+  font-weight: bold;
+}
+
+.g-inactive,
+.g-disabled,
+.g-unavailable,
+.g-uneditable,
+.g-locked,
+.g-deselected,
+.g-understate {
+  color: #ccc;
+  font-weight: normal;
+}
+
+.g-editable {
+  padding: .2em .3em;
+}
+
+.g-editable:hover {
+  background-color: #ffc;
+  cursor: text;
+}
+
+.g-error,
+.g-info,
+.g-success,
+.g-warning {
+  padding-left: 30px;
+}
+
+form li.g-error,
+form li.g-info,
+form li.g-success,
+form li.g-warning {
+  background-image: none;
+  padding: .3em .8em .3em 0;
+}
+
+.g-short-form li.g-error {
+  padding: .3em 0;
+}
+
+form.g-error input[type="text"],
+li.g-error input[type="text"],
+form.g-error input[type="password"],
+li.g-error input[type="password"],
+form.g-error input[type="checkbox"],
+li.g-error input[type="checkbox"],
+form.g-error input[type="radio"],
+li.g-error input[type="radio"],
+form.g-error textarea,
+li.g-error textarea,
+form.g-error select,
+li.g-error select {
+  border: 2px solid #f00;
+  margin-bottom: .2em;
+}
+
+.g-error,
+.g-denied,
+tr.g-error td.g-error,
+#g-add-photos-status .g-error {
+  background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%;
+  color: #f00;
+}
+
+.g-info {
+  background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%;
+}
+
+.g-success,
+.g-allowed,
+#g-add-photos-status .g-success {
+  background: #d9efc2 url('../images/ico-success.png') no-repeat .4em 50%;
+}
+
+tr.g-success {
+  background-image: none;
+}
+
+tr.g-success td.g-success {
+  background-image: url('../images/ico-success.png');
+}
+
+.g-warning,
+tr.g-warning td.g-warning {
+  background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%;
+}
+
+form .g-error {
+  background-color: #fff;
+  padding-left: 20px;
+}
+
+.g-open {
+}
+
+.g-closed {
+}
+
+.g-installed {
+  background-color: #eeeeee;
+}
+
+.g-default {
+  background-color: #c5dbec;
+  font-weight: bold;
+}
+
+.g-draggable {
+  cursor: move;
+}
+
+.g-draggable:hover {
+  border: 1px dashed #000;
+}
+
+.ui-sortable .g-target,
+.ui-state-highlight {
+  background-color: #fcf9ce;
+  border: 2px dotted #999;
+  height: 2em;
+  margin: 1em 0;
+}
+
+/* Ajax loading indicator ~~~~~~~~~~~~~~~~ */
+
+.g-loading-large,
+.g-dialog-loading-large {
+  background: #e8e8e8 url('../images/loading-large.gif') no-repeat center center !important;
+}
+
+.g-loading-small {
+  background: #e8e8e8 url('../images/loading-small.gif') no-repeat center center !important;
+}
+
+/** *******************************************************************
+ *  6) Positioning and order
+ **********************************************************************/
+
+.g-left {
+  clear: none;
+  float: left;
+}
+
+.g-right {
+  clear: none;
+  float: right;
+}
+
+.g-first {
+}
+
+.g-last {
+}
+
+.g-even {
+  background-color: #fff;
+}
+
+.g-odd {
+  background-color: #eee;
+}
+
+/** *******************************************************************
+ *  7) Navigation and menus
+ *********************************************************************/
+
+/* Login menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-banner #g-login-menu {
+  color: #999;
+  float: right;
+}
+
+#g-banner #g-login-menu li {
+  padding-left: 1.2em;
+}
+
+/* Site Menu  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-site-menu {
+  bottom: 0;
+  left: 140px;
+  position: absolute;
+}
+
+#g-site-menu ul {
+  margin-bottom: 0 !important;
+}
+
+/* Context Menu  ~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-context-menu {
+  background-color: #fff;
+  bottom: 0;
+  left: 0;
+  position: absolute;
+}
+
+.g-item .g-context-menu {
+  display: none;
+  margin-top: 2em;
+  width: 100%;
+}
+
+#g-item .g-context-menu ul {
+  display: none;
+}
+
+.g-context-menu li {
+  border-left: none;
+  border-right: none;
+  border-bottom: none;
+}
+
+.g-context-menu li a {
+  display: block;
+  line-height: 1.6em;
+}
+
+.g-hover-item .g-context-menu {
+  display: block;
+}
+
+.g-hover-item .g-context-menu li {
+  text-align: left;
+}
+
+.g-hover-item .g-context-menu a:hover {
+  text-decoration: none;
+}
+
+/* View Menu  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+#g-view-menu {
+  margin-bottom: 1em;
+}
+
+#g-view-menu a {
+  background-repeat: no-repeat;
+  background-position: 50% 50%;
+  height: 28px !important;
+  width: 43px !important;
+}
+
+#g-view-menu #g-slideshow-link {
+  background-image: url('../images/ico-view-slideshow.png');
+}
+
+#g-view-menu .g-fullsize-link {
+  background-image: url('../images/ico-view-fullsize.png');
+}
+
+#g-view-menu #g-comments-link {
+  background-image: url('../images/ico-view-comments.png');
+}
+
+#g-view-menu #g-print-digibug-link {
+  background-image: url('../images/ico-print.png');
+}
+
+/** *******************************************************************
+ *  8) jQuery and jQuery UI
+ *********************************************************************/
+
+/* Generic block container ~~~~~~~~~~~~~~~ */
+
+.g-block {
+  clear: both;
+  margin-bottom: 2.5em;
+}
+
+.g-block-content {
+}
+
+/* Superfish menu overrides ~~~~~~~~~~~~~~ */
+
+.sf-menu ul {
+  width: 12em;
+}
+
+ul.sf-menu li li:hover ul,
+ul.sf-menu li li.sfHover ul {
+  left: 12em;
+}
+
+ul.sf-menu li li li:hover ul,
+ul.sf-menu li li li.sfHover ul {
+  left: 12em;
+}
+
+.sf-menu li li,
+.sf-menu li li ul li {
+  background-color: #bdd2ff;
+}
+
+.sf-menu li:hover {
+  background-color: #dfe9ff;
+}
+
+/* jQuery UI Dialog ~~~~~~~~~~~~~~~~~~~~~~ */
+
+.ui-widget-overlay {
+  background: #000;
+  opacity: .7;
+}
+
+/* Buttons ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-button {
+  display: inline-block;
+  margin: 0 4px 0 0;
+  padding: .2em .4em;
+}
+
+.g-button,
+.g-button:hover,
+.g-button:active {
+  cursor: pointer !important;
+  outline: 0;
+  text-decoration: none;
+  -moz-outline-style: none;
+}
+
+button {
+  padding: 2px 4px 2px 4px;
+}
+
+/* jQuery UI ThemeRoller buttons ~~~~~~~~~ */
+
+.g-buttonset {
+  padding-left: 1px;
+}
+
+.g-buttonset li {
+  float: left;
+}
+
+.g-buttonset .g-button {
+  margin: 0;
+}
+
+.ui-icon-left .ui-icon {
+  float: left;
+  margin-right: .2em;
+}
+
+.ui-icon-right .ui-icon {
+  float: right;
+  margin-left: .2em;
+}
+
+/* Rotate icon, ThemeRoller only provides one of these */
+
+.ui-icon-rotate-ccw {
+  background-position: -192px -64px;
+}
+
+.ui-icon-rotate-cw {
+  background-position: -208px -64px;
+}
+
+.g-progress-bar {
+  height: 1em;
+  width: 100%;
+  margin: .5em 0;
+  display: inline-block;
+}
+
+/* Status and validation messages ~~~~ */
+
+.g-message-block {
+  background-position: .4em .3em;
+  border: 1px solid #ccc;
+  padding: 0;
+}
+
+#g-action-status {
+  margin-bottom: 1em;
+}
+
+#g-action-status li,
+p#g-action-status,
+div#g-action-status {
+  padding: .3em .3em .3em 30px;
+}
+
+#g-site-status li {
+  border-bottom: 1px solid #ccc;
+  padding: .3em .3em .3em 30px;
+}
+
+.g-module-status {
+  clear: both;
+  margin-bottom: 1em;
+}
+
+.g-message {
+  background-position: 0 50%;
+}
+
+/* Breadcrumbs ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-breadcrumbs {
+  clear: both;
+  padding: 0 20px;
+}
+
+.g-breadcrumbs li {
+  background: transparent url('../images/ico-separator.gif') no-repeat scroll left center;
+  float: left;
+  padding: 1em 8px 1em 18px;
+}
+
+.g-breadcrumbs .g-first {
+  background: none;
+  padding-left: 0;
+}
+
+.g-breadcrumbs li a,
+.g-breadcrumbs li span {
+  display: block;
+}
+
+#g-dialog ul.g-breadcrumbs {
+  margin-left: 0;
+  padding-left: 0;
+}
+
+/* Pagination ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+.g-paginator {
+  padding: .2em 0;
+  width: 100%;
+}
+
+.g-paginator li {
+  float: left;
+  width: 30%;
+}
+
+.g-paginator .g-info {
+  background: none;
+  padding: .2em 0;
+  text-align: center;
+  width: 40%;
+}
+
+/* Dialogs and panels ~~~~~~~~~~~~~~~~~~ */
+
+#g-dialog {
+  text-align: left;
+}
+
+#g-dialog legend {
+  display: none;
+}
+
+#g-dialog .g-cancel {
+  margin: .4em 1em;
+}
+
+#g-panel {
+  display: none;
+  padding: 1em;
+}
+
+/* Inline layout  ~~~~~~~~~~ */
+
+.g-inline li {
+  float: left;
+  margin-left: 1.8em;
+  padding-left: 0 !important;
+}
+
+.g-inline li.g-first {
+  margin-left: 0;
+}
+
+/* Autocomplete  ~~~~~~~~~~ */
+
+.ac_loading {
+  background: white url('../images/loading-small.gif') right center no-repeat !important;
+}
diff --git a/themes/wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png b/themes/wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 0000000..5b5dab2
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png b/themes/wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png
new file mode 100644
index 0000000..47acaad
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png b/themes/wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png
new file mode 100644
index 0000000..9fb564f
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png b/themes/wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png
new file mode 100644
index 0000000..0149515
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png b/themes/wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 0000000..4443fdc
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png b/themes/wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
new file mode 100644
index 0000000..0cdbda3
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png b/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
new file mode 100644
index 0000000..4f3faf8
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png differ
diff --git a/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
new file mode 100644
index 0000000..38c3833
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_217bc0_256x240.png b/themes/wind/css/themeroller/images/ui-icons_217bc0_256x240.png
new file mode 100644
index 0000000..7719d48
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-icons_217bc0_256x240.png differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_2e83ff_256x240.png b/themes/wind/css/themeroller/images/ui-icons_2e83ff_256x240.png
new file mode 100644
index 0000000..d9897d2
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-icons_2e83ff_256x240.png differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_469bdd_256x240.png b/themes/wind/css/themeroller/images/ui-icons_469bdd_256x240.png
new file mode 100644
index 0000000..d816185
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-icons_469bdd_256x240.png differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_6da8d5_256x240.png b/themes/wind/css/themeroller/images/ui-icons_6da8d5_256x240.png
new file mode 100644
index 0000000..b3c7d66
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-icons_6da8d5_256x240.png differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png b/themes/wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 0000000..2db88b7
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png b/themes/wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png
new file mode 100644
index 0000000..2c8aac4
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-icons_d8e7f3_256x240.png differ
diff --git a/themes/wind/css/themeroller/images/ui-icons_f9bd01_256x240.png b/themes/wind/css/themeroller/images/ui-icons_f9bd01_256x240.png
new file mode 100644
index 0000000..e81603f
Binary files /dev/null and b/themes/wind/css/themeroller/images/ui-icons_f9bd01_256x240.png differ
diff --git a/themes/wind/css/themeroller/ui.base.css b/themes/wind/css/themeroller/ui.base.css
new file mode 100644
index 0000000..1a1810c
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.base.css
@@ -0,0 +1,7 @@
+@import "ui.core.css";
+@import "ui.theme.css";
+@import "ui.datepicker.css";
+@import "ui.dialog.css";
+@import "ui.progressbar.css";
+@import "ui.resizable.css";
+@import "ui.tabs.css";
diff --git a/themes/wind/css/themeroller/ui.core.css b/themes/wind/css/themeroller/ui.core.css
new file mode 100644
index 0000000..d832ad7
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.core.css
@@ -0,0 +1,37 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+*/
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
\ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.datepicker.css b/themes/wind/css/themeroller/ui.datepicker.css
new file mode 100644
index 0000000..92986c9
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.datepicker.css
@@ -0,0 +1,62 @@
+/* Datepicker
+----------------------------------*/
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month, 
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:left; width:100%; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+    display: none; /*sorry for IE5*/
+    display/**/: block; /*sorry for IE5*/
+    position: absolute; /*must have*/
+    z-index: -1; /*must have*/
+    filter: mask(); /*must have*/
+    top: -4px; /*must have*/
+    left: -4px; /*must have*/
+    width: 200px; /*must have*/
+    height: 200px; /*must have*/
+}
\ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.dialog.css b/themes/wind/css/themeroller/ui.dialog.css
new file mode 100644
index 0000000..f10f409
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.dialog.css
@@ -0,0 +1,13 @@
+/* Dialog
+----------------------------------*/
+.ui-dialog { position: relative; padding: .2em; width: 300px; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative;  }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
\ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.progressbar.css b/themes/wind/css/themeroller/ui.progressbar.css
new file mode 100644
index 0000000..bc0939e
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.progressbar.css
@@ -0,0 +1,4 @@
+/* Progressbar
+----------------------------------*/
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.resizable.css b/themes/wind/css/themeroller/ui.resizable.css
new file mode 100644
index 0000000..44efeb2
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.resizable.css
@@ -0,0 +1,13 @@
+/* Resizable
+----------------------------------*/
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
\ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.tabs.css b/themes/wind/css/themeroller/ui.tabs.css
new file mode 100644
index 0000000..70ed3ef
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.tabs.css
@@ -0,0 +1,9 @@
+/* Tabs
+----------------------------------*/
+.ui-tabs {padding: .2em;}
+.ui-tabs .ui-tabs-nav { padding: .2em .2em 0 .2em;  position: relative; }
+.ui-tabs .ui-tabs-nav li { float: left; border-bottom: 0 !important; margin: 0 .2em -1px 0; padding: 0; list-style: none; }
+.ui-tabs .ui-tabs-nav li a { display:block; text-decoration: none; padding: .5em 1em; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected {  padding-bottom: .1em; border-bottom: 0; }
+.ui-tabs .ui-tabs-panel { padding: 1em 1.4em;  display: block; border: 0; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
\ No newline at end of file
diff --git a/themes/wind/css/themeroller/ui.theme.css b/themes/wind/css/themeroller/ui.theme.css
new file mode 100644
index 0000000..477252e
--- /dev/null
+++ b/themes/wind/css/themeroller/ui.theme.css
@@ -0,0 +1,243 @@
+
+
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+* To view and modify this theme, visit http://ui.jquery.com/themeroller/?tr=&ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+*/
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; }
+.ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
+.ui-widget-header a { color: #ffffff; }
+.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; outline: none; }
+.ui-state-default a { color: #2e6e9e; text-decoration: none; outline: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; outline: none; }
+.ui-state-hover a { color: #1d5987; text-decoration: none; outline: none; }
+.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; outline: none; }
+.ui-state-active a { color: #e17009; outline: none; text-decoration: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; }
+.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
+.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-right {  -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
+.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
+.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }
\ No newline at end of file
diff --git a/themes/wind/images/avatar.jpg b/themes/wind/images/avatar.jpg
new file mode 100644
index 0000000..acad931
Binary files /dev/null and b/themes/wind/images/avatar.jpg differ
diff --git a/themes/wind/images/ico-album.png b/themes/wind/images/ico-album.png
new file mode 100644
index 0000000..affa1b8
Binary files /dev/null and b/themes/wind/images/ico-album.png differ
diff --git a/themes/wind/images/ico-denied-inactive.png b/themes/wind/images/ico-denied-inactive.png
new file mode 100644
index 0000000..56db3ff
Binary files /dev/null and b/themes/wind/images/ico-denied-inactive.png differ
diff --git a/themes/wind/images/ico-denied-passive.png b/themes/wind/images/ico-denied-passive.png
new file mode 100644
index 0000000..1e99223
Binary files /dev/null and b/themes/wind/images/ico-denied-passive.png differ
diff --git a/themes/wind/images/ico-denied.png b/themes/wind/images/ico-denied.png
new file mode 100644
index 0000000..08f2493
Binary files /dev/null and b/themes/wind/images/ico-denied.png differ
diff --git a/themes/wind/images/ico-error.png b/themes/wind/images/ico-error.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/themes/wind/images/ico-error.png differ
diff --git a/themes/wind/images/ico-help.png b/themes/wind/images/ico-help.png
new file mode 100644
index 0000000..5c87017
Binary files /dev/null and b/themes/wind/images/ico-help.png differ
diff --git a/themes/wind/images/ico-info.png b/themes/wind/images/ico-info.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/themes/wind/images/ico-info.png differ
diff --git a/themes/wind/images/ico-lock.png b/themes/wind/images/ico-lock.png
new file mode 100644
index 0000000..2ebc4f6
Binary files /dev/null and b/themes/wind/images/ico-lock.png differ
diff --git a/themes/wind/images/ico-print.png b/themes/wind/images/ico-print.png
new file mode 100644
index 0000000..b82a8e1
Binary files /dev/null and b/themes/wind/images/ico-print.png differ
diff --git a/themes/wind/images/ico-separator-rtl.gif b/themes/wind/images/ico-separator-rtl.gif
new file mode 100644
index 0000000..d9061a4
Binary files /dev/null and b/themes/wind/images/ico-separator-rtl.gif differ
diff --git a/themes/wind/images/ico-separator.gif b/themes/wind/images/ico-separator.gif
new file mode 100644
index 0000000..3de2d0d
Binary files /dev/null and b/themes/wind/images/ico-separator.gif differ
diff --git a/themes/wind/images/ico-success-inactive.png b/themes/wind/images/ico-success-inactive.png
new file mode 100644
index 0000000..74b2032
Binary files /dev/null and b/themes/wind/images/ico-success-inactive.png differ
diff --git a/themes/wind/images/ico-success-passive.png b/themes/wind/images/ico-success-passive.png
new file mode 100644
index 0000000..dc8d1de
Binary files /dev/null and b/themes/wind/images/ico-success-passive.png differ
diff --git a/themes/wind/images/ico-success.png b/themes/wind/images/ico-success.png
new file mode 100644
index 0000000..a9925a0
Binary files /dev/null and b/themes/wind/images/ico-success.png differ
diff --git a/themes/wind/images/ico-view-comments.png b/themes/wind/images/ico-view-comments.png
new file mode 100644
index 0000000..e5d3630
Binary files /dev/null and b/themes/wind/images/ico-view-comments.png differ
diff --git a/themes/wind/images/ico-view-fullsize.png b/themes/wind/images/ico-view-fullsize.png
new file mode 100644
index 0000000..0be23e9
Binary files /dev/null and b/themes/wind/images/ico-view-fullsize.png differ
diff --git a/themes/wind/images/ico-view-slideshow-rtl.png b/themes/wind/images/ico-view-slideshow-rtl.png
new file mode 100644
index 0000000..5788b3c
Binary files /dev/null and b/themes/wind/images/ico-view-slideshow-rtl.png differ
diff --git a/themes/wind/images/ico-view-slideshow.png b/themes/wind/images/ico-view-slideshow.png
new file mode 100644
index 0000000..82f61f6
Binary files /dev/null and b/themes/wind/images/ico-view-slideshow.png differ
diff --git a/themes/wind/images/ico-warning.png b/themes/wind/images/ico-warning.png
new file mode 100644
index 0000000..628cf2d
Binary files /dev/null and b/themes/wind/images/ico-warning.png differ
diff --git a/themes/wind/images/loading-large.gif b/themes/wind/images/loading-large.gif
new file mode 100644
index 0000000..cc70a7a
Binary files /dev/null and b/themes/wind/images/loading-large.gif differ
diff --git a/themes/wind/images/loading-small.gif b/themes/wind/images/loading-small.gif
new file mode 100644
index 0000000..d0bce15
Binary files /dev/null and b/themes/wind/images/loading-small.gif differ
diff --git a/themes/wind/images/select-photos-backg.png b/themes/wind/images/select-photos-backg.png
new file mode 100644
index 0000000..81c2d61
Binary files /dev/null and b/themes/wind/images/select-photos-backg.png differ
diff --git a/themes/wind/js/ui.init.js b/themes/wind/js/ui.init.js
new file mode 100644
index 0000000..fd75c21
--- /dev/null
+++ b/themes/wind/js/ui.init.js
@@ -0,0 +1,118 @@
+/**
+ * Initialize jQuery UI and Gallery Plugins
+ */
+
+$(document).ready(function() {
+
+  // Initialize Superfish menus (hidden, then shown to address IE issue)
+  $("#g-site-menu .g-menu").hide().addClass("sf-menu");
+  $("#g-site-menu .g-menu").superfish({
+    delay: 500,
+    animation: {
+      opacity:'show',
+      height:'show'
+    },
+    pathClass: "g-selected",
+    speed: 'fast'
+  }).show();
+
+  // Initialize status message effects
+  $("#g-action-status li").gallery_show_message();
+
+  // Initialize dialogs
+  $(".g-dialog-link").gallery_dialog();
+
+  // Initialize short forms
+  $(".g-short-form").gallery_short_form();
+
+  // Apply jQuery UI icon, hover, and rounded corner styles
+  $("input[type=submit]:not(.g-short-form input)").addClass("ui-state-default ui-corner-all");
+  if ($("#g-view-menu").length) {
+    $("#g-view-menu ul").removeClass("g-menu").removeClass("sf-menu");
+    $("#g-view-menu a").addClass("ui-icon");
+  }
+
+  // Apply jQuery UI icon and hover styles to context menus
+  if ($(".g-context-menu").length) {
+    $(".g-context-menu li").addClass("ui-state-default");
+    $(".g-context-menu a").addClass("g-button ui-icon-left");
+    $(".g-context-menu a").prepend("<span class=\"ui-icon\"></span>");
+    $(".g-context-menu a span").each(function() {
+      var iconClass = $(this).parent().attr("class").match(/ui-icon-.[^\s]+/).toString();
+      $(this).addClass(iconClass);
+    });
+  }
+
+  // Remove titles for menu options since we're displaying that text anyway
+  $(".sf-menu a, .sf-menu li").removeAttr("title");
+
+  // Album and search results views
+  if ($("#g-album-grid").length) {
+    // Set equal height for album items and vertically align thumbnails/metadata
+    $(".g-item").equal_heights().gallery_valign();
+    // Store the resulting item height.  Storing this here for the whole grid as opposed to in the
+    // hover event as an attr for each item is more efficient and ensures IE6-8 compatibility.
+    var item_height = $(".g-item").height();
+
+    // Initialize thumbnail hover effect
+    $(".g-item").hover(
+      function() {
+        // Insert a placeholder to hold the item's position in the grid
+        var place_holder = $(this).clone().attr("id", "g-place-holder");
+        $(this).after($(place_holder));
+        // Style and position the hover item
+        var position = $(this).position();
+        $(this).css("top", position.top).css("left", position.left);
+        $(this).addClass("g-hover-item");
+        // Initialize the contextual menu. Note that putting it here delays execution until needed.
+        $(this).gallery_context_menu();
+        // Set the hover item's height.  Use "li a" on the context menu so we get the height of the
+        // collapsed menu and avoid problems with incomplete slideUp/Down animations.
+        $(this).height("auto");
+        $(this).height(Math.max($(this).height(), item_height) +
+                       $(this).find(".g-context-menu li a").height());
+      },
+      function() {
+        // Reset item height and position
+        $(this).height(item_height);
+        $(this).css("top", "").css("left", "");
+        // Remove the placeholder and hover class from the item
+        $(this).removeClass("g-hover-item");
+        $("#g-place-holder").remove();
+      }
+    );
+
+    // Realign any thumbnails that change so that when we rotate a thumb it stays centered.
+    $(".g-item").bind("gallery.change", function() {
+      $(".g-item").each(function() {
+        $(this).height($(this).find("img").height() + 2);
+      });
+      $(".g-item").equal_heights().gallery_valign();
+    });
+  }
+
+  // Photo/Item item view
+  if ($("#g-photo,#g-movie").length) {
+    // Ensure the resized image fits within its container
+    $("#g-photo,#g-movie").gallery_fit_photo();
+
+    // Initialize context menus
+    $("#g-photo,#g-movie").hover(function(){
+      $(this).gallery_context_menu();
+    });
+
+    // Add scroll effect for links to named anchors
+    $.localScroll({
+      queue: true,
+      duration: 1000,
+      hash: true
+    });
+
+    $(this).find(".g-dialog-link").gallery_dialog();
+    $(this).find(".g-ajax-link").gallery_ajax();
+  }
+
+  // Initialize button hover effect
+  $.fn.gallery_hover_init();
+
+});
diff --git a/themes/wind/theme.info b/themes/wind/theme.info
new file mode 100644
index 0000000..b00e56d
--- /dev/null
+++ b/themes/wind/theme.info
@@ -0,0 +1,10 @@
+name = "Gallery Wind"
+description = "A crisp and distinctive theme that uses large fonts and icons for easy navigation and an enjoyable browsing experience."
+version = 1
+author = "Gallery Team"
+site = 1
+admin = 0
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Themes:wind"
+discuss_url = "http://galleryproject.org/forum_theme_wind"
diff --git a/themes/wind/thumbnail.png b/themes/wind/thumbnail.png
new file mode 100755
index 0000000..2c9ee43
Binary files /dev/null and b/themes/wind/thumbnail.png differ
diff --git a/themes/wind/views/album.html.php b/themes/wind/views/album.html.php
new file mode 100644
index 0000000..ca69bda
--- /dev/null
+++ b/themes/wind/views/album.html.php
@@ -0,0 +1,47 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? // @todo Set hover on AlbumGrid list items for guest users ?>
+<div id="g-info">
+  <?= $theme->album_top() ?>
+  <h1><?= html::purify($item->title) ?></h1>
+  <div class="g-description"><?= nl2br(html::purify($item->description)) ?></div>
+</div>
+
+<ul id="g-album-grid" class="ui-helper-clearfix">
+<? if (count($children)): ?>
+  <? foreach ($children as $i => $child): ?>
+    <? if ($child->is_album()): ?>
+      <? $item_class = "g-album"; ?>
+    <? elseif ($child->is_movie()): ?>
+      <? $item_class = "g-movie"; ?>
+    <? else: ?>
+      <? $item_class = "g-photo"; ?>
+    <? endif ?>
+  <li id="g-item-id-<?= $child->id ?>" class="g-item <?= $item_class ?>">
+    <?= $theme->thumb_top($child) ?>
+    <a href="<?= $child->url() ?>">
+      <? if ($child->has_thumb()): ?>
+      <?= $child->thumb_img(array("class" => "g-thumbnail")) ?>
+      <? endif ?>
+    </a>
+    <?= $theme->thumb_bottom($child) ?>
+    <?= $theme->context_menu($child, "#g-item-id-{$child->id} .g-thumbnail") ?>
+    <h2><span class="<?= $item_class ?>"></span>
+      <a href="<?= $child->url() ?>"><?= html::purify($child->title) ?></a></h2>
+    <ul class="g-metadata">
+      <?= $theme->thumb_info($child) ?>
+    </ul>
+  </li>
+  <? endforeach ?>
+<? else: ?>
+  <? if ($user->admin || access::can("add", $item)): ?>
+  <? $addurl = url::site("uploader/index/$item->id") ?>
+  <li><?= t("There aren't any photos here yet! <a %attrs>Add some</a>.",
+            array("attrs" => html::mark_clean("href=\"$addurl\" class=\"g-dialog-link\""))) ?></li>
+  <? else: ?>
+  <li><?= t("There aren't any photos here yet!") ?></li>
+  <? endif; ?>
+<? endif; ?>
+</ul>
+<?= $theme->album_bottom() ?>
+
+<?= $theme->paginator() ?>
diff --git a/themes/wind/views/block.html.php b/themes/wind/views/block.html.php
new file mode 100644
index 0000000..699d7c2
--- /dev/null
+++ b/themes/wind/views/block.html.php
@@ -0,0 +1,10 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? if ($anchor): ?>
+<a name="<?= $anchor ?>"></a>
+<? endif ?>
+<div id="<?= $css_id ?>" class="g-block">
+  <h2><?= $title ?></h2>
+  <div class="g-block-content">
+    <?= $content ?>
+  </div>
+</div>
diff --git a/themes/wind/views/dynamic.html.php b/themes/wind/views/dynamic.html.php
new file mode 100644
index 0000000..c8b2fca
--- /dev/null
+++ b/themes/wind/views/dynamic.html.php
@@ -0,0 +1,29 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-album-header">
+  <div id="g-album-header-buttons">
+    <?= $theme->dynamic_top() ?>
+  </div>
+  <h1><?= html::purify($title) ?></h1>
+</div>
+
+<ul id="g-album-grid" class="ui-helper-clearfix">
+  <? foreach ($children as $i => $child): ?>
+  <li class="g-item <?= $child->is_album() ? "g-album" : "" ?>">
+    <?= $theme->thumb_top($child) ?>
+    <a href="<?= $child->url() ?>">
+      <img id="g-photo-id-<?= $child->id ?>" class="g-thumbnail"
+           alt="photo" src="<?= $child->thumb_url() ?>"
+           width="<?= $child->thumb_width ?>"
+           height="<?= $child->thumb_height ?>" />
+    </a>
+    <h2><?= html::purify($child->title) ?></h2>
+    <?= $theme->thumb_bottom($child) ?>
+    <ul class="g-metadata">
+      <?= $theme->thumb_info($child) ?>
+    </ul>
+  </li>
+  <? endforeach ?>
+</ul>
+<?= $theme->dynamic_bottom() ?>
+
+<?= $theme->paginator() ?>
diff --git a/themes/wind/views/movie.html.php b/themes/wind/views/movie.html.php
new file mode 100644
index 0000000..158857d
--- /dev/null
+++ b/themes/wind/views/movie.html.php
@@ -0,0 +1,19 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-item">
+  <?= $theme->photo_top() ?>
+
+  <?= $theme->paginator() ?>
+
+  <div id="g-movie" class="ui-helper-clearfix">
+    <?= $theme->resize_top($item) ?>
+    <?= $item->movie_img(array("class" => "g-movie", "id" => "g-item-id-{$item->id}")) ?>
+    <?= $theme->resize_bottom($item) ?>
+  </div>
+
+  <div id="g-info">
+    <h1><?= html::purify($item->title) ?></h1>
+    <div><?= nl2br(html::purify($item->description)) ?></div>
+  </div>
+
+  <?= $theme->photo_bottom() ?>
+</div>
diff --git a/themes/wind/views/no_sidebar.html.php b/themes/wind/views/no_sidebar.html.php
new file mode 100644
index 0000000..58c5725
--- /dev/null
+++ b/themes/wind/views/no_sidebar.html.php
@@ -0,0 +1,11 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul class="g-message-block">
+  <li class="g-warning">
+  <? if (block_manager::get_active("site_sidebar")): ?>
+  <?= t("Active sidebar blocks have no content.") ?>
+  <? else: ?>
+  <?= t("No active sidebar blocks.") ?>
+  <? endif ?>
+  <a href="<?= url::site("admin/sidebar") ?>"><?= t("configure blocks") ?></a>
+  </li>
+</ul>
diff --git a/themes/wind/views/page.html.php b/themes/wind/views/page.html.php
new file mode 100644
index 0000000..e1a5304
--- /dev/null
+++ b/themes/wind/views/page.html.php
@@ -0,0 +1,153 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" <?= $theme->html_attributes() ?> xml:lang="en" lang="en">
+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+    <? $theme->start_combining("script,css") ?>
+    <title>
+      <? if ($page_title): ?>
+        <?= $page_title ?>
+      <? else: ?>
+        <? if ($theme->item()): ?>
+          <?= html::purify($theme->item()->title) ?>
+        <? elseif ($theme->tag()): ?>
+          <?= t("Photos tagged with %tag_title", array("tag_title" => $theme->tag()->name)) ?>
+        <? else: /* Not an item, not a tag, no page_title specified.  Help! */ ?>
+          <?= html::purify(item::root()->title) ?>
+        <? endif ?>
+      <? endif ?>
+    </title>
+    <link rel="shortcut icon"
+          href="<?= url::file(module::get_var("gallery", "favicon_url")) ?>"
+          type="image/x-icon" />
+    <link rel="apple-touch-icon-precomposed"
+          href="<?= url::file(module::get_var("gallery", "apple_touch_icon_url")) ?>" />
+    <? if ($theme->page_type == "collection"): ?>
+    <? if (($thumb_proportion = $theme->thumb_proportion($theme->item())) != 1): ?>
+        <? $new_width = round($thumb_proportion * 213) ?>
+        <? $new_height = round($thumb_proportion * 240) ?>
+        <style type="text/css">
+        .g-view #g-content #g-album-grid .g-item {
+          width: <?= $new_width ?>px;
+          height: <?= $new_height ?>px;
+          /* <?= $thumb_proportion ?> */
+        }
+        </style>
+      <? endif ?>
+    <? endif ?>
+
+    <?= $theme->script("json2-min.js") ?>
+    <?= $theme->script("jquery.js") ?>
+    <?= $theme->script("jquery.form.js") ?>
+    <?= $theme->script("jquery-ui.js") ?>
+    <?= $theme->script("gallery.common.js") ?>
+    <? /* MSG_CANCEL is required by gallery.dialog.js */ ?>
+    <script type="text/javascript">
+    var MSG_CANCEL = <?= t('Cancel')->for_js() ?>;
+    </script>
+    <?= $theme->script("gallery.ajax.js") ?>
+    <?= $theme->script("gallery.dialog.js") ?>
+    <?= $theme->script("superfish/js/superfish.js") ?>
+    <?= $theme->script("jquery.localscroll.js") ?>
+
+    <? /* These are page specific but they get combined */ ?>
+    <? if ($theme->page_subtype == "photo"): ?>
+    <?= $theme->script("jquery.scrollTo.js") ?>
+    <?= $theme->script("gallery.show_full_size.js") ?>
+    <? elseif ($theme->page_subtype == "movie"): ?>
+    <?= $theme->script("flowplayer.js") ?>
+    <? endif ?>
+
+    <?= $theme->head() ?>
+
+    <? /* Theme specific CSS/JS goes last so that it can override module CSS/JS */ ?>
+    <?= $theme->script("ui.init.js") ?>
+    <?= $theme->css("yui/reset-fonts-grids.css") ?>
+    <?= $theme->css("superfish/css/superfish.css") ?>
+    <?= $theme->css("themeroller/ui.base.css") ?>
+    <?= $theme->css("screen.css") ?>
+    <? if (locales::is_rtl()): ?>
+    <?= $theme->css("screen-rtl.css") ?>
+    <? endif; ?>
+    <!--[if lte IE 8]>
+    <link rel="stylesheet" type="text/css" href="<?= $theme->url("css/fix-ie.css") ?>"
+          media="screen,print,projection" />
+    <![endif]-->
+
+    <!-- LOOKING FOR YOUR CSS? It's all been combined into the link below -->
+    <?= $theme->get_combined("css") ?>
+
+    <!-- LOOKING FOR YOUR JAVASCRIPT? It's all been combined into the link below -->
+    <?= $theme->get_combined("script") ?>
+  </head>
+
+  <body <?= $theme->body_attributes() ?>>
+    <?= $theme->page_top() ?>
+    <div id="doc4" class="yui-t5 g-view">
+      <?= $theme->site_status() ?>
+      <div id="g-header" class="ui-helper-clearfix">
+        <div id="g-banner">
+          <? if ($header_text = module::get_var("gallery", "header_text")): ?>
+          <?= $header_text ?>
+          <? else: ?>
+          <a id="g-logo" class="g-left" href="<?= item::root()->url() ?>" title="<?= t("go back to the Gallery home")->for_html_attr() ?>">
+            <img width="107" height="48" alt="<?= t("Gallery logo: Your photos on your web site")->for_html_attr() ?>" src="<?= url::file("lib/images/logo.png") ?>" />
+          </a>
+          <? endif ?>
+          <?= $theme->user_menu() ?>
+          <?= $theme->header_top() ?>
+
+          <!-- hide the menu until after the page has loaded, to minimize menu flicker -->
+          <div id="g-site-menu" style="visibility: hidden">
+            <?= $theme->site_menu($theme->item() ? "#g-item-id-{$theme->item()->id}" : "") ?>
+          </div>
+          <script type="text/javascript"> $(document).ready(function() { $("#g-site-menu").css("visibility", "visible"); }) </script>
+
+          <?= $theme->header_bottom() ?>
+        </div>
+
+        <? if (!empty($breadcrumbs)): ?>
+        <ul class="g-breadcrumbs">
+          <? foreach ($breadcrumbs as $breadcrumb): ?>
+           <li class="<?= $breadcrumb->last ? "g-active" : "" ?>
+                      <?= $breadcrumb->first ? "g-first" : "" ?>">
+            <? if (!$breadcrumb->last): ?> <a href="<?= $breadcrumb->url ?>"><? endif ?>
+            <?= html::clean(text::limit_chars($breadcrumb->title, module::get_var("gallery", "visible_title_length"))) ?>
+            <? if (!$breadcrumb->last): ?></a><? endif ?>
+           </li>
+          <? endforeach ?>
+        </ul>
+        <? endif ?>
+      </div>
+      <div id="bd">
+        <div id="yui-main">
+          <div class="yui-b">
+            <div id="g-content" class="yui-g">
+              <?= $theme->messages() ?>
+              <?= $content ?>
+            </div>
+          </div>
+        </div>
+        <div id="g-sidebar" class="yui-b">
+          <? if (!in_array($theme->page_subtype, array("login", "error"))): ?>
+          <?= new View("sidebar.html") ?>
+          <? endif ?>
+        </div>
+      </div>
+      <div id="g-footer" class="ui-helper-clearfix">
+        <?= $theme->footer() ?>
+        <? if ($footer_text = module::get_var("gallery", "footer_text")): ?>
+        <?= $footer_text ?>
+        <? endif ?>
+
+        <? if (module::get_var("gallery", "show_credits")): ?>
+        <ul id="g-credits" class="g-inline">
+          <?= $theme->credits() ?>
+        </ul>
+        <? endif ?>
+      </div>
+    </div>
+    <?= $theme->page_bottom() ?>
+  </body>
+</html>
diff --git a/themes/wind/views/paginator.html.php b/themes/wind/views/paginator.html.php
new file mode 100644
index 0000000..5034c96
--- /dev/null
+++ b/themes/wind/views/paginator.html.php
@@ -0,0 +1,87 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?
+// This is a generic paginator for album, photo and movie pages.  Depending on the page type,
+// there are different sets of variables available.  With this data, you can make a paginator
+// that lets you say "You're viewing photo 5 of 35", or "You're viewing photos 10 - 18 of 37"
+// for album views.
+//
+// Available variables for all page types:
+//   $page_type               - "collection", "item", or "other"
+//   $page_subtype            - "album", "movie", "photo", "tag", etc.
+//   $previous_page_url       - the url to the previous page, if there is one
+//   $next_page_url           - the url to the next page, if there is one
+//   $total                   - the total number of photos in this album
+//
+// Available for the "collection" page types:
+//   $page                    - what page number we're on
+//   $max_pages               - the maximum page number
+//   $page_size               - the page size
+//   $first_page_url          - the url to the first page, or null if we're on the first page
+//   $last_page_url           - the url to the last page, or null if we're on the last page
+//   $first_visible_position  - the position number of the first visible photo on this page
+//   $last_visible_position   - the position number of the last visible photo on this page
+//
+// Available for "item" page types:
+//   $position                - the position number of this photo
+//
+?>
+
+<ul class="g-paginator ui-helper-clearfix">
+  <li class="g-first">
+  <? if ($page_type == "collection"): ?>
+    <? if (isset($first_page_url)): ?>
+      <a href="<?= $first_page_url ?>" class="g-button ui-icon-left ui-state-default ui-corner-all">
+        <span class="ui-icon ui-icon-seek-first"></span><?= t("First") ?></a>
+    <? else: ?>
+      <a class="g-button ui-icon-left ui-state-disabled ui-corner-all">
+        <span class="ui-icon ui-icon-seek-first"></span><?= t("First") ?></a>
+    <? endif ?>
+  <? endif ?>
+
+  <? if (isset($previous_page_url)): ?>
+    <a href="<?= $previous_page_url ?>" class="g-button ui-icon-left ui-state-default ui-corner-all">
+      <span class="ui-icon ui-icon-seek-prev"></span><?= t("Previous") ?></a>
+  <? else: ?>
+    <a class="g-button ui-icon-left ui-state-disabled ui-corner-all">
+      <span class="ui-icon ui-icon-seek-prev"></span><?= t("Previous") ?></a>
+  <? endif ?>
+  </li>
+
+  <li class="g-info">
+    <? if ($total): ?>
+      <? if ($page_type == "collection"): ?>
+        <?= /* @todo This message isn't easily localizable */
+            t2("Photo %from_number of %count",
+               "Photos %from_number - %to_number of %count",
+               $total,
+               array("from_number" => $first_visible_position,
+                     "to_number" => $last_visible_position,
+                     "count" => $total)) ?>
+      <? else: ?>
+        <?= t("%position of %total", array("position" => $position, "total" => $total)) ?>
+      <? endif ?>
+    <? else: ?>
+      <?= t("No photos") ?>
+    <? endif ?>
+  </li>
+
+  <li class="g-text-right">
+  <? if (isset($next_page_url)): ?>
+    <a href="<?= $next_page_url ?>" class="g-button ui-icon-right ui-state-default ui-corner-all">
+      <span class="ui-icon ui-icon-seek-next"></span><?= t("Next") ?></a>
+  <? else: ?>
+    <a class="g-button ui-state-disabled ui-icon-right ui-corner-all">
+      <span class="ui-icon ui-icon-seek-next"></span><?= t("Next") ?></a>
+  <? endif ?>
+
+  <? if ($page_type == "collection"): ?>
+    <? if (isset($last_page_url)): ?>
+      <a href="<?= $last_page_url ?>" class="g-button ui-icon-right ui-state-default ui-corner-all">
+        <span class="ui-icon ui-icon-seek-end"></span><?= t("Last") ?></a>
+    <? else: ?>
+      <a class="g-button ui-state-disabled ui-icon-right ui-corner-all">
+        <span class="ui-icon ui-icon-seek-end"></span><?= t("Last") ?></a>
+    <? endif ?>
+  <? endif ?>
+  </li>
+</ul>
diff --git a/themes/wind/views/photo.html.php b/themes/wind/views/photo.html.php
new file mode 100644
index 0000000..b42ab98
--- /dev/null
+++ b/themes/wind/views/photo.html.php
@@ -0,0 +1,51 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+
+<? if (access::can("view_full", $theme->item())): ?>
+<!-- Use javascript to show the full size as an overlay on the current page -->
+<script type="text/javascript">
+  $(document).ready(function() {
+    full_dims = [<?= $theme->item()->width ?>, <?= $theme->item()->height ?>];
+    $(".g-fullsize-link").click(function() {
+      $.gallery_show_full_size(<?= html::js_string($theme->item()->file_url()) ?>, full_dims[0], full_dims[1]);
+      return false;
+    });
+
+    // After the image is rotated or replaced we have to reload the image dimensions
+    // so that the full size view isn't distorted.
+    $("#g-photo").bind("gallery.change", function() {
+      $.ajax({
+        url: "<?= url::site("items/dimensions/" . $theme->item()->id) ?>",
+        dataType: "json",
+        success: function(data, textStatus) {
+          full_dims = data.full;
+        }
+      });
+    });
+  });
+</script>
+<? endif ?>
+
+<div id="g-item">
+  <?= $theme->photo_top() ?>
+
+  <?= $theme->paginator() ?>
+
+  <div id="g-photo">
+    <?= $theme->resize_top($item) ?>
+    <? if (access::can("view_full", $item)): ?>
+    <a href="<?= $item->file_url() ?>" class="g-fullsize-link" title="<?= t("View full size")->for_html_attr() ?>">
+      <? endif ?>
+      <?= $item->resize_img(array("id" => "g-item-id-{$item->id}", "class" => "g-resize")) ?>
+      <? if (access::can("view_full", $item)): ?>
+    </a>
+    <? endif ?>
+    <?= $theme->resize_bottom($item) ?>
+  </div>
+
+  <div id="g-info">
+    <h1><?= html::purify($item->title) ?></h1>
+    <div><?= nl2br(html::purify($item->description)) ?></div>
+  </div>
+
+  <?= $theme->photo_bottom() ?>
+</div>
diff --git a/themes/wind/views/sidebar.html.php b/themes/wind/views/sidebar.html.php
new file mode 100644
index 0000000..086d135
--- /dev/null
+++ b/themes/wind/views/sidebar.html.php
@@ -0,0 +1,16 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?= $theme->sidebar_top() ?>
+<div id="g-view-menu" class="g-buttonset ui-helper-clearfix">
+  <? if ($page_subtype == "album"):?>
+    <?= $theme->album_menu() ?>
+  <? elseif ($page_subtype == "photo") : ?>
+    <?= $theme->photo_menu() ?>
+  <? elseif ($page_subtype == "movie") : ?>
+    <?= $theme->movie_menu() ?>
+  <? elseif ($page_subtype == "tag") : ?>
+    <?= $theme->tag_menu() ?>
+  <? endif ?>
+</div>
+
+<?= $theme->sidebar_blocks() ?>
+<?= $theme->sidebar_bottom() ?>
-- 
cgit v1.0-28-g1787

